ラビットチャレンジ - 機械学習 第1章 線形回帰モデル

# 0．概要
本記事は日本ディープラーニング協会認定の講座プログラムである「ラビット・チャレンジ」が提供している科目の1つである機械学習のレポートである。
記事タイトルに記載のとおり、第1章の線形回帰モデルについて以下にまとめる。

# 1．機械学習(深層学習)モデリングプロセス

## 1.1．問題設定

どういった問題があり、どう解決させるか。
機械学習や深層学習でなにかしたい！という声はよく聞くが、これは間違いであり、**問題の解決に必ずしも機械学習や深層学習を使う必要はない。**
手段の目的化になってはならない。

また、機械学習や深層学習が持つデメリットとして以下の2つがある。

* 技術的負債

機械学習や深層学習は応用数学や統計等の知識も必要とし、非常に複雑な仕組みとなっている。
そのため、開発はできたとしても運用チーム等で十分に知識がない人がトラブルに見舞われた時に対策を取ることができない。

* テストのしにくさ

一般的なルールベースのプログラムであれば想定される結果が決まっているため、自動テスト等で容易にテストを行うことができる。
しかし、学習モデルは更新したことによって入力が同じでも以前とは異なる結果となることもあり得る。

そのため、ルールベースで解決できるのであればルールベースで良い。
あくまでも**目的は問題の解決**であるということを忘れてはならない。

## 1.2．データ選定
問題を解決するためにはどういったデータが必要か。どうやってデータを用意するか。
データを持ってるところからもらったり外注でデータを作ってもらったり方法は色々あるがどういったデータが必要かは見極めねばならない。

## 1.3．データの前処理
集めたデータはそのまま使えるとは限らない。
欠損値や異常に対するクレンジング処理等を行って学習モデルに投入できる形にする。

## 1.4．機械学習(深層学習)モデルの選定
分類・予測・クラスタリング等、解決した問題に合わせてどういった学習モデルのアルゴリズムを使用するか選定する。
最良のものを使用したり結果を組み合わせたアンサンブルさせたものを使用したりする。

## 1.5．モデルの学習(パラメータ推定)
学習モデルには何かしらのハイパーパラメータが存在する。
用意したデータを元にパラメータをどういった値とするか推定する。

## 1.6．モデルの評価
ハイパーパラメータの選定やモデルの精度を測る。

# 2．機械学習の定義
トム・ミッチェルによる定義。

* コンピュータプログラムは、タスクTを性能指標Pで測定し、その性能が経験Eにより改善される場合、タスクTおよび性能指標Pに関して経験Eから学習すると言われている。

タスク：アプリケーションにさせたいこと
経験：データ
性能指標：例えば、猫の画像をどれだけ正しく猫と判断するか。

上記の定義を言い換えると

* アプリケーションで実現したいことが、データをより与えることによって以前の結果より改善したなら与えたデータから学習したと言える。

# 3．線形回帰モデル

## 3.1．回帰問題
ある入力値(離散値または連続値)から連続値の出力を予測すること。教師あり学習の1つ。
例）株価がいくらになるかの予測。

## 3.2．線形回帰と非線形回帰
ここでいう線形回帰モデルの「線形」とは直線(1次関数)のこと。
回帰モデルの中には下記の2つがある。

* 線形回帰：直線で予測すること。いわゆる一次関数。
* 非線形回帰：曲線で予測すること。いわゆる二次関数等、次数が2以上の関数。

## 3.3．回帰で扱うデータ

### 3.3.1．入力データ
説明変数または特徴量と呼ぶ。
$m$次元ベクトル($m=1$ならスカラ値)。

```math
x=(x_{1},x_{2},...,x_{m})^T\in\mathbb{R}^m
```

例）不動産の価格予測の場合
部屋の数
部屋の広さ
築年数
駅からの距離 ...etc

### 3.3.2．出力データ
目的変数と呼ぶ。

```math
y\in\mathbb{R}^1
```

例）不動産の価格予測の場合
その不動産の価格

