ラビットチャレンジ -機械学習編-

# はじめに
本記事は、E資格受験を得るためのレポート記事になります。
プログラム名は、ラビットチャレンジ。そして今回は、機械学習編です。

# 1.線形回帰モデル
線形回帰モデルとは、分類問題とは異なり入力値から流れを見出し推定し予測行う。

まずはじめに機械学習のモデルプロセスは次の通り。

問題設定→データ選定→データの前処理→機械学習（モデルの選定）→モデルの学習（パラメーター推定）→モデルの評価

本当に機械学習が必要なのか、操作を行う前に考える必要がある。
→場合によってはルールベース（if文）で行ったほうが良い時が多いので
問題設定が一番重要になってくる。（安易に機械学習を使用しないほうが無難）

回帰モデルとは、ある入力値からデータの流れを読み込み推測し出力値を算出する機械学習のひとつ。
回帰モデルには、大きく分けて線形回帰モデルと非線形回帰モデルが存在する。

・線形と非線形の違いについて
大雑把にいうと、線形とは直線（比例関係、線形回帰）を表現し、非線形とはそれ以外（曲線）を指す。

ちなみに線形回帰モデルは、教師あり学習があてはまる。

・パラメーター
→最小二乗法により推定。

```math
 w =(w_{1},w_{2}   ..w_{m}) \in R^m
```
※Rは実数を示す。

・線形結合
→入力とパラメータの内積になる。

```math
\hat{y} =w^Tx +w_{0} = \sum_{j=1}^{m}w_{j}x{j}+w_{0}
```

・モデル数式

```math
y=w_{0}+w_{1}x_{1}+w_{2}x_{2}+ε

```

※実装の際、うまくできない場合行列の型を確認するとよい。
#実装例
・単純回帰分析を用いたコードを下記に記載。
今回の対象レコードはボストンの住宅データセット。
実行環境は、google colaboratoryを使用しました。

```python

from sklearn.datasets  import load_boston
from pandas import DataFrame
import numpy as np

boston=load_boston()
df = DataFrame(data = boston.data,columns= boston.feature_names)
df['PRICE']= np.array(boston.target)

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


from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.get_params()
model.fit(data,target)
model.predict([[6]])


＞array([19.94203311])
```
以上により、部屋数が６の価格は、約19(千ドル)と予測される。

# 2.非線形回帰モデル
→線形回帰では予測できないモデルについて使用するモデル。
基本式は、線形モデルと同じだが、基底関数を用いて表現している

基底展開法
→回帰関数：基底関数(ex:多項式関数、ガウス型基底関数etc)
非線形回帰では、線形回帰モデルを基底展開法に適用し、予測を行うことができる。

```math

y=w_{0}+w_{1}x_{1}+w_{2}x_{2}
```
```math
y=\sum_{h=0}^{H}w_{n}\phi_{n}(x)
```

```math
\phi_{0}(x)=1,\phi_{1}(x)=x,\phi_{2}=x^2
```
```math
\phi_{n}(x)は基底関数を示す。
```


・未学習
→学習の段階で、大きな誤差がでる。

・過学習
→学習の段階では、誤差は大きいが未知のデータでは誤差が大きい。
対策：学習データを増やす、正則化法を使用する等。

・正則化
基底関数で用いた予測モデルでは、過学習になりやすいため、罰則項（正則化）を
用いてほどよい予測モデルに修正を行う。


・実装演習

```python
from google.colab import drive
drive.mount('/content/drive')

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

%matplotlib inline


sns.set()
sns.set_style("darkgrid", {'grid.linestyle': '--'})
sns.set_context("paper")

n=100

def true_func(x):
    z = 1-48*x+218*x**2-315*x**3+145*x**4
    return z 

def linear_func(x):
    z = x
    return z 

data = np.random.rand(n).astype(np.float32)
data = np.sort(data)
target = true_func(data)

noise = 0.5 * np.random.randn(n) 
target = target  + noise

plt.scatter(data, target)

plt.title('NonLinear Regression')
plt.legend(loc=2)
```
![非線形モデル.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207209/9feec8f6-21ff-6b53-18d3-968d03d3c9e6.png)

```python
from sklearn.linear_model import LinearRegression

clf = LinearRegression()
data = data.reshape(-1,1)
target = target.reshape(-1,1)
clf.fit(data, target)

p_lin = clf.predict(data)

plt.scatter(data, target, label='data')
plt.plot(data, p_lin, color='darkorange', marker='', linestyle='-', linewidth=1, markersize=6, label='linear regression')
plt.legend()
print(clf.score(data, target))
```
![非線形モデル2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207209/04bd5ae1-3976-443a-1556-431ca3cec34b.png)

