100日後にエンジニアになるキミ - 81日目 - プログラミング - 機械学習について6

昨日までのはこちら

[100日後にエンジニアになるキミ - 76日目 - プログラミング - 機械学習について](https://qiita.com/otupy/items/6a4f960ba4df06e27050)

[100日後にエンジニアになるキミ - 70日目 - プログラミング - スクレイピングについて](https://qiita.com/otupy/items/f53e2e7d16adf80b5acf)

[100日後にエンジニアになるキミ - 66日目 - プログラミング - 自然言語処理について](https://qiita.com/otupy/items/5828ac7450c5ba8d6931)

[100日後にエンジニアになるキミ - 63日目 - プログラミング - 確率について1](https://qiita.com/otupy/items/0196897ae4d2134794fa)

[100日後にエンジニアになるキミ - 59日目 - プログラミング - アルゴリズムについて](https://qiita.com/otupy/items/f1a5e81633b868f3b5ed)

[100日後にエンジニアになるキミ - 53日目 - Git - Gitについて](https://qiita.com/otupy/items/0abaad82a7f3fea73f1f)

[100日後にエンジニアになるキミ - 42日目 - クラウド - クラウドサービスについて](https://qiita.com/otupy/items/d1765f1541a104ed6133)

[100日後にエンジニアになるキミ - 36日目 - データベース - データベースについて](https://qiita.com/otupy/items/7af17635d576677606dc)

[100日後にエンジニアになるキミ - 24日目 - Python - Python言語の基礎1](https://qiita.com/otupy/items/6d1e5453f530e07b7aec)

[100日後にエンジニアになるキミ - 18日目 - Javascript - JavaScriptの基礎1](https://qiita.com/otupy/items/2f71d5f9c754b29d9555)

[100日後にエンジニアになるキミ - 14日目 - CSS - CSSの基礎1](https://qiita.com/otupy/items/61a97863f6df14171994)

[100日後にエンジニアになるキミ - 6日目 - HTML - HTMLの基礎1](https://qiita.com/otupy/items/cd2315dcb38671cfded0)

今回は機械学習についてのお話の続きです。

## 回帰モデルについて

初回で機械学習でできることについて解説していますが、機械学習でできることは
基本的には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`が予測したい`目的変数`、それ以外が`説明変数`になります。

### データの可視化

まずはどんなデータなのかをみてみましょう。

```python
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 |

数値のデータが入っていますね。

各列同士の関係性をみてみるために可視化をしてみます。

```python
sns.pairplot(data=boston_df[list(boston_df.columns[0:6])+['MEDV']])
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/040d9a88-a7b4-05f4-9b8d-7b48ef887205.png)

```python
sns.pairplot(data=boston_df[list(boston_df.columns[6:13])+['MEDV']])
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/ce4860f8-8d62-447f-8d94-d30a50d3c21c.png)

各列の相関性もみてみます。

```python
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で分割を行います。

```python
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`と言うものになります。

```python
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に近い量になります。

<img width="238" alt="スクリーンショット 2020-06-09 19.19.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/cc598157-957a-0408-e4e1-8c0dc3c8647f.png">



```python
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くらいズレてます。
住宅価格に対して平均的にはこれくらいズレていると言う誤差になります。

**残差のプロット**

さて、予測モデルはどれくらいズレが生じたのでしょうか？
`残差`を可視化してみましょう。

```python
# 残差をプロット
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()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/d7405f3a-7d63-274c-f9d0-b3dbd4593590.png)

テストデータと予測データを組みあわせることで、どれくらいズレているのかを見ることができます。
ズレているものはかなりズレが生じていますね。

こんな感じで、ズレが少なくなるようにモデルを作り、データの取捨選択や前処理、モデルのパラメータ値の調整などで
誤差が少なく精度が良くなるように目指します。

## まとめ

本日は回帰のモデルの仕組みを説明しました。
回帰モデルは他にもたくさん存在します。

まずは、回帰とは何、と言うことから初めて、モデル作り方と検証の仕方を抑えておきましょう。

君がエンジニアになるまであと19日

## 作者の情報
乙pyのHP：
http://www.otupy.net/

Youtube：
https://www.youtube.com/channel/UCaT7xpeq8n1G_HcJKKSOXMw

Twitter：
https://twitter.com/otupython