## 3.4．モデルのパラメータ
重み：$w=(w_{1},w_{2},...,w_{m})^T\in\mathbb{R}^m$
推定すべき未知のパラメータ。
それぞれの説明変数がモデルにどれだけ影響を与えるか(重要か)を決定する。
大きいほど対応する説明変数が大きな影響を持つ。

この重みが調整されていくことで予測の精度が上がっていく。

切片：$w_{0}$
y軸との交点。

## 3.5．線形結合(一次結合)
説明変数とパラメータの内積。内積なので出力はスカラ値。

この$\hat{y}$が予測値となるが、目的変数との混同を防ぐために$y$とは記述せず、ハットをつける。

```math
\hat{y}=w^{T}x+w_{0}=\sum_{j=i}^{m}{w_{j}x_{j}+w_{0}}
```

内積とってる総和のところが線形結合。

## 3.6．単回帰
説明変数が1次元($m=1$)の場合。
直線で表される。

データは回帰直線に誤差が加わって観測されていると仮定する。

```math
y=w_{0}+w_{1}x_{1}+\epsilon
```

$\epsilon$：誤差

## 3.7．重回帰
説明変数が多次元($m>1$)の場合。
曲面(3次元のグラフ)で表される。

```math
y=w_{0}+w_{1}x_{1}+...+w_{m}x_{m}+\epsilon
```

## 3.8．パラメータの推定

### 3.8.1．平均二乗誤差(残差平方和の平均)
予測値と目的変数の差(誤差、予測とのズレ)を2乗した総和の平均。
小さいほど目的変数に近いと言える。

与えるデータは学習データ($train$。後述する)。
式に$train$とたくさん付くと見づらくなるため以降も省略して表記する。

```math
MSE=\frac{1}{n}\sum_{i=1}^{n}{(\hat{y}-y)^2}
```

#### 3.8.1.1．平均平方二乗誤差
平均二乗誤差の式を見た時、分散っぽい式だなって思ったので分散で言うところの標準偏差に当たるものが平均二乗誤差にもあるのか調べてみたらありました。
Mean Squared Errorの略であるMSEの頭にRootが付いただけでそのままです。

```math
RMSE=\sqrt{\frac{1}{n}\sum_{i=1}^{n}{(\hat{y}-y)^2}}
```

平均二乗誤差よりも平均平方二乗誤差を使うことの方が一般的なようです。
特徴の1つとして外れ値の影響を受けやすいため事前に外れ値は外しておくと良い。

### 3.8.2．最小二乗法
平均二乗誤差を最小化するパラメータを探索する。

```math
\hat{w}=arg\, min_{w\in\mathbb{R}^m}\,MSE
```

$w$に対して微分した勾配が0になる点。

```math
\frac{\partial}{\partial w}MSE=0
```

回帰係数(傾き)が以下となる。

```math
\hat{w}=(X^TX)^{-1}X^Ty
```

予測値を出すには線形結合(つまり内積)を算出すれば良いので以下となる。

```math
\hat{y}=X\hat{w}
```

### 3.8.3．最尤法
誤差を正規分布に従う確率変数と仮定して尤度関数の最大化を利用した推定を行う。
回帰の場合は最小二乗法と同じ解となる。

### 3.8.4．平均絶対誤差
これも平均平方二乗誤差と同じで講義動画には出てきませんが、調べてた時に一緒に出てきたので合わせてまとめておきます。
平均偏差みたいな式。

```math
MAE=\frac{1}{n}\sum_{i=1}^{n}{|\hat{y}-y|}
```

2乗してない分、平均平方二乗誤差より外れ値の影響を受けにくい。

# 4．データの分割
全てのデータを学習に使うことはない。分割して使用する。

重要なのはどれだけ正しく学習できたかではなく、**どれだけ未知のデータに対して正しく予測ができるか(汎化性能)**。
学習に使ったデータはモデルにとって既に既知のものであるため、汎化性能を図ることはできない。

## 4.1．学習データ
その名の通り学習に使用するデータ。
モデルにとっては既知なので検証には使えない(予測できて当たり前)。
$x^{train}$と表記する。

## 4.2．検証データ
モデルの汎化性能を確認するために使用するデータ。
この講義内では$x^{test}$と表記するとあるが、データを学習・検証・テストの3つに分けるなら$x^{val}$。

