ラビットチャレンジレポート＿機械学習

**線形回帰モデル**
回帰問題を解くための機械学習モデルのひとつ。教師あり学習。
入力と出力との関係が1次式によっておおよそ表現可能な場合に有効なモデルで、
「入力をパラメータwで重み付けした和＋バイアス」によって出力を決定される。

線形回帰モデルの学習は
・外れ値の影響を強く受ける。
・多重共線性に注意する
といったことを意識する必要がある。

$$\hat{y} =w_0 + \boldsymbol{w^Tx}   = w_0 + w_1x_1 + \cdots + w_ix_i$$

（線形であるのはパラメータwに関してで、入力に関しては非線形でも可。）

最小二乗法
学習データの平均二乗誤差を最小にするパラメータを探索
その勾配が０になる点を求めれば良い

$$MSE_{train}=\frac{1}{n}\sum_{i=1}^n(y_i- \hat{y}_i)^2$$

平均二乗誤差（残差平方和）
データとモデルの２乗誤差の和
データは既知のため、パラメータのみに依存する関数

線形回帰のサンプルコード
（ボストンの家賃価格データセットを用いての実装例）

```
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression

# データの読み込み、変換
boston=load_boston()
df = pd.DataFrame(boston.data)
df.columns = boston.feature_names
df['PRICE'] = pd.DataFrame(boston.target)
df.head()

# 説明変数（RM）をX、目的変数（PRICE）をYに格納
X = df[['RM']].values
Y = df["PRICE"].values

# モデルを構築し、学習
model = LinearRegression()
model.fit(X,Y)　

# 学習済のモデルで予測
y_pred = model.predict(X)　　
print('傾き： ' , model.coef_)
print('切片： ' ,  model.intercept_)

```



**非線形回帰モデル**
学習パラメータと目的変数との関係が線形になっていないモデル

回帰を実行するにあたり、未学習と過学習の対策が必要。

未学習：学習データに対して、十分小さな誤差が見られない
　対策→表現力の高いモデルを採用する。

過学習：手元のデータに対して小さな誤差が得られるが、必要以上にフィットしてしまい汎化ができない
　対策→学習データ数を増やす、不要な基底関数を削除する、正則化を行う。

正則化:
損失関数に罰則項を組み込むことで、次数が大きくなった時のパラメータを抑え、モデルの複雑さを緩和すること。複雑なモデルが過学習を起こす原因として、学習パラメータが極端に大きい（または小さい）ことが挙げられる。罰則項は、学習パラメータの絶対値が大きくなることに対して、損失が大きくなるような罰則を与える役割を持っている。

L1ノルムを利用する場合の回帰を、Lasso回帰
L2ノルムを利用する場合の回帰を、Ridge回帰　と言う。

Lasso回帰：
いくつかのパラメータを0に推定する。
影響の小さい変数を0に推定するため、説明変数を選ぶ指標となる。
特徴選択を目的に用いられることもある。
$$||w||=|w_0|+|w_1|+\cdots+|w_d|$$

Ridge回帰：
パラメータを0に近づけるよう推定する。
L1ノルムよりコストがかかるが精度向上に役立つ。
$$||w||^2=w_0^2+w_1^2\cdots+w_d^2$$

汎化誤差
未知のデータをどれだけ精度良く予測できた、モデルの性能を表す指標。
$$MSE_{test}=\frac{1}{n_{test}}\sum_{i=1}^{n_{test}}{(\hat{y}^{test}-y^{test})^2}$$

汎化誤差は誤差、バイアス、バリアンスに分解できる。
バイアス:モデルの予測と目的変数との平均のズレ
バリアンス：モデルの複雑さ(分散)
であり、
低バリアンス・高バイアス：表現力が低いモデル
高バリアンス・低バイアス：表現力が高いモデル
である。

作成されたモデルの汎化性能を検証するためにホールドアウト法やK-分割交差検証法（交差検証法）がある

ホールドアウト法：
データ集合をふたつに分け、一方を訓練用、もう一方をテスト用として用いる評価方法

K-分割交差検証法：
データ集合をK個に分け、ひとつをテスト用、残りを訓練用とする。
テスト集合を入れ替えながらK回の検証を行い、その平均などの指標で評価する。

学習データや検証データの相性が偶然に左右される場合があるため、交差検証を行うことが推奨される。

非線形回帰のサンプルコード
（ボストンの家賃価格データセットを用いての実装例）

```
import numpy as np
import pandas as pd
from pandas import DataFrame
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

# データの読み込み、変換
boston = load_boston()
df = DataFrame(boston.data, columns = boston.feature_names)
df['MEDV'] = np.array(boston.target)

# 説明変数
X = df.loc[:, ['LSTAT']].values
# 目的変数
y = df.loc[:, 'MEDV'].values

# モデルのインスタンス生成
mod = LinearRegression()
# 2次までの変数を作成するインスタンス
quadratic = PolynomialFeatures(degree = 2)
# 3次までの変数を作成するインスタンス
cubic = PolynomialFeatures(degree = 3)

# 変数作成
X_quad = quadratic.fit_transform(X)
X_cubic = cubic.fit_transform(X)

# モデル式用に変数を作成
X_fit = np.arange(X.min(), X.max(), 1)[:, np.newaxis]

# 線形回帰モデル
mod_lin = mod.fit(X, y)
y_lin_fit = mod_lin.predict(X_fit)
r2_lin = mod.score(X, y)
# 2次の項を追加
mod_quad = mod.fit(X_quad, y)
y_quad_fit = mod_quad.predict(quadratic.fit_transform(X_fit))
r2_quad = mod.score(X_quad, y)
# 3次の項を追加
mod_cubic = mod.fit(X_cubic, y)
y_cubic_fit = mod_cubic.predict(cubic.fit_transform(X_fit))
r2_cubic = mod.score(X_cubic, y)

# 各モデルの結果をプロット
plt.scatter(X, y, label = 'Traning points', color = 'lightgray')
# 線形モデルのモデル式
plt.plot(X_fit, y_lin_fit)
# 2次
plt.plot(X_fit, y_quad_fit)
# 3次
plt.plot(X_fit, y_cubic_fit)
plt.xlabel('LSTAT')
plt.ylabel('MEDV')
plt.legend(loc = 'upper right')
plt.show()

```