```python
from sklearn.kernel_ridge import KernelRidge

clf = KernelRidge(alpha=0.0002, kernel='rbf')
clf.fit(data, target)

p_kridge = clf.predict(data)

plt.scatter(data, target, color='blue', label='data')

plt.plot(data, p_kridge, color='orange', linestyle='-', linewidth=3, markersize=6, label='kernel ridge')
plt.legend()
#plt.plot(data, p, color='orange', marker='o', linestyle='-', linewidth=1, markersize=6)
```

![非線形モデル3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207209/a4913f8f-25ca-65ad-0fe0-0a23cfe45947.png)

# 3.ロジスティック回帰モデル
・"回帰"とついているが、クラス"分類"にあてはまるので注意。
・目的のデータが、シグモイド関数を用いてどのクラスに属するか確率(0~1)で算出する。
→あとで出てくるタイタニックデータでは、生死を"生"を"1","死"を"0"で表記している。

・説明変数

```math
x = (x_{1},x_{2}.....x_{m})^T \in R^m
```
・目的変数

```math
y \in{0,1}
```
→（クラスは、"0"or"1"にわけられる）

・ロジスティック線形回帰
→入力とm次元パラメータの線形結合をシグモイド関数に入力

シグモイド関数の数式を下記に記載する

```math
\sigma(x) =\frac{1}{1+exp(-ax)}
```

ちなみにシグモイド関数は微分すると、シグモイド関数自身で表現することが可能。


```math
\frac{\delta\sigma(x)}{\delta x} = a\delta(x)(1-\delta(x))
```
・実装演習
対象は、タイタニックデータ。

```python
from google.colab import drive
drive.mount('/content/drive')

import pandas as pd
from pandas import DataFrame
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

%matplotlib inline

titanic_df = pd.read_csv('/content/drive/My Drive/study_ai_ml_google/data/titanic_train.csv')

titanic_df.drop(['PassengerId', 'Name', 'Ticket', 'Cabin'], axis=1, inplace=True)


titanic_df['AgeFill'] = titanic_df['Age'].fillna(titanic_df['Age'].mean())

titanic_df[titanic_df.isnull().any(1)]

data1 = titanic_df.loc[:, ["Fare"]].values
label1 =  titanic_df.loc[:,["Survived"]].values

from sklearn.linear_model import LogisticRegression
model=LogisticRegression()

model.fit(data1, label1)

model.predict_proba([[62]])

>array([[0.49978123, 0.50021877]])
```

以上により運賃が62ドルだったひとの生き乗る確率(約0.50)と亡くなる確率(約0.499)が
算出される。

# 4.主成分分析
データの変数を削減するために使われる手法（PCA）。次元削減は、たくさんの変数を持つデータを特徴を保ちながら、少数の変数で表現するといった意味を持つ。

・アルゴリズム
1.分散共分散行列を計算する
2.分散共分散行列に対して、固有値問題を解き固有ベクトル、固有値を求める。
3.各主成分方向にデータを表現する。

分散共分散行列に対して、固有値問題を解くことが「分散を最大化するような直交する軸を求める」という問題と数学的に等しいものになっている。

・実装演習
scikit-learn に入っているアヤメデータにおいて４つある説明変数を２つの主成分に
変換する。

```python
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris

data = load_iris()
n_components = 2

model = PCA(n_components=n_components)
model = model.fit(data.data)
print(model.transform(data.data))

[[-2.68412563  0.31939725]
 [-2.71414169 -0.17700123]
 ～略～
 [ 1.39018886 -0.28266094]]
```

# 5.サポートベクターマシーン
線形サポートベクトルマシーン（SVM）では、マージンを最大化することで分類するのによい決定境界を得ることが可能になる。ちなみにマージンとは、学習データのうち最も決定境界に近いものと決定境界との距離を指す。
また、マージンにはハードマージンとソフトマージンが存在する。
直線で綺麗に分離できるようなマージンの内側にデータが入り込むのを許容しないことものをハードマージンと呼び、反対に一部のデータがマージンの内側に入ることを許容するものをソフトマージンと呼ぶ。

・実装演習
今回は、線形サポートベクトルマシンを使い二値分類問題に適用する。

```python
from sklearn.svm import LinearSVC
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

centers = [(-1, -0.125), (0.5, 0.5)]
X,y = make_blobs(n_samples=50,n_features=2,centers=centers,cluster_std=0.3)
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size= 0.3)

model = LinearSVC()
model.fit(X_train,y_train)
y_pred = model.predict(X_test)
accuracy_score(y_pred,y_test)

>1.0
```

検証データより、正解率は1.0と算出される。

# 6.参考図書
[機械学習図鑑](https://www.amazon.co.jp/%E8%A6%8B%E3%81%A6%E8%A9%A6%E3%81%97%E3%81%A6%E3%82%8F%E3%81%8B%E3%82%8B%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF-%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E5%9B%B3%E9%91%91-%E7%A7%8B%E5%BA%AD-%E4%BC%B8%E4%B9%9F/dp/4798155659)