## 4.3．テストデータ
モデルの性能を最終チェックするためのデータ。
$x^{test}$と表記する。

# 5．ハンズオン

## 5.1．使用するデータ
ボストンの住宅データセットを使用する。
いくつもの説明変数があるが、ここでは住宅周辺の犯罪発生率と部屋数を使用する。

## 5.2．課題
犯罪発生率と部屋数からその物件の住宅価格がいくらになるか予測する。
　→部屋数が4で犯罪率は0.3の物件はいくらか。

## 5.3．演習

### 5.3.1．ライブラリのインポートとデータセット読み込み

```python:
# from モジュール名 import クラス名（もしくは関数名や変数名）
from sklearn.datasets import load_boston
from pandas import DataFrame
import numpy as np

# ボストンデータを"boston"というインスタンスにインポート
boston = load_boston()
```

ここで読み込むライブラリは以下の3つ

* scikit-learn：ボストンの住宅データセットを使用するため。
* Pandas：Excelのようなイメージでデータを表示等できるライブラリでデータを扱いやすくするもの。
* numpy：ベクトルや行列等の計算を効率的に行うためのもの。

今回使うボストンの住宅データセットやMNISTの手書き数字文字等、このように学習等に使えるデータセットは自分でどこかからダウンロードしてこなくてもライブラリの機能として提供されているものもある。

### 5.3.2．データセットの中身確認

```python:
# インポートしたデータを確認(data / target / feature_names / DESCR)
print(boston)

# DESCR変数の中身を確認
print(boston['DESCR'])

# feature_names変数の中身を確認
# カラム名
print(boston['feature_names'])

# data変数(説明変数)の中身を確認
print(boston['data'][:5])

# target変数(目的変数)の中身を確認
print(boston['target'][:5])
```

bostonをそのまま出力した結果の抜粋。
コメントにもあるが、説明変数を持つdata、目的変数を持つtarget、各説明変数の名前を持つfeature_names、このデータセットの説明であるDESCRを持っていることが分かる。

> {'data': array([[6.3200e-03, 1.8000e+01, 2.3100e+00, ..., 1.5300e+01, 3.9690e+02,
>         4.9800e+00],
>        [2.7310e-02, 0.0000e+00, 7.0700e+00, ..., 1.7800e+01, 3.9690e+02,
>         9.1400e+00],
>        [2.7290e-02, 0.0000e+00, 7.0700e+00, ..., 1.7800e+01, 3.9283e+02,
>         4.0300e+00],
>        ...,
>        [6.0760e-02, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 3.9690e+02,
>         5.6400e+00],
>        [1.0959e-01, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 3.9345e+02,
>         6.4800e+00],
>        [4.7410e-02, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 3.9690e+02,
>         7.8800e+00]]),
> 'target': array([24. , 21.6, 34.7, 33.4, 36.2, 28.7, 22.9, 27.1, 16.5, 18.9, 15. ,
>        18.9, 21.7, 20.4, 18.2, 19.9, 23.1, 17.5, 20.2, 18.2, 13.6, 19.6,
>        15.2, 14.5, 15.6, 13.9, 16.6, 14.8, 18.4, 21. , 12.7, 14.5, 13.2,
>        ...,
>        29.8, 13.8, 13.3, 16.7, 12. , 14.6, 21.4, 23. , 23.7, 25. , 21.8,
>        20.6, 21.2, 19.1, 20.6, 15.2,  7. ,  8.1, 13.6, 20.1, 21.8, 24.5,
>        23.1, 19.7, 18.3, 21.2, 17.5, 16.8, 22.4, 20.6, 23.9, 22. , 11.9]),
> 'feature_names': array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD',
>        'TAX', 'PTRATIO', 'B', 'LSTAT'], dtype='<U7'),
> 'DESCR': ".. _boston_dataset:\n\nBoston house prices dataset\n---------------------------\n\n**Data Set Characteristics:**  \n\n    (以下省略)
> }

