My Linear Analysis
Machine Learning
2020년 기준 1인당 GDP와 삶의 만족도 관계 선형 분석
기본설정
# 파이썬 버전 ≥ 3.5
import sys
assert sys.version_info >= (3, 5)
# Scikit-Learn 버전 ≥0.20
import sklearn
assert sklearn.__version__ >= "0.20"
주피터 노트북에서 그래프를 깔금하게 그리기 위한 설정
%matplotlib inline
import matplotlib as mpl
mpl.rc('axes', labelsize=14)
mpl.rc('xtick', labelsize=12)
mpl.rc('ytick', labelsize=12)
필요한 모듈 불러오기
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
그래프 저장 함수 선언
import os
# 그래프 저장을 디렉토리 지정
PROJECT_ROOT_DIR = "."
CHAPTER_ID = "fundamentals"
IMAGES_PATH = os.path.join(PROJECT_ROOT_DIR, "images", CHAPTER_ID)
os.makedirs(IMAGES_PATH, exist_ok=True)
# 그래프 저장 함수 선언
def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
print("Saving figure", fig_id)
if tight_layout:
plt.tight_layout()
plt.savefig(path, format=fig_extension, dpi=resolution)
무작위 시드 지정
import numpy as np
np.random.seed(42)
데이터 다운로드
데이터 경로 설정
datapath = os.path.join("datasets", "lifesat", "")
데이터 다운로드 (oecd_bli_2020.csv, gdp_per_capita_2020.xlsx)
import urllib.request
DOWNLOAD_ROOT = "https://raw.githubusercontent.com/codingalzi/handson-ml/master/"
os.makedirs(datapath, exist_ok=True)
for filename in ("oecd_bli_2020.csv", "gdp_per_capita_2020.xlsx"):
print("다운로드:", filename)
url = DOWNLOAD_ROOT + "notebooks/datasets/lifesat/" + filename
urllib.request.urlretrieve(url, datapath + filename)
다운로드: oecd_bli_2020.csv
다운로드: gdp_per_capita_2020.xlsx
데이터 적재와 준비
삶의 만족도 데이터 적재와 준비
oecd_bli = pd.read_csv(datapath + "oecd_bli_2020.csv", thousands=',')
oecd_bli = oecd_bli[oecd_bli["INEQUALITY"]=="TOT"]
oecd_bli = oecd_bli.pivot(index="Country", columns="Indicator", values="Value")
# 알파벳 순으로 첫 5개 국가 데이터 보여주기
oecd_bli.head()
Indicator | Air pollution | Dwellings without basic facilities | Educational attainment | Employees working very long hours | Employment rate | Feeling safe walking alone at night | Homicide rate | Household net adjusted disposable income | Household net wealth | Housing expenditure | Labour market insecurity | Life expectancy | Life satisfaction | Long-term unemployment rate | Personal earnings | Quality of support network | Rooms per person | Self-reported health | Stakeholder engagement for developing regulations | Student skills | Time devoted to leisure and personal care | Voter turnout | Water quality | Years in education |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Country | ||||||||||||||||||||||||
Australia | 5.0 | NaN | 81.0 | 13.04 | 73.0 | 63.5 | 1.1 | 32759.0 | 427064.0 | 20.0 | 5.4 | 82.5 | 7.3 | 1.31 | 49126.0 | 95.0 | NaN | 85.0 | 2.7 | 502.0 | 14.35 | 91.0 | 93.0 | 21.0 |
Austria | 16.0 | 0.9 | 85.0 | 6.66 | 72.0 | 80.6 | 0.5 | 33541.0 | 308325.0 | 21.0 | 3.5 | 81.7 | 7.1 | 1.84 | 50349.0 | 92.0 | 1.6 | 70.0 | 1.3 | 492.0 | 14.55 | 80.0 | 92.0 | 17.0 |
Belgium | 15.0 | 1.9 | 77.0 | 4.75 | 63.0 | 70.1 | 1.0 | 30364.0 | 386006.0 | 21.0 | 3.7 | 81.5 | 6.9 | 3.54 | 49675.0 | 91.0 | 2.2 | 74.0 | 2.0 | 503.0 | 15.70 | 89.0 | 84.0 | 19.3 |
Brazil | 10.0 | 6.7 | 49.0 | 7.13 | 61.0 | 35.6 | 26.7 | NaN | NaN | NaN | NaN | 74.8 | 6.4 | NaN | NaN | 90.0 | NaN | NaN | 2.2 | 395.0 | NaN | 79.0 | 73.0 | 16.2 |
Canada | 7.0 | 0.2 | 91.0 | 3.69 | 73.0 | 82.2 | 1.3 | 30854.0 | 423849.0 | 22.0 | 6.0 | 81.9 | 7.4 | 0.77 | 47622.0 | 93.0 | 2.6 | 88.0 | 2.9 | 523.0 | 14.56 | 68.0 | 91.0 | 17.3 |
oecd 2020년도 삶의 만족도 데이터 확인
oecd_bli["Life satisfaction"].head()
Country
Australia 7.3
Austria 7.1
Belgium 6.9
Brazil 6.4
Canada 7.4
Name: Life satisfaction, dtype: float64
1인당 GDP 데이터 적재와 준비
gdp_per_capita = pd.read_excel(datapath+"gdp_per_capita_2020.xlsx", thousands=',', na_values="n/a")
gdp_per_capita.rename(columns={2020: "GDP per capita"}, inplace=True) # "2020" 컬럼 이름을 "GDP per capita" 로 변경
gdp_per_capita.set_index("Country", inplace=True)
# 알파벳 순으로 첫 5개 국가 GDP 정보 확인
gdp_per_capita.head()
Subject Descriptor | Units | Scale | Country/Series-specific Notes | GDP per capita | Estimates Start After | |
---|---|---|---|---|---|---|
Country | ||||||
Afghanistan | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 499.441 | 2019.0 |
Albania | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 4898.277 | 2018.0 |
Algeria | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 3331.076 | 2019.0 |
Angola | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 2021.310 | 2017.0 |
Antigua and Barbuda | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 14158.571 | 2011.0 |
두 데이터의 병합 (oecd 삶의 만족도, 1인당 GDP)
full_country_stats = pd.merge(left=oecd_bli, right=gdp_per_capita, left_index=True, right_index=True)
1인당 GDP 기준으로 오름차순으로 국가를 정렬시킵니다.
full_country_stats.sort_values(by="GDP per capita", inplace=True) # 1인당 GDP 기준으로 정렬
1인당 GDP 기준 하위 3개 국가는 남아공, 콜롬비아, 브라질입니다.
full_country_stats.head(3)
Air pollution | Dwellings without basic facilities | Educational attainment | Employees working very long hours | Employment rate | Feeling safe walking alone at night | Homicide rate | Household net adjusted disposable income | Household net wealth | Housing expenditure | Labour market insecurity | Life expectancy | Life satisfaction | Long-term unemployment rate | Personal earnings | Quality of support network | Rooms per person | Self-reported health | Stakeholder engagement for developing regulations | Student skills | Time devoted to leisure and personal care | Voter turnout | Water quality | Years in education | Subject Descriptor | Units | Scale | Country/Series-specific Notes | GDP per capita | Estimates Start After | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Country | ||||||||||||||||||||||||||||||
South Africa | 22.0 | 37.0 | 73.0 | 18.12 | 43.0 | 36.1 | 13.7 | NaN | NaN | 18.0 | NaN | 57.5 | 4.7 | 16.46 | NaN | 88.0 | NaN | NaN | NaN | NaN | 14.92 | 73.0 | 67.0 | NaN | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 4735.747 | 2019.0 |
Colombia | 10.0 | 23.9 | 54.0 | 26.56 | 67.0 | 44.4 | 24.5 | NaN | NaN | 17.0 | NaN | 76.2 | 6.3 | 0.79 | NaN | 89.0 | 1.2 | NaN | 1.4 | 410.0 | NaN | 53.0 | 75.0 | 14.1 | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 5207.238 | 2019.0 |
Brazil | 10.0 | 6.7 | 49.0 | 7.13 | 61.0 | 35.6 | 26.7 | NaN | NaN | NaN | NaN | 74.8 | 6.4 | NaN | NaN | 90.0 | NaN | NaN | 2.2 | 395.0 | NaN | 79.0 | 73.0 | 16.2 | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 6450.451 | 2019.0 |
1인당 GDP 기준 상위 3개 아일랜드, 스위스, 룩셈부르크 입니다.
full_country_stats.tail(3)
Air pollution | Dwellings without basic facilities | Educational attainment | Employees working very long hours | Employment rate | Feeling safe walking alone at night | Homicide rate | Household net adjusted disposable income | Household net wealth | Housing expenditure | Labour market insecurity | Life expectancy | Life satisfaction | Long-term unemployment rate | Personal earnings | Quality of support network | Rooms per person | Self-reported health | Stakeholder engagement for developing regulations | Student skills | Time devoted to leisure and personal care | Voter turnout | Water quality | Years in education | Subject Descriptor | Units | Scale | Country/Series-specific Notes | GDP per capita | Estimates Start After | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Country | ||||||||||||||||||||||||||||||
Ireland | 7.0 | 1.0 | 82.0 | 5.25 | 67.0 | 75.9 | 0.7 | 25310.0 | 217130.0 | 20.0 | 7.8 | 81.8 | 7.0 | 3.23 | 47653.0 | 95.0 | 2.1 | 83.0 | 1.3 | 509.0 | NaN | 65.0 | 85.0 | 18.1 | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 79668.502 | 2019.0 |
Switzerland | 15.0 | 0.1 | 88.0 | 0.37 | 80.0 | 85.3 | 0.6 | 37466.0 | NaN | 22.0 | NaN | 83.7 | 7.5 | 1.82 | 62283.0 | 93.0 | 1.9 | 78.0 | 2.3 | 506.0 | NaN | 49.0 | 95.0 | 17.5 | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 81867.462 | 2019.0 |
Luxembourg | 12.0 | 0.5 | 77.0 | 3.82 | 66.0 | 75.8 | 0.6 | 39264.0 | 769053.0 | 21.0 | 1.7 | 82.8 | 6.9 | 2.35 | 63062.0 | 93.0 | 1.9 | 69.0 | 1.7 | 483.0 | NaN | 91.0 | 84.0 | 15.1 | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 109602.322 | 2018.0 |
데이터 분석
시작하기 전에 7개 제외 국가
- Columbia(콜롬비아)
- Brazil(브라질)
- Mexico(멕시코)
- Chille(칠레)
- Ireland(아일랜드)
- Switzerland(스위스)
- Luxembourg(룩셈부르크)
# 7개 국가의 행 인덱스를 전체 인덱스 집합에서 제거
remove_indices = [1, 2, 4, 6, 37, 38, 39]
keep_indices = list(set(range(40)) - set(remove_indices))
# 7개 국가를 제외한 국가들의 1인당 GDP와 삶의 만족도 데이터
sample_data = full_country_stats[["GDP per capita", 'Life satisfaction']].iloc[keep_indices]
# 제외된 7개 국가의 1인당 GGP와 삶의 만족도 데이터
missing_data = full_country_stats[["GDP per capita", 'Life satisfaction']].iloc[remove_indices]
제외된 7개 국가의 데이터를 제외한 국가들의 1인당 GDP와 삶의 만족도 사이의 관계를 산점도로 나타냅니다.
다만 아래에 언급된 5개 국가는 빨간색 점으로 표시됩니다.
- 헝가리(Hungary)
- 대한민국(Korea)
- 프랑스(France)
- 호주(Australia)
- 미국(United States)
# 7개 국가를 제외한 국가들의 데이터 산점도
sample_data.plot(kind='scatter', x="GDP per capita", y='Life satisfaction', figsize=(5,3))
plt.axis([0, 65000, 0, 10])
# 언급된 5개 국가명 명기 좌표
position_text = {
"Hungary": (8000, 1),
"Korea": (26000, 1.7),
"France": (34000, 2.4),
"Australia": (44000, 3.0),
"United States": (60000, 3.8),
}
# 5개 국가는 좌표를 이용하여 빨강색 점으로 표기
for country, pos_text in position_text.items():
pos_data_x, pos_data_y = sample_data.loc[country]
# 5개 국가명 표기
country = "U.S." if country == "United States" else country
plt.annotate(country, xy=(pos_data_x, pos_data_y), xytext=pos_text,
arrowprops=dict(facecolor='black', width=0.5, shrink=0.1, headwidth=5))
# 5개 국가 산점도 그리기
plt.plot(pos_data_x, pos_data_y, "ro")
plt.xlabel("GDP per capita (USD)")
save_fig('money_happy_scatterplot')
plt.show()
Saving figure money_happy_scatterplot
언급된 5개 국가의 1인당 GDP와 삶의 만족도를 데이터에서 직접 확인하면 다음과 같습니다.
sample_data.loc[list(position_text.keys())]
GDP per capita | Life satisfaction | |
---|---|---|
Country | ||
Hungary | 15372.885 | 5.6 |
Korea | 30644.427 | 5.9 |
France | 39257.434 | 6.5 |
Australia | 51885.466 | 7.3 |
United States | 63051.398 | 6.9 |
선형 회귀 모델
위 산점도에 따르면 1인당 GDP와 삶의 만족도가 어느 정도 선형 관계에 있는 것처럼 보입니다.
아래 도표에서 그려진 세 개의 직선 중에서 파랑색 실선이 선형 관계를 가장 적절하게 나타냅니다.
import numpy as np
sample_data.plot(kind='scatter', x="GDP per capita", y='Life satisfaction', figsize=(5,3))
plt.xlabel("GDP per capita (USD)")
plt.axis([0, 60000, 0, 10])
X=np.linspace(0, 60000, 1000)
plt.plot(X, 2*X/100000, "r")
plt.text(40000, 2.7, r"$\theta_0 = 0$", fontsize=14, color="r")
plt.text(40000, 1.8, r"$\theta_1 = 2 \times 10^{-5}$", fontsize=14, color="r")
plt.plot(X, 8 - 5*X/100000, "g")
plt.text(5000, 9.1, r"$\theta_0 = 8$", fontsize=14, color="g")
plt.text(5000, 8.2, r"$\theta_1 = -5 \times 10^{-5}$", fontsize=14, color="g")
plt.plot(X, 5 + 4*X/100000, "b")
plt.text(5000, 3.5, r"$\theta_0 = 5$", fontsize=14, color="b")
plt.text(5000, 2.6, r"$\theta_1 = 4 \times 10^{-5}$", fontsize=14, color="b")
save_fig('tweaking_model_params_plot')
plt.show()
Saving figure tweaking_model_params_plot
선형회귀 모델 훈련
- 삶의만족도 = 𝜃0 + 𝜃1 × 1인당GDP
- 훈련 데이터넷 지정
- 특성 데이터: 1인당 GDP
- 타깃 데이터: 삶의 만족도
from sklearn import linear_model
# 선형회귀 모델 지정
lin1 = linear_model.LinearRegression()
# 훈련 데이터셋 지정
Xsample = np.c_[sample_data["GDP per capita"]]
ysample = np.c_[sample_data["Life satisfaction"]]
# 모델 훈련
lin1.fit(Xsample, ysample)
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)
훈련된 모델이 알아낸 최적 선형 모델의 절편과 기울기는 아래 두 속성에 저장합니다.
- intercept_[0]: 직선의 절편
- coef_[0]: 직선의 기울기
# 예측된 최적의 직선에 대한 정보: 절편과 기울기
t0, t1 = lin1.intercept_[0], lin1.coef_[0][0]
t0, t1
(5.071121853750363, 4.1410177424136694e-05)
2020년에서 구해진 절편을 이용하여 산점도와 함께 기울기를 나타냅니다.
# 산점도
sample_data.plot(kind='scatter', x="GDP per capita", y='Life satisfaction', figsize=(5,3))
plt.xlabel("GDP per capita (USD)")
plt.axis([0, 60000, 0, 10])
# 직선 그리기
X=np.linspace(0, 60000, 1000)
plt.plot(X, t0 + t1*X, "b")
# 직선의 절편과 기울기 정보 명시
plt.text(5000, 3.1, r"$\theta_0 = 5.07$", fontsize=14, color="b")
plt.text(5000, 2.2, r"$\theta_1 = 4.14 \times 10^{-5}$", fontsize=14, color="b")
save_fig('best_fit_model_plot')
plt.show()
Saving figure best_fit_model_plot
훈련 모델 활용
훈련된 모델을 이용하여 한 국가의 삶의 만족도를 1인당 GDP를 이용하여 예측한다. 예를 들어, 키프러스(Cyprus) 1인당 GDP만 다음과 같이 알려져 있을 때 키프러스 국민의 삶의 만족도를 예측한다.
- 2020년 키프러스 1인당 GDP: 26240
cyprus_gdp_per_capita = gdp_per_capita.loc["Cyprus"]["GDP per capita"]
print(cyprus_gdp_per_capita)
26240.048
키프러스 국민의 삶의 만족도는 2020년 기준으로 6.16으로 보입니다.
cyprus_predicted_life_satisfaction = lin1.predict([[cyprus_gdp_per_capita]])[0][0]
cyprus_predicted_life_satisfaction
6.157726897048226
아래 도표에서 확인할 수 있듯이 예측값은 정확하게 앞서 확인한 최적의 직선 위에 위치합니다.
sample_data.plot(kind='scatter', x="GDP per capita", y='Life satisfaction', figsize=(5,3), s=1)
plt.xlabel("GDP per capita (USD)")
# 예측된 최적의 직선
X=np.linspace(0, 60000, 1000)
plt.plot(X, t0 + t1*X, "b")
plt.axis([0, 60000, 0, 10])
plt.text(5000, 7.5, r"$\theta_0 = 5.07$", fontsize=14, color="b")
plt.text(5000, 6.6, r"$\theta_1 = 4.14 \times 10^{-5}$", fontsize=14, color="b")
# 키프러스에 대한 삶의 만족도 예측값
# 빨간 점선 그리기
plt.plot([cyprus_gdp_per_capita, cyprus_gdp_per_capita], [0, cyprus_predicted_life_satisfaction], "r--")
plt.text(30000, 5.0, r"Prediction = 6.16", fontsize=14, color="b")
# 예측 지점 좌표 찍기(빨간색)
plt.plot(cyprus_gdp_per_capita, cyprus_predicted_life_satisfaction, "ro")
save_fig('cyprus_prediction_plot')
plt.show()
Saving figure cyprus_prediction_plot
대표성이 없는 훈련 데이터
대표성이 없는 데이터 7가지를 포함해봅니다.
- Columbia(콜롬비아)
- Brazil(브라질)
- Mexico(멕시코)
- Chille(칠레)
- Ireland(아일랜드)
- Switzerland(스위스)
- Luxembourg(룩셈부르크)
missing_data
GDP per capita | Life satisfaction | |
---|---|---|
Country | ||
Colombia | 5207.238 | 6.3 |
Brazil | 6450.451 | 6.4 |
Mexico | 8069.104 | 6.5 |
Chile | 12612.322 | 6.5 |
Ireland | 79668.502 | 7.0 |
Switzerland | 81867.462 | 7.5 |
Luxembourg | 109602.322 | 6.9 |
아래 좌표는 7개 국가명을 아래 도표에서 표기할 때 사용할 좌표입니다.
position_text2 = {
"Colombia": (1000, 9.0),
"Brazil": (11000, 9.0),
"Mexico": (25000, 9.0),
"Chile": (35000, 9.0),
"Ireland": (60000, 3),
"Switzerland": (72000, 3.0),
"Luxembourg": (90000, 3.0),
}
7개 국가를 포함한 전체 훈련 데이터셋을 이용하여 훈련한 결과를 7개 국가를 제외했을 때의 훈련 결과와 비교합니다.
- 검정 실선: 7개 국가 포함 예측 선형 모델
- 파랑 점선: 7개 국가 제외 예측 선형 모델
결론 : 선형회귀 모델은 1인당 GDP와 삶의 만족도 사이의 관계를 모델링 하기에 부적합니다.
# 7개 국가를 제외한 국가들의 산점도 (파랑색 점)
sample_data.plot(kind='scatter', x="GDP per capita", y='Life satisfaction', figsize=(8,3))
plt.axis([0, 110000, 0, 10])
# 7개 국가 산점도(빨강 점)
for country, pos_text in position_text2.items():
pos_data_x, pos_data_y = missing_data.loc[country]
# 7개 국가명 표기
plt.annotate(country, xy=(pos_data_x, pos_data_y), xytext=pos_text,
arrowprops=dict(facecolor='black', width=0.5, shrink=0.1, headwidth=5))
plt.plot(pos_data_x, pos_data_y, "rs")
# 7개 국가 제외 예측 선형 모델 그래프 (파랑 점선)
X=np.linspace(0, 110000, 1000)
plt.plot(X, t0 + t1*X, "b:")
# 7개 국가 포함 선형회귀 모델 훈련 및 예측
lin_reg_full = linear_model.LinearRegression()
Xfull = np.c_[full_country_stats["GDP per capita"]]
yfull = np.c_[full_country_stats["Life satisfaction"]]
lin_reg_full.fit(Xfull, yfull)
# 7개 국가 포함 예측 선형 모델 그래프(검정 실선)
t0full, t1full = lin_reg_full.intercept_[0], lin_reg_full.coef_[0][0]
X = np.linspace(0, 110000, 1000)
plt.plot(X, t0full + t1full * X, "k")
plt.xlabel("GDP per capita (USD)")
save_fig('representative_training_data_scatterplot')
plt.show()
Saving figure representative_training_data_scatterplot
과대적합과 모델규제
과대 적합
훈련된 모델이 훈련데이터에는 너무나도 잘 맞지만 새로운 데이터에 대해서는 잘 작동하지 않을 때 해당 모델이 훈련데이터에 과대적합되었다고 말한다.
고차항 다항회귀를 이용하여 선형이 아니라 60차 다항식의 그래프로 모델을 예측한다. 결과는 훈련데이터셋에 매우 잘 들어맞지만, 새루운 데이터에 대해 훈련된 모델이 제대로된 예측을 할 수 있을 거라고 믿기는 어렵다. 이런 모델은 일반화가 어렵다라고 말한다.
full_country_stats.plot(kind='scatter', x="GDP per capita", y='Life satisfaction', figsize=(8,3))
plt.axis([0, 110000, 0, 10])
from sklearn import preprocessing
from sklearn import pipeline
poly = preprocessing.PolynomialFeatures(degree=60, include_bias=False)
scaler = preprocessing.StandardScaler()
lin_reg2 = linear_model.LinearRegression()
pipeline_reg = pipeline.Pipeline([('poly', poly), ('scal', scaler), ('lin', lin_reg2)])
pipeline_reg.fit(Xfull, yfull)
curve = pipeline_reg.predict(X[:, np.newaxis])
plt.plot(X, curve)
plt.xlabel("GDP per capita (USD)")
save_fig('overfitting_model_plot')
plt.show()
/usr/local/lib/python3.7/dist-packages/numpy/lib/nanfunctions.py:1544: RuntimeWarning: overflow encountered in multiply
sqr = np.multiply(arr, arr, out=arr)
Saving figure overfitting_model_plot
훈련세트에 잡음이 많이 있거나 데이터셋이 너무 작으면 훈련 과정에서 별로 상관 없는 특성을 이용하려고 시도할 수도 있습니다.
OECD에 속하는 국가 중에서 나라 이름에 영어 알파벳 W가 포함된 아래의 나라의 삶의 만족도가 매우 높은 편입니다.
full_country_stats.loc[[c for c in full_country_stats.index if "W" in c.upper()]]["Life satisfaction"]
Country
New Zealand 7.3
Sweden 7.3
Norway 7.6
Switzerland 7.5
Name: Life satisfaction, dtype: float64
하지만 그렇다해서 나라명에 영어 알파벳 W가 포함된 모든 나라의 삶의 만족도가 높다고 결론 지을 수는 없습니다.
실제로 영어 알파벳 W를 포함한 국가 중에 여러 국가의 1인당 GDP가 아래 코드에서 볼 수 있듯이 매우 낮습니다.
예를 들어, 루완다(Rwanda), 짐바브웨(Zimbabwe) 등의 국가의 삶의 만족도를 그럼에도 불구하고 매우 높다고 말할 수는 없습니다.
gdp_per_capita.loc[[c for c in gdp_per_capita.index.astype(str) if "W" in c.upper()]].head()
Subject Descriptor | Units | Scale | Country/Series-specific Notes | GDP per capita | Estimates Start After | |
---|---|---|---|---|---|---|
Country | ||||||
Botswana | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 6557.505 | 2017.0 |
Eswatini | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 3414.805 | 2017.0 |
Kuwait | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 22252.431 | 2018.0 |
Malawi | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 399.097 | 2011.0 |
New Zealand | Gross domestic product per capita, current prices | U.S. dollars | Units | See notes for: Gross domestic product, curren... | 38675.319 | 2019.0 |
모델 규제
‘규제가 있는 선형 모델’에서 다루는 이용하면 과대적합의 위험을 줄일 수 있다. 이렇게 과대적합의 위험을 감소시키기 위에 훈련 모델에 제약을 가하는 것을 규제(regularization)라고 한다.
아래 코드는 세 개의 모델을 비교한다.
- 빨강 파선: 7개 국가 포함 예측 선형 모델
- 파랑 점선: 7개 국가 제외 예측 선형 모델
- 파랑 실선: 7개 국가 제외 규제 적용 예측 선형 모델
- 규제 방식: Ridge 규제
7개 국가를 제외하더라도 모델에 규제를 적용하면 데이터에 덜 과대적합한 모델을 얻게 됨을 세 개의 그래프를 비교해서 알 수 있습니다.
plt.figure(figsize=(8,3))
plt.xlabel("GDP per capita")
plt.ylabel('Life satisfaction')
# 7개 국가 제외 데이터 산점도(파랑 동그라미)
plt.plot(list(sample_data["GDP per capita"]), list(sample_data["Life satisfaction"]), "bo")
# 제외된 7개 국가 산점도(빨강 네모)
plt.plot(list(missing_data["GDP per capita"]), list(missing_data["Life satisfaction"]), "rs")
# 7개 국가 포함 예측 선형 모델 그래프(빨강 파선)
X = np.linspace(0, 110000, 1000)
plt.plot(X, t0full + t1full * X, "r--", label="Linear model on all data")
# 7개 국가 제외 예측 선형 모델 그래프(파랑 점선)
plt.plot(X, t0 + t1*X, "b:", label="Linear model on partial data")
# 릿지(Ridge) 규제 적용 훈련: 7개 국가 제외 데이터 대상
ridge = linear_model.Ridge(alpha=10**9.5)
Xsample = np.c_[sample_data["GDP per capita"]]
ysample = np.c_[sample_data["Life satisfaction"]]
ridge.fit(Xsample, ysample)
# 릿지 규제 적용 예측 선형 모델 그래프(파랑 실선)
t0ridge, t1ridge = ridge.intercept_[0], ridge.coef_[0][0]
plt.plot(X, t0ridge + t1ridge * X, "b", label="Regularized linear model on partial data")
plt.legend(loc="lower right")
plt.axis([0, 110000, 0, 10])
plt.xlabel("GDP per capita (USD)")
save_fig('ridge_model_plot')
plt.show()
Saving figure ridge_model_plot
k-최근접 이웃 모델
사례기반 학습
키프러스의 삶의 만족도를 사례 기반 학습으로 예측하기 위해 1인당 GDP가 키프러스의 경우가 가장 가까운 국가들의 삶의 만족도의 평균값을 활용할 수 있습니다.
2020년 키프러스 1인당 GDP: 26240
예를 들어, 키프러스의 1인당 GDP와 가장 가까운 세 나라는 다음과 같습니다.
- 슬로베니아(Slovenia)
- 스페인(Spain)
- 한국(Korea)
sample_data[12:15]
GDP per capita | Life satisfaction | |
---|---|---|
Country | ||
Slovenia | 25038.792 | 5.9 |
Spain | 26831.629 | 6.3 |
Korea | 30644.427 | 5.9 |
위 세 나라의 삶의 만족도의 평균값은 다음과 같습니다.
(5.9 + 6.3 + 5.9)/3
6.033333333333334
앞서 설명한 알고리즘을 k-최근접 이웃 회귀라고 하며, 위 예제에서 사용된 k는 3입니다.
사이킷런에서 지원하는 k-최근접 이웃 회귀모델을 적용하면 반올림하면 같은 결과를 얻게 됩니다.
- n_neighbors = 3: 예측할 데이터와 가장 가까운 3개의 훈련 데이터 정보를 활용한다는 의미입니다.
6.03 과 5.96이므로 6으로 일치한다고 볼 수 있음
import sklearn.neighbors
model = sklearn.neighbors.KNeighborsRegressor(n_neighbors=3)
X = np.c_[sample_data["GDP per capita"]]
y = np.c_[sample_data["Life satisfaction"]]
# 모델 훈련
model.fit(X, y)
# 키프러스 국가에 대한 예측하기
X_new = np.array([[26240.048]]) # Cyprus' GDP per capita
print(model.predict(X_new)) # outputs [[ 6.033333333333334]]
[[5.96666667]]