昨日までのはこちら
100日後にエンジニアになるキミ - 76日目 - プログラミング - 機械学習について
100日後にエンジニアになるキミ - 70日目 - プログラミング - スクレイピングについて
100日後にエンジニアになるキミ - 66日目 - プログラミング - 自然言語処理について
100日後にエンジニアになるキミ - 63日目 - プログラミング - 確率について1
100日後にエンジニアになるキミ - 59日目 - プログラミング - アルゴリズムについて
100日後にエンジニアになるキミ - 53日目 - Git - Gitについて
100日後にエンジニアになるキミ - 42日目 - クラウド - クラウドサービスについて
100日後にエンジニアになるキミ - 36日目 - データベース - データベースについて
100日後にエンジニアになるキミ - 24日目 - Python - Python言語の基礎1
100日後にエンジニアになるキミ - 18日目 - Javascript - JavaScriptの基礎1
100日後にエンジニアになるキミ - 14日目 - CSS - CSSの基礎1
100日後にエンジニアになるキミ - 6日目 - HTML - HTMLの基礎1
今回は機械学習についてのお話の続きです。
回帰モデルについて
初回で機械学習でできることについて解説していますが、機械学習でできることは
基本的には3つです。
・回帰
・分類
・クラスタリング
大まかに言うと予測
になりますが何を予測
するかと言う部分が変わります。
・回帰:数値を予測する
・分類:カテゴリを予測する
・クラスタリング:いい感じにする
回帰モデル
は数値を予測しにいきます。
今回使用するデータはscikit-learn
に付属しているボストンの住宅価格のデータを用います。
カラム | 説明 |
---|---|
CRIM | 町ごとの一人当たりの犯罪率 |
ZN | 宅地の比率が25,000平方フィートを超える敷地に区画 |
INDUS | 町当たりの非小売業エーカーの割合 |
CHAS | チャーリーズ川ダミー変数(川の境界にある場合は1、それ以外は0) |
NOX | 一酸化窒素濃度(1000万分の1) |
RM | 1住戸あたりの平均部屋数 |
AGE | 1940年以前に建設された所有占有ユニットの年齢比率 |
DIS | 5つのボストンの雇用センターまでの加重距離 |
RAD | ラジアルハイウェイへのアクセス可能性の指標 |
TAX | 10,000ドルあたりの税全額固定資産税率 |
PTRATIO | 生徒教師の比率 |
B | 町における黒人の割合 |
LSTAT | 人口当たり地位が低い率 |
MEDV | 1000ドルでの所有者居住住宅の中央値 |
MEDV
が予測したい目的変数
、それ以外が説明変数
になります。
データの可視化
まずはどんなデータなのかをみてみましょう。
from sklearn.datasets import load_boston
# データの読み込み
boston = load_boston()
# データフレームの作成
boston_df = pd.DataFrame(data=boston.data,columns=boston.feature_names)
boston_df['MEDV'] = boston.target
# データの概要
print(boston_df.shape)
boston_df.head()
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | MEDV | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00632 | 18 | 2.31 | 0 | 0.538 | 6.575 | 65.2 | 4.09 | 1 | 296 | 15.3 | 396.9 | 4.98 | 24 |
1 | 0.02731 | 0 | 7.07 | 0 | 0.469 | 6.421 | 78.9 | 4.9671 | 2 | 242 | 17.8 | 396.9 | 9.14 | 21.6 |
2 | 0.02729 | 0 | 7.07 | 0 | 0.469 | 7.185 | 61.1 | 4.9671 | 2 | 242 | 17.8 | 392.83 | 4.03 | 34.7 |
3 | 0.03237 | 0 | 2.18 | 0 | 0.458 | 6.998 | 45.8 | 6.0622 | 3 | 222 | 18.7 | 394.63 | 2.94 | 33.4 |
4 | 0.06905 | 0 | 2.18 | 0 | 0.458 | 7.147 | 54.2 | 6.0622 | 3 | 222 | 18.7 | 396.9 | 5.33 | 36.2 |
数値のデータが入っていますね。
各列同士の関係性をみてみるために可視化をしてみます。
sns.pairplot(data=boston_df[list(boston_df.columns[0:6])+['MEDV']])
plt.show()
sns.pairplot(data=boston_df[list(boston_df.columns[6:13])+['MEDV']])
plt.show()
各列の相関性もみてみます。
boston_df.corr()
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | MEDV | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
CRIM | 1 | -0.200469 | 0.406583 | -0.055892 | 0.420972 | -0.219247 | 0.352734 | -0.37967 | 0.625505 | 0.582764 | 0.289946 | -0.385064 | 0.455621 | -0.388305 |
ZN | -0.200469 | 1 | -0.533828 | -0.042697 | -0.516604 | 0.311991 | -0.569537 | 0.664408 | -0.311948 | -0.314563 | -0.391679 | 0.17552 | -0.412995 | 0.360445 |
INDUS | 0.406583 | -0.533828 | 1 | 0.062938 | 0.763651 | -0.391676 | 0.644779 | -0.708027 | 0.595129 | 0.72076 | 0.383248 | -0.356977 | 0.6038 | -0.483725 |
CHAS | -0.055892 | -0.042697 | 0.062938 | 1 | 0.091203 | 0.091251 | 0.086518 | -0.099176 | -0.007368 | -0.035587 | -0.121515 | 0.048788 | -0.053929 | 0.17526 |
NOX | 0.420972 | -0.516604 | 0.763651 | 0.091203 | 1 | -0.302188 | 0.73147 | -0.76923 | 0.611441 | 0.668023 | 0.188933 | -0.380051 | 0.590879 | -0.427321 |
RM | -0.219247 | 0.311991 | -0.391676 | 0.091251 | -0.302188 | 1 | -0.240265 | 0.205246 | -0.209847 | -0.292048 | -0.355501 | 0.128069 | -0.613808 | 0.69536 |
AGE | 0.352734 | -0.569537 | 0.644779 | 0.086518 | 0.73147 | -0.240265 | 1 | -0.747881 | 0.456022 | 0.506456 | 0.261515 | -0.273534 | 0.602339 | -0.376955 |
DIS | -0.37967 | 0.664408 | -0.708027 | -0.099176 | -0.76923 | 0.205246 | -0.747881 | 1 | -0.494588 | -0.534432 | -0.232471 | 0.291512 | -0.496996 | 0.249929 |
RAD | 0.625505 | -0.311948 | 0.595129 | -0.007368 | 0.611441 | -0.209847 | 0.456022 | -0.494588 | 1 | 0.910228 | 0.464741 | -0.444413 | 0.488676 | -0.381626 |
TAX | 0.582764 | -0.314563 | 0.72076 | -0.035587 | 0.668023 | -0.292048 | 0.506456 | -0.534432 | 0.910228 | 1 | 0.460853 | -0.441808 | 0.543993 | -0.468536 |
PTRATIO | 0.289946 | -0.391679 | 0.383248 | -0.121515 | 0.188933 | -0.355501 | 0.261515 | -0.232471 | 0.464741 | 0.460853 | 1 | -0.177383 | 0.374044 | -0.507787 |
B | -0.385064 | 0.17552 | -0.356977 | 0.048788 | -0.380051 | 0.128069 | -0.273534 | 0.291512 | -0.444413 | -0.441808 | -0.177383 | 1 | -0.366087 | 0.333461 |
LSTAT | 0.455621 | -0.412995 | 0.6038 | -0.053929 | 0.590879 | -0.613808 | 0.602339 | -0.496996 | 0.488676 | 0.543993 | 0.374044 | -0.366087 | 1 | -0.737663 |
MEDV | -0.388305 | 0.360445 | -0.483725 | 0.17526 | -0.427321 | 0.69536 | -0.376955 | 0.249929 | -0.381626 | -0.468536 | -0.507787 | 0.333461 | -0.737663 | 1 |
一部の列を除いて各列同士の相関性はそこまで高くないように見えます。
これらの列を用いて1つの目的変数
の値を当てに行きたいというのが回帰モデル
になります。
予測モデルの作成
データの分割
まずは訓練用とテスト用にデータを分割します。今回は6:4で分割を行います。
from sklearn.model_selection import train_test_split
# 訓練データとテストデータに6:4で分割
X = boston_df.drop('MEDV',axis=1)
Y = boston_df['MEDV']
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.4, random_state=0)
モデル作成
次に予測モデルを作成します。
ここでは線形回帰モデル
を使用し目的変数をMEDV
、説明変数をCRIM~LSTAT
とした回帰モデルを構築します。
ざっくりとした説明をすると、Y = x1 * a + x2 * b + ... ϵ
と言うような式を作るイメージです。
a
とかb
は回帰係数
と呼ばれるもので、それぞれの変数が
どれだけ目的変数の予測に寄与するかを表しています。
ϵ
は残差
と呼ばれるもので、各データと式のズレ
具合を表します。
線形回帰モデル
では各データの残差の二乗
を足し合わせたものを
最小にするという方法で各係数を求めます。
用いるライブラリはlinear_model
と言うものになります。
from sklearn import linear_model
# 線形回帰で学習
model = linear_model.LinearRegression()
model.fit(x_train, y_train)
モデルづくりはライブラリを呼び出してfit
を行うことですぐに終わります。
精度検証
回帰モデルの精度検証は、どれだけ予測と実測がズレているのかを見ていきます。
良く用いられる指標としては
平均二乗誤差(nean squared error : MSE)
や
二乗平均平方根誤差(root mean squared error : RMSE)
R二乗値
$R^2$があります。
MSEは
誤差の二乗和の平均値となり、訓練データ、テストデータともに小さければモデルの性能が良いと判断されます。
RMSEは
誤差の二乗和の平均値の平方根の値です。
R二乗値
$R^2$はMSE
が0の場合に1をとり、モデルの性能が良いほど1に近い量になります。
from sklearn.metrics import mean_squared_error
y_pred = model.predict(x_test)
print('MSE : {0} '.format(mean_squared_error(y_test, y_pred)))
print('RMSE : {0} '.format(np.sqrt(mean_squared_error(y_test, y_pred))))
print('R^2 : {0}'.format(model.score(x_test, y_test)))
MSE : 25.79036215070245
RMSE : 5.078421226198399
R^2 : 0.6882607142538019
さて、精度を見るとRMSE
の値で5.0くらいズレてます。
住宅価格に対して平均的にはこれくらいズレていると言う誤差になります。
残差のプロット
さて、予測モデルはどれくらいズレが生じたのでしょうか?
残差
を可視化してみましょう。
# 残差をプロット
plt.scatter(y_pred, y_pred - y_test, c = 'red', marker = 's')
plt.xlabel('Predicted Values')
plt.ylabel('Residuals')
# y = 0に直線を引く
plt.hlines(y = 0, xmin = -10, xmax = 50, lw = 2, color = 'blue')
plt.xlim([10, 50])
plt.show()
テストデータと予測データを組みあわせることで、どれくらいズレているのかを見ることができます。
ズレているものはかなりズレが生じていますね。
こんな感じで、ズレが少なくなるようにモデルを作り、データの取捨選択や前処理、モデルのパラメータ値の調整などで
誤差が少なく精度が良くなるように目指します。
まとめ
本日は回帰のモデルの仕組みを説明しました。
回帰モデルは他にもたくさん存在します。
まずは、回帰とは何、と言うことから初めて、モデル作り方と検証の仕方を抑えておきましょう。
君がエンジニアになるまであと19日
作者の情報
乙pyのHP:
http://www.otupy.net/
Youtube:
https://www.youtube.com/channel/UCaT7xpeq8n1G_HcJKKSOXMw
Twitter:
https://twitter.com/otupython