DESCRの中身を確認すると以下のようになっている(後半の概要的な部分は省略)。
レコードが506件、説明変数が13個あること、各説明変数の意味について説明されている。

> .. _boston_dataset:
> 
> Boston house prices dataset
> \---------------------------
> 
> \*\*Data Set Characteristics:**
> 
> :Number of Instances: 506 
> 
> :Number of Attributes: 13 numeric/categorical predictive. Median Value (attribute 14) is usually the target.
> 
> :Attribute Information (in order):
>         - CRIM     per capita crime rate by town
>         - ZN       proportion of residential land zoned for lots over 25,000 sq.ft.
>         - INDUS    proportion of non-retail business acres per town
>         - CHAS     Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
>         - NOX      nitric oxides concentration (parts per 10 million)
>         - RM       average number of rooms per dwelling
>         - AGE      proportion of owner-occupied units built prior to 1940
>         - DIS      weighted distances to five Boston employment centres
>         - RAD      index of accessibility to radial highways
>         - TAX      full-value property-tax rate per \$10,000
>         - PTRATIO  pupil-teacher ratio by town
>         - B        1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town
>         - LSTAT    % lower status of the population
>         - MEDV     Median value of owner-occupied homes in $1000's
> 
> :Missing Attribute Values: None
> 
> :Creator: Harrison, D. and Rubinfeld, D.L.

実際に要素数を確認してみるとレコードが506件、説明変数が13個、目的変数が1つ(実行結果では1が省略されてカンマで終わっている)あることが分かる。

```python:
# 各次元の要素数を確認
print(boston.data.shape)
print(boston.target.shape)
```

> (506, 13)
> (506,)

feature_namesの中身を確認すると説明変数の名前は以下になっていてDESCR通りであることが分かる。

> ['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO' 'B' 'LSTAT']

dataの中身(データが多いので上位5件)が以下。

> [[6.3200e-03 1.8000e+01 2.3100e+00 0.0000e+00 5.3800e-01 6.5750e+00
>   6.5200e+01 4.0900e+00 1.0000e+00 2.9600e+02 1.5300e+01 3.9690e+02
>   4.9800e+00]
>  [2.7310e-02 0.0000e+00 7.0700e+00 0.0000e+00 4.6900e-01 6.4210e+00
>   7.8900e+01 4.9671e+00 2.0000e+00 2.4200e+02 1.7800e+01 3.9690e+02
>   9.1400e+00]
>  [2.7290e-02 0.0000e+00 7.0700e+00 0.0000e+00 4.6900e-01 7.1850e+00
>   6.1100e+01 4.9671e+00 2.0000e+00 2.4200e+02 1.7800e+01 3.9283e+02
>   4.0300e+00]
>  [3.2370e-02 0.0000e+00 2.1800e+00 0.0000e+00 4.5800e-01 6.9980e+00
>   4.5800e+01 6.0622e+00 3.0000e+00 2.2200e+02 1.8700e+01 3.9463e+02
>   2.9400e+00]
>  [6.9050e-02 0.0000e+00 2.1800e+00 0.0000e+00 4.5800e-01 7.1470e+00
>   5.4200e+01 6.0622e+00 3.0000e+00 2.2200e+02 1.8700e+01 3.9690e+02
>   5.3300e+00]]

targetの中身(データが多いので上位5件)が以下。

> [24.  21.6 34.7 33.4 36.2]

### 5.3.3．データフレーム(DataFrame)の作成

```python:
# 説明変数らをDataFrameへ変換
df = DataFrame(data=boston.data, columns = boston.feature_names)

# 目的変数をDataFrameへ追加
df['PRICE'] = np.array(boston.target)

# 最初の5行を表示
df.head(5)
```

まず説明変数からデータフレームを作る。カラム名はfeature_namesに持ってるのでそれを使う。
作ったデータフレームに目的変数を追加する。目的変数の名前PRICEはfeature_namesにないのでそのまま記述する。
結果はprintで確認していた時と違って以下のような見やすい形で出力できる。

