ラビットチャレンジレポート #6 線形回帰

# 線形回帰
### まず線形とは？
* 1次関数
* もっと簡単に言うと直線

### 線形回帰
* 線形が1次関数であることから、線形回帰は2次元の話っぽいということがわかる。
* 入力 $X$と出力$Y$の2次元
* 例えば、部屋数と家賃をまとめたデータがあるとする。
    * 入力$x$を部屋数、出力$y$を家賃として考えてみる
    * このとき、
        * xを特徴量、説明変数という
        * yを目的変数という
    * 部屋数（入力$x$）から家賃（出力$y$）がいくらになるか予測したい
    * 下記図のように部屋数と家賃を表す図がある
    * 図から部屋数が多ければ多いほど家賃が高くなっていることがわかる
    * このとき赤線を求めることができれば部屋数から家賃がわかりそう！
    * すべての青い丸から赤い線までの距離の平均が1番小さい直線を見つけることで正確な予測ができそう！
    * **では、どうやって赤線を求めるか？**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183979/51e36a7e-7d31-3bf9-1328-d991fa6a7fbb.png)

* 以上を下記のようにまとめて式にしてみる
    * $\hat{y}$が予測したい家賃（出力）
    * $x_1$が部屋数（入力）
    * $w_1$が赤線の傾きで$w_0$が切片

```math
\hat{y} = w_1x_1+w_0
```

* いい感じの$w_0$と$w_1$を求めることで部屋数から家賃の予測ができる

### 部屋数と駅の近さから家賃を予測したいときは？
* 先ほど部屋数から家賃を求めるときは$\hat{y} = w_1x_1+w_0$でいけそうとわかった
* じゃあ、駅の近さも入力にするとどうなるか考えていく
* 入力が増えるから$z=ax+by+c$みたいな3次元の式になるのか？
* つまり入力が増えれば増えるほど次元数が上がる？
* 下記のように整理してから式を書いてみる
    * $x_1$が部屋数
    * $x_2$が駅の近さ
    * $w_0$、$w_1$、$w_2$はパラメータ

```math
\hat{y} = w_1x_1+w_2x_2+w_0
```

* $w$と$x$を行列またはベクトルとして考えたら1次関数になりそう！

```math
w = \{w_1,w_2\}\\
X = \{x_1,x_2\}\\
\hat{y} = wX+w_0
```

* それぞれまとめて$w$を転置してものと$X$の計算で出力($\hat{y}$)が求められる！
* $w_0$も$w$の一部として考えると線形回帰の式は下記のようになる

```math
w = \{w_0,w_1,w_2\}\\
X = \{x_1,x_2\}\\
\hat{y} = w^TX+\varepsilon
```

* $\varepsilon$は誤差を表す

### 最小二乗法
* 線形回帰の式はわかった！
* ここで重要なのはパラメータ（傾き）をどうやって求めるか
* パラメータが分からなければ結果の予測はできない！
* そこで使うのが **平均二乗誤差**
* 平均二乗誤差とは・・
    * データとモデル出力の二乗誤差の和
    * つまりは、実際の値と予測した値の差を2乗したものの平均
    * この誤差が小さければ小さいほどいいパラメータと言える
    * 平均二乗誤差の式は下記

```math
MSE= \frac{1}{n} \sum^n_{i=1}(\hat{y_i}-y_i)^2
```

* だから誤差が最小になるときのパラメータを求めたい！
        * この最小の平均二乗誤差を求めることを**最小二乗法** という


* 平均二乗誤差（MSE）が最小の時って？
    * それは！傾きが0のとき！
    * 傾きが0って？
        * それは！$w$で微分した値が0になるとき！
* $w$で微分ってMSEの式に$w$ないんやんけ
* $\hat{y}$の式を思い出してそれを使うとよい
* $\hat{y} = wX+\varepsilon$だったのでこれをMSEの式に代入する（誤差は小さいものとして考えない）

```math
MSE= \frac{1}{n}((wX)-y_i)^2
```
* 代入した時に$\sum$が消えるのは$w$と$X$に入力orパラメータがすべて含まれているから
* 行列式の二乗は転置を使って表現するので下記になる

```math
MSE= \frac{1}{n}(wX-y)^T(wX-y)
```

* これを展開すると最終的に下記になる
    * MSEが最小の値、微分したときに0になる値を見つけるための計算だから左辺を0にしとく

```math
0= 2X^TXw-2X^Ty
```
* 求めたいのはパラメータ$w$なので

```math
2X^TXw= 2X^Ty
```

