学生による学生のためのデータサイエンス勉強会

【さきどりPython#10】WorldHappinesReportで線形回帰モデルを作ってみよう

 こんにちは。今回から「Python機械学習クックブック」2週目ですね。2週目からはkaggleのデータを実装していきます。今回はword Happiness Reportのデータを使用して線形回帰モデルを作ります。

使用するデータ

 「World Happiness Report」という国別の幸福度に関する調査をまとめたKaggleのデータセットです。2015年から2019年までの調査がそろっていますが、今回は2019年のデータを使用します。

データの確認

 まずはデータの中身を確認します。

import pandas as pd
df=pd.read_csv('/content/drive/My Drive/2019.csv')
df

 156カ国が国別幸福度順に並べられています。列名は’Overall rank’(順位), ‘Country or region’(国または地域), ‘Score’(幸福度スコア), ‘GDP per capita’(GDP), ‘Social support’(ソーシャルサポート), ‘Healthy life expectancy’(健康寿命), ‘Freedom to make life choices’(人生選択の自由), ‘Generosity’(寛大さ), ‘Perceptions of corruption’(国への信頼度)です。

 ちなみに日本は何位なのでしょうか?==で検索してみましょう。

#Japanを抽出
row1=df['Country or region']
result1=row1=='Japan'
df[result1]

 

Overall rankCountry or regionScoreGDP per capitaSocial supportHealthy life expectancyFreedom to make life choicesGenerosityPerceptions of corruption
5758Japan5.8861.3271.4191.0880.4450.0690.14

 58位なんですね。(思ったより高かった。。。)

では、国民の97%が「幸せ」と答える幸せの国ブータンはどうでしょうか?

Overall rankCountry or regionScoreGDP per capitaSocial supportHealthy life expectancyFreedom to make life choicesGenerosityPerceptions of corruption
9495Bhutan5.0820.8131.3210.6040.4570.370.167

日本よりも低いですね。意外ですΣ(´∀`;)

もしかしたら、人々が感じる「幸福度」と調査項目から導き出された「幸福度」は異なるものなのかもしれませんね。

グラフの描画

各項目が幸福度スコアとどのような関係にあるのかを確認します。

説明変数

‘GDP per capita’(GDP), ‘Social support’(ソーシャルサポート), ‘Healthy life expectancy’(健康寿命), ‘Freedom to make life choices’(人生選択の自由), ‘Generosity’(寛大さ), ‘Perceptions of corruption’(国への信頼度)

目的変数

‘Score’(幸福度スコア)

としてそれぞれ散布図を描きました。参考程度に見てください(⌒∇⌒)

線形回帰分析

  直線ぽいけど曲線にもなりそうな’Social support’を説明変数、’Score’を目的変数として線形回帰を行います。まずは、直線回帰からです。

from sklearn.linear_model import LinearRegression

#線形回帰器を作成
regression=LinearRegression()

#データ
feature=df[['Social support']].values
target=df['Score'].values

#線形回帰器を訓練
model=regression.fit(feature,target)

#散布図
x=df[['Social support']]
y=df['Score']

fig=plt.figure(figsize=(6,4))
ax=plt.axes()
plt.plot(x,y,'o',color='pink')
plt.grid(color='gray',linestyle=':',linewidth=0.5)
plt.xlabel('Social support',fontsize=16)
plt.ylabel('Score',fontsize=16)

#回帰係数
plt.plot(x,model.predict(x), label = 'linear (d = 1)',color='orange')
plt.legend();

やはり直線にするとずれているような気がしますね。

では、この回帰モデルを評価するにはどうすればよいのでしょうか?

モデル評価

 線形回帰ではよく決定係数 $$R^2$$ が使用されます。

 決定係数とはデータに対する推定された当てはまりの良さをあらわす指標です。1に近いほど、回帰式が実際のデータに当てはまっていることをあらわしているのでわかりやすいですね。

決定係数は.scoreで出します。

# 予測値、R^2(決定係数)を評価
r2_lin = model.score(feature, target)
r2_lin
#0.6038188059907054

 0.60…なのでデータの約60%をこの回帰モデルで説明できるということです。

精度を上げるには?

 直線がだめなら、曲線にして複雑なモデルを作れば精度が上がるのではないかと考えました。試しに2次~7次、9次の多項式回帰モデルを作ってみます。

from sklearn.preprocessing import PolynomialFeatures

f=df[['Social support']].values
t=df['Score'].values

#以下、直線と2次の場合のみ書いています。次数に合わせて各々変えてください。
quadratic=PolynomialFeatures(degree=2,include_bias=False) #degree:最高次数(デフォルトは2)
f_quad=quadratic.fit_transform(f)

#線形回帰器を作成
regression=LinearRegression()

#線形回帰器を訓練
mod=regression.fit(f,t)
mod2=regression.fit(f_quad,t)

# モデル式用に変数を作成
f_fit = np.arange(f.min(), f.max(), 0.1)[:, np.newaxis]

# 線形回帰モデル、予測値、R^2を評価
mod_lin = mod.fit(f, t)
t_lin_fit = mod_lin.predict(f_fit)
r2_lin = mod.score(f, t)

# 2次の項を追加、予測値、R^2を評価
mod_quad = mod2.fit(f_quad, t)
t_quad_fit = mod_quad.predict(quadratic.fit_transform(f_fit))
r2_quad = mod2.score(f_quad, t)

# データ点をプロット
plt.figure(figsize=(10,6))
plt.scatter(f, t, color = 'pink')

# 線形モデルのモデル式()
plt.plot(f_fit, t_lin_fit, label = 'linear (d = 1), $R^2=%.2f$' % r2_lin,color = 'orange', lw = 2,linestyle='--')
# 2次
plt.plot(f_fit, t_quad_fit,label = 'quadratic (d = 2), $R^2=%.2f$' % r2_quad,  color = 'red', lw = 2, linestyle = '-')

plt.grid(color='gray',linestyle=':',linewidth=0.5)
plt.xlabel('Social support',fontsize=16)
plt.ylabel('Score',fontsize=16)
plt.legend();

まず3次式までの回帰モデルと決定係数です。


3次式までは順調に決定係数の値が上がっていますね。では、3次以上はどうでしょうか?

3次から6次まで、決定係数の値は変化なしです。

7次になると、決定係数の値は少し上がりましたが、データにフィットしすぎているような気がします。

9次まで上げると誤差が大きくなりすぎて、データがつぶれてしまいました。

 ちなみにこれが過学習を起こしている状態ですね。でも、決定係数だけで過学習を起こしているかまでは判断できないので誤差を計算してモデルを評価する必要があります。

まとめ

・説明変数を’sosial sapport’、目的変数を’score’とした単回帰分析の場合、3~6次程度が良い次数

・次数を上げると決定係数の値は良くなったが、上げすぎると過学習がおこるので次数を上げれば良いというわけではない。

・今回のモデルでは高くてもデータの約67%しか説明できなかったので、説明変数を’sosial sapport’、目的変数を’score’とした場合、単回帰分析はあまり適さない?

今後の課題

・誤差を用いてモデル評価を行う。

・訓練データとテストデータを分けてモデルを検証する。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です