||CRIM|ZN|INDUS|CHAS|NOX|RM|AGE|DIS|RAD|TAX|PTRATIO|B|LSTAT|PRICE|
|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|
|0|0.00632|18.0|2.31|0.0|0.538|6.575|65.2|4.0900|1.0|296.0|15.3|396.90|4.98|24.0|
|1|0.02731|0.0|7.07|0.0|0.469|6.421|78.9|4.9671|2.0|242.0|17.8|396.90|9.14|21.6|
|2|0.02729|0.0|7.07|0.0|0.469|7.185|61.1|4.9671|2.0|242.0|17.8|392.83|4.03|34.7|
|3|0.03237|0.0|2.18|0.0|0.458|6.998|45.8|6.0622|3.0|222.0|18.7|394.63|2.94|33.4|
|4|0.06905|0.0|2.18|0.0|0.458|7.147|54.2|6.0622|3.0|222.0|18.7|396.90|5.33|36.2|

### 5.3.4．単回帰

#### 5.3.4.1．与えるデータの準備

```python:
# カラムを指定してデータを表示
df[['RM']].head()

# 説明変数
data = df.loc[:, ['RM']].values

# dataリストの表示(1-5)
print(data[0:5])
```

> [[6.575]
>  [6.421]
>  [7.185]
>  [6.998]
>  [7.147]]

単回帰で使用する説明変数を取り出す。
ここでは単回帰なのでRM(部屋数)1つだけを使用する。1つなのでベクトル。
5件だけ表示してみた。

```python:
# 目的変数
target = df.loc[:, 'PRICE'].values

print(target[0:5])
```

> [24.  21.6 34.7 33.4 36.2]

目的変数を取り出す。
今回の単回帰では部屋数からこの価格を予測するという形になる。
5件だけ表示してみた。

#### 5.3.4.2．学習

```python:
# sklearnモジュールからLinearRegressionをインポート
from sklearn.linear_model import LinearRegression

# オブジェクト生成
model = LinearRegression()

# fit関数でパラメータ推定
model.fit(data, target)
```

scikit-learnで用意されているLinearRegressionを使用する。
fitに説明変数と目的変数を与えることで学習(平均二乗誤差を最小化)が行われる。

LinearRegressionのコンストラクタには特に指定していないので以下のようなデフォルト値が使われている。
> LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)

copy_X：説明変数をコピーするか。正規化すると値が変わるが影響を受けないようにすることできる。
fit_intercept：切片を計算するか。
n_jobs：並列に計算する数(恐らく)。
normalize：正規化するか。

#### 5.3.4.3．予測

```python:
# 予測
print(model.predict([[1]]))
```

> [-25.5685118]

部屋数1の住宅の価格がマイナスの金額が予測されてしまっている。
部屋数だけでは正しく予測は到底できていないことが分かる。

### 5.3.5．重回帰

```python:
# カラムを指定してデータを表示
df[['CRIM', 'RM']].head()

# 説明変数
data2 = df.loc[:, ['CRIM', 'RM']].values

# 目的変数
target2 = df.loc[:, 'PRICE'].values

# オブジェクト生成
model2 = LinearRegression()

# fit関数でパラメータ推定
model2.fit(data2, target2)

print(model2.predict([[0.2, 7]]))
```

||CRIM|RM
|-----:|-----:|-----:|
0|0.00632|6.575
1|0.02731|6.421
2|0.02729|7.185
3|0.03237|6.998
4|0.06905|7.147

予測結果

> [29.43977562]

説明変数の数が増えるだけでやり方は単回帰と同じ。
説明変数に犯罪発生率を表すCRIM列を増やしているだけで他は同じ。

予測結果は単回帰の時と比べてそれらしい数字になっている。

```python:
print(model2.predict([[0.3, 4]]))
```

> [4.24007956]

課題で提示されていた「部屋数が4で犯罪率は0.3の物件の価格」はこのようになる。
うーん、なんか安いので2変数でも足りなさそう(もしくは追加した犯罪発生率はあまり価格に影響していない)に思う。

```python:
df_tmp = df.query('CRIM>=0.2 & RM>=3 & CRIM<=0.4 & RM<=6')[['CRIM', 'RM', 'PRICE']]

print('最小：', df_tmp['PRICE'].min())
print('最大：', df_tmp['PRICE'].max())
print('平均：', df_tmp['PRICE'].mean())
```