* 両辺2でわる
* 左辺にある$（X^TX）$が邪魔なので左辺の左から$（X^TX）$の逆行列をかける

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

* こんな感じでパラメータ（傾き）を求める

## 実際にやってみた！
### Dataの準備・確認
* scikit learnで用意されているボストンのデータセットを使いました

https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_boston.html

* boston dataをimportしてとりあえず絡むチェックしてみます。

```python
### Check Columns

print(boston["feature_names"])

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

* カラムの意味が分からないので確認します

```python
print(boston["DESCR"])

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

* 上記の結果から今回は下記2つを使っていこうと思う
    * CRIM : 町ごとの 1 人当たりの犯罪率
    * RM : 平均部屋数
* dataをDataFrameにセットしていきます
* boston datasetsの目的変数（target）をPRICEとしてDataFrameにセット

``` python
df = DataFrame(data=boston.data, columns=boston.feature_names)

df['PRICE']=np.array(boston.target)
```

### dataの分布
* まず部屋数と家賃の関係

```python
plt.scatter(x=df.RM, y=df.PRICE, s=10)

plt.xlabel("RM")
plt.ylabel("PRICE")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183979/b8a98913-01fd-3596-5ea5-2aadf93e9c0a.png)

* やっぱり部屋数が多いほど家賃は高そう

* 次に犯罪率と家賃の関係

```python
plt.scatter(x=df.CRIM, y=df.PRICE, s=10)

plt.xlabel("CRIM")
plt.ylabel("PRICE")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183979/a1a64c44-1185-0b35-ec29-3611394a1e7f.png)

* もう少し右下がりになるかなと思ったけど・・・
* 40%以上が少ないのに他と値が離れているからx軸を20くらいまでで再度みてみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183979/61223479-ec36-99c7-f949-3e80a9ea151b.png)

* 右下がりといえば右下がり・・？
* そもそも犯罪率ってどんな感じなんだろう？みてみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183979/df9588c5-fdb4-7765-a4ba-af06ae4b41a4.png)

* ヒストグラム作成してみたけど、そもそも約10%以下がほとんどみたい
* そんなしょっちゅう犯罪起きるわけじゃないし当然と言えば当然か
* 明らかに犯罪率が高いときは家賃に影響しそうだけど、ほとんどの場合は家賃予測に使えないかもな～
* まぁ、一旦部屋数と犯罪率でみていきます

### 予測
* 特徴量として使う予定の犯罪率と部屋数をdataにセット！
* 目的変数の家賃をtargetにセット！

```python
data = df.loc[:,['CRIM','RM']].values
target = df.loc[:,['PRICE']].values
```

* 次にパラメータを推定する
* ゴリゴリ計算しなくても便利な関数fitがあるのでそれを使います。

```python
# Create object
model = LinearRegression()
model.get_params()

model.fit(data, target)
```

* では、作成したモデルにいろんな値をいれて予測してみる！

```python
## 犯罪率10, 部屋数8のとき
model.predict([[10, 8]])
# array([[35.23469401]])

## 犯罪率0、部屋数8のとき
model.predict([[0, 8]])
# array([[37.88382652]])

## 犯罪率0、部屋数10のとき
model.predict([[0, 10]])
# array([[54.66596301]])

## 犯罪率0、部屋数3のとき
model.predict([[0, 3]])
# array([[-4.07151471]])
```

* この結果から下記がわかる
    * 部屋数が同じときは犯罪率が引くほうが家賃が安い
    * 犯罪率が同じとき部屋数が多いほど家賃が安い
    * 部屋数が多いほうが家賃高い、犯罪率が高いほうが家賃が安いのは納得
    * 犯罪率より部屋数のほうが家賃に関係してそう
    * 犯罪率が0で部屋数が3のとき家賃はマイナス
        * **おかしい！**

* さすがに家賃がマイナスになるのはおかしい！
* データに異常値や外れ値が入ってたか、そもそも使っている特徴量がよくない可能性大
* そもそも線形でfitするのがよくない可能性もある
* そもそも学習データに部屋数3のデータがなくて予測できてない可能性も・・
    * ヒストグラムみてみましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183979/2e774c66-4e6c-5fc3-d1f5-4626c4b9d248.png)

* ちょっとあるのか・・？
* 小さい順から並べてみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183979/bca55418-b63d-c433-eed2-af10005eeea8.png)

* 3以下はないみたい
* 学習データに部屋数3がないから正しくできていない可能性もある

* このように様々な理由が考えられるのでいろいろ見てみてモデルの精度を上げていく必要がありそう