**ロジスティック回帰モデル**
教師あり学習。分類を行うアルゴリズム。
主に２クラス分類に用いられる手法。

ロジスティック回帰では確率を計算するため出力の範囲を0以上1以下に制限する必要がある

シグモイド関数　$σ(z)=\frac{1}{1+exp({-z})}$

を用いて、データx与えられたときに、そのラベルがyである確率pを計算する。

$$p=σ(w_0 + w^TX)$$

閾値を設定し、
閾値より小さい場合 -> yの予測値は0 
閾値以上の場合 -> yの予測値は1
と判定をする。




ロジスティック回帰のサンプルコード
（irisのデータセットを用いての実装例）


```
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

# データの読み込み、変換
data = load_iris()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = pd.DataFrame(data.target, columns=['Species'])
df = pd.concat([X, y], axis=1)
df.head()

# 品種 setosa、versicolorを抽出
df2 = df[(df['Species']==0) | (df['Species']==1)]
# 説明変数
X = df2.iloc[:, [2, 3]]
# 目的変数
y = df2.iloc[:, 4]
# 学習データと検証データを分割
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

# モデルを構築し学習
model = LogisticRegression()
model.fit(X_train, y_train)

# 切片
print(model.intercept_)
# 傾き
print(model.coef_)

w_0 = model.intercept_
w_1 = model.coef_[0, 0]
w_2 = model.coef_[0, 1]

x1 = np.linspace(0, 6, 30)
x2 = (-w_1 * x1 - w_0) / w_2

# 表に出力する
plt.plot(x1, x2, color='gray')
plt.scatter(X.iloc[:, 0][y==0], X.iloc[:, 1][y==0], color='lightskyblue', label=data.target_names[0])
plt.scatter(X.iloc[:, 0][y==1], X.iloc[:, 1][y==1], color='sandybrown', label=data.target_names[1])
plt.ylim(-0.25, 2)
plt.xlabel(X.columns[0])
plt.ylabel(X.columns[1])
plt.legend()
plt.show()

```



**主成分分析**
教師なし学習。
多数のデータの持つ構造を、重要な一部の変数に次元を削減する分析手法。

主成分分析のサンプルコード
（ボストンの家賃価格データセットを用いての実装例）

```
from sklearn.datasets import load_boston
from sklearn.decomposition import PCA
import pandas as pd

# データの読み込み、変換
boston = load_boston()
df = pd.DataFrame(boston.data, columns=boston.feature_names)

# ３次元に次元圧縮
pca = PCA(n_components=3)
df_pca = pca.fit_transform(df)

# 次元圧縮後のデータを確認
print(df_pca)
# 固有値を出力
print('固有値:', pca.explained_variance_)
# 寄与率を出力
print('寄与率:', pca.explained_variance_ratio_)

```

**サポートベクターマシーン**
主に２クラス分類で用いられるアルゴリズム。

線形判別関数（決定境界）と最も近いデータ点との距離をマージンとよび、マージンが最大化されるような線形判別関数を求める。
　線形判別関数： $w^Tx+b=0$

識別面を決定する一部のデータのことをサポートベクトルという。

サポートベクトルマシーンにはデータを分類するための超平面を求めて、データの分類を行なっている。その超平面の計算方法として、ハードマージン法とソフトマージン法がある。

ハードマージン法は、データが空間上できれいにクラスごとに分離している場合だけに適用できる。これに対して、ソフトマージン法は、データがきれいに分離していなくても適用でき、その適用範囲は広い。ソフトマージン法では、教師データが間違って分類された場合に、ペナルティを与えることで誤分類に対応している。この後識別に対するペナルティを表現するのがスラック変数である。

カーネルトリックを利用することで、複雑な決定境界を学習することができる。
　カーネル関数： $k(xi,xj)=ϕ(x_i)^Tϕ(x_j)$

サポートベクターマシンのサンプルコード
（irisのデータセットを用いての実装例）

```
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.svm import SVC

# データの読み込み、変換
iris = load_iris()

dataset = pd.DataFrame(data = iris['data'], columns = iris['feature_names'])
dataset['species'] = iris['target']
dataset.head()

# 目的変数(Y)、説明変数(X)
Y = np.array(dataset['species'])
X = np.array(dataset[iris['feature_names']])

# データの分割
from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=0)

# モデルを構築し、学習
model = SVC(gamma='scale')
model.fit(X_train, Y_train)

# 学習済のモデルで予測
Y_pred = model.predict(X_test)
print(Y_test[:10])
print(Y_pred[:10])

```


**この記事の参考図書**
「機械学習のエッセンス」加藤公一
「ゼロから作るDeepLearning」 斎藤康毅

〜Fin〜