> 最小： 8.1
> 最大： 24.5
> 平均： 18.308695652173917

実際に元データのうち、犯罪率と部屋数がわりと近いデータの価格を見てみるともっと高いことが分かる。

### 5.3.6．回帰係数と切片の値

```python:
# 単回帰の回帰係数と切片を出力
print('推定された回帰係数: %.3f, 推定された切片 : %.3f' % (model.coef_, model.intercept_))
```

> 推定された回帰係数: 9.102, 推定された切片 : -34.671

単回帰の回帰係数と切片。
coef_で回帰係数、intercept_で切片が確認できる。

```python:
# 重回帰の回帰係数と切片を出力
print(model2.coef_)
print(model2.intercept_)
```

> [-0.26491325  8.39106825]
> -29.24471945192992

重回帰の回帰係数と切片。
説明変数が2変数だったため回帰係数も2つあることが分かる。

### 5.3.7．決定係数
講義動画では省略されていますがせっかくなので。

#### 5.3.7.1．決定係数とは
決定係数$R^2$は予測値が実際の値(目的変数)にどれだけ当てはまっているか(どれだけズレが小さいか)。
値は0から1までの範囲であり、1に近いほど当てはまっていると言える。

```math
R^2=1-\frac{\sum^{n}_{i=1}(y_{i}-\hat{y})^2}{\sum^{n}_{i=1}(y_{i}-\bar{y})^2}
```

$y_{i}$：目的変数
$\hat{y_{i}}$：予測値
$\bar{y_{i}}$：目的変数の平均

```python:
# train_test_splitをインポート
from sklearn.model_selection import train_test_split

# 70%を学習用、30%を検証用データにするよう分割
X_train, X_test, y_train, y_test = train_test_split(data, target, test_size = 0.3, random_state = 666)

# 学習用データでパラメータ推定
model.fit(X_train, y_train)

# 作成したモデルから予測（学習用、検証用モデル使用）
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
```

train_test_splitは指定した割合でデータを分割できるもの。
random_stateを固定値にしているので常に同じように分割される。

学習には分割した70%の学習用データのみを使用している。

```python:
# matplotlibをインポート
import matplotlib.pyplot as plt
# Jupyterを利用していたら、以下のおまじないを書くとnotebook上に図が表示
%matplotlib inline

# 学習用、検証用それぞれで残差をプロット
plt.scatter(y_train_pred, y_train_pred - y_train, c = 'blue', marker = 'o', label = 'Train Data')
plt.scatter(y_test_pred, y_test_pred - y_test, c = 'lightgreen', marker = 's', label = 'Test Data')
plt.xlabel('Predicted Values')
plt.ylabel('Residuals')

# 凡例を左上に表示
plt.legend(loc = 'upper left')

# y = 0に直線を引く
plt.hlines(y = 0, xmin = -10, xmax = 50, lw = 2, color = 'red')
plt.xlim([10, 50])
plt.show()
```

![matplotlib.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389699/9f62f781-8a89-6241-65eb-02490d2f281d.png)


学習用データによる予測値(青)、検証用データによる予測値(緑)のプロット。
matplotlibを使って視覚的に表現することで分かりやすくなる。

```python:
# 平均二乗誤差を評価するためのメソッドを呼び出し
from sklearn.metrics import mean_squared_error

# 学習用、検証用データに関して平均二乗誤差を出力
print('MSE Train : %.3f, Test : %.3f' % (mean_squared_error(y_train, y_train_pred), mean_squared_error(y_test, y_test_pred)))

# 学習用、検証用データに関してR^2を出力
print('R^2 Train : %.3f, Test : %.3f' % (model.score(X_train, y_train), model.score(X_test, y_test)))
```

> MSE Train : 44.983, Test : 40.412
> R^2 Train : 0.500, Test : 0.434

平均二乗誤差$MSE$、決定係数$R^2$を出力した結果。
検証データの決定係数を見ると0.434しかないのでやはり精度は良くないことが分かる。

### 5.3.8．おまけ
せっかく説明変数が13個あるので全部使ってみる+値の範囲がバラバラ(パーセンテージなので最大が1の犯罪発生率に対してTAXやBは200、300とかある)なので標準化してみようと思います。

* 標準化

平均が0、標準偏差が1(もちろん分散も1)になるように変換すること。標準化変量やzスコアとも呼ぶ。応用数学の確率・統計レポートでもちょっと書きましたがこれは統計を使ったものですね。
機械学習を独学でやってた頃から標準化を知ってはいましたが統計であるということは知らなかったのでやはり数学や統計を学ぶのは大切です。

```python:
# 説明変数、目的変数を用意
data3 = boston.data
target3 = np.array(boston.target)
# 7:3で分割
X_train3, X_test3, y_train3, y_test3 = train_test_split(data3, target3, test_size = 0.3, random_state = 666)

from sklearn import preprocessing
ss = preprocessing.StandardScaler()
# 標準化に必要な統計情報を計算(検証データに同じ前処理を適用させられるよう学習データだけでやる)
train_fit = ss.fit(X_train3)
# 標準化
X_train3 = ss.transform(X_train3)
X_test3 = ss.transform(X_test3)

model3 = LinearRegression()
# 学習
model3.fit(X_train3, y_train3)
# 予測
y_train_pred3 = model3.predict(X_train3)
y_test_pred3 = model3.predict(X_test3)

# 残差をプロット
plt.scatter(y_train_pred3, y_train_pred3 - y_train3, c = 'blue', marker = 'o', label = 'Train Data')
plt.scatter(y_test_pred3, y_test_pred3 - y_test3, c = 'lightgreen', marker = 's', label = 'Test Data')
plt.xlabel('Predicted Values')
plt.ylabel('Residuals')
# 凡例を左上に表示
plt.legend(loc = 'upper left')
# y = 0に直線を引く
plt.hlines(y = 0, xmin = -10, xmax = 50, lw = 2, color = 'red')
plt.xlim([10, 50])
plt.show()

from sklearn.metrics import mean_absolute_error
# MSE
print('MSE  Train : %.3f, Test : %.3f' % (mean_squared_error(y_train3, y_train_pred3), mean_squared_error(y_test3, y_test_pred3)))
# RMSE
print('RMSE Train : %.3f, Test : %.3f' % (np.sqrt(mean_squared_error(y_train3, y_train_pred3)), np.sqrt(mean_squared_error(y_test3, y_test_pred3))))
# MAE
print('MAE  Train : %.3f, Test : %.3f' % (mean_absolute_error(y_train3, y_train_pred3), mean_absolute_error(y_test3, y_test_pred3)))
# 決定係数
print('R^2  Train : %.3f, Test : %.3f' % (model3.score(X_train3, y_train3), model3.score(X_test3, y_test3)))
```

![omake.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389699/4323911b-39c3-b628-fc88-31695c56e6cf.png)

> MSE  Train : 21.373, Test : 24.325
> RMSE Train : 4.623, Test : 4.932
> MAE  Train : 3.254, Test : 3.540
> R^2  Train : 0.763, Test : 0.659

importは追加で必要な分のみ記載しています。
決定係数見ると検証データで0.659となっており、まだまだであるものの改善していることが分かります。

(標準化のやり方間違ってないと思いますが、結果に変わりはなかったです…)

# X．ラビットチャレンジとは
ラビットチャレンジとは、日本ディープラーニング協会認定の講座プログラムの1つ。
E資格を受験するためにはこのラビットチャレンジ等、いずれかの講座プログラムを修了しなければならない。

ラビットチャレンジの特徴は「現場で潰しが効くディープラーニング講座」の通学講座録画ビデオを編集した教材を使用した自習スタイルであるという点。
サポートは他の講座より少なく、受け身ではなく自主的に学んでいく姿勢でなければ進められないが、その分、他の講座に比べると安価であり、手が出しやすい。
ある程度知識がある人、自力で頑張るぞというガッツのある人向けではないかと感じる。

![bnr_jdla.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389699/bce66671-a2f5-a7f9-de6f-3f87e15c253b.png)