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

(1)線形回帰モデル

回帰問題は、ある入力から出力を予測する問題で、直線で予測するときは線形回帰、曲線なら非線形回帰という。

回帰で扱うデータは、入力がn次元のベクトルで、出力はスカラー値である。

線形回帰モデルは、回帰問題を解くための機械学習モデルである。

教師あり学習は、教師データから学習するモデルの総称である

線形回帰のモデルの推定するべき未知のパラメータ$w$は
$$w=(w_1,w_2,w_3,\cdots,w_n)^T\in\mathbb{R^n}$$
切片を$b_1$とする
予測値を $\hat{y}\in\mathbb{R}$ とすると、
$$\hat{y}=w^Tx+b_1=\sum_{k=1}^n x_k w_k+b_1$$

データの分割は、モデルの汎化性能を測定するために行うもので、学習用データ(機械学習モデルの学習に利用するデータ)、検証用データ(学習済みモデルの精度を検証するためのデータ)に分割する。

線形回帰モデルのパラメータは最小二乗法で推定する。このとき、平均二乗誤差(MSE)という関数を用いる。
$$MSE_{\rm train}=\frac{1}{n_{\rm train}}\sum_{k=1}^{n_{\rm train}}\Big(\hat{y_k}-y_k\Big)^2$$

平均二乗誤差はパラメータに依存する関数なので、最小化は、その勾配が零になる点を求めることと言える。
$w$を微分して0になる$w$を求める。
$$\frac{\partial}{\partial w}MSE_{\rm train}=0$$

(2)線形回帰実装演習

``` python
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression
import pandas as pd
import numpy as np

boston = load_boston()

print(boston.feature_names)
```
> ['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
 'B' 'LSTAT']

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

``` python
train_X = df.loc[:, ['RM', 'CRIM']].values
train_y = df.loc[:, 'PRICE'].values
model = LinearRegression()
model.fit(train_X, train_y)
```
> LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)

``` python
print(model.coef_)
print(model.intercept_)
print(model.predict([[4, 0.3]]))
```
>[ 8.39106825 -0.26491325]
-29.24471945192995
[4.24007956]

これらから、部屋数4、犯罪率0.3の場合は、物件の価格は4240ドルと予測された。今回用いたデータセットにはいくつか不適切と思われる変数が見られた。この予測には使用しなかったが、何かしらの予測の際にはデータを整えなければならないことに注意すべきである。


(3)非線形回帰モデル
複雑な非線形構造の事柄には非線形回帰モデルを使って予測を行う。データの構造が線形として扱える場合とそうで無い場合があり、それらの区別が必要である。

基底展開法は回帰関数に基底関数を使うものである。未知パラメータの推定には最尤法等を用いる。

(例)

多項式関数
$$\phi_i(x)=x^i$$

ガウス型基底関数

$$\phi_i(x)=\exp \Bigg\(\frac{(x-\mu_i)^2}{2h_i}\Bigg)$$

未学習は、学習データとの誤差が未だ大きいモデルで、より高い表現力が必要である。

過学習は、学習データとの誤差は小さいが、未知のデータに対して誤差が大きいモデルで、正則化やより多くのデータが必要である。

正則化法は、モデルが複雑になると値が大きくなる正則化項を加えた関数を最適化するもので、正則化項にはL1ノルムやL2ノルムがある。
$$S_{\gamma}=(y-\Phi w)^T(y-\Phi w)+\gamma R(w)$$

正則化項が無いときの推定量を最小二乗推定量、L2ノルムを用いたときはリッジ推定量、L2ノルムを用いたときはラッソ推定量という。
$$R(w)=\sqrt{\sum_{k=1}^n w_k^2}=\sqrt{w_1^2+w_2^2+w_3^2+\cdots +w_n^2}$$
$$R(w)=\sum_{k=1}^n|w_k|=|w_1|+|w_2|+|w_3|+\cdots +|w_n|$$

ホールドアウト法は、データを学習用と検証用に分割して精度を評価する方法である。データが有限であることから、評価の精度と学習の精度はトレードオフとなるので、データが十分多い場合でなければ適切に評価出来ない。

交差検証法は、データを複数に分割してそのうち1つを検証データ、その他を学習データとして学習と評価を繰り返して平均で評価する方法である。

グリッドサーチは乱数でパラメータを決定して、そのうち最も良い評価値を持つパラメータの組み合わせを探すものである。

(4)非線形回帰実装演習

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

``` python
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)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/0a3aacca-37e1-16d5-a02f-6692b3053d53.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))
```
> 0.2972077836133967
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/760191b2-dc65-fc39-b075-cf546e9afb88.png)

``` python
from sklearn.kernel_ridge import KernelRidge

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

p_kridge = clf.predict(data)
print(clf.score(data, target))

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()
```
> 0.825000625105667
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/f0c26866-e966-52e5-f62c-4b837c842a67.png)

``` python
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
deg = [1,2,3,4,5,6,7,8,9,10]
for d in deg:
    regr = Pipeline([
        ('poly', PolynomialFeatures(degree=d)),
        ('linear', LinearRegression())
    ])
    regr.fit(data, target)
    p_poly = regr.predict(data)
    plt.scatter(data, target, label='data')
    plt.plot(data, p_poly, label='polynomial of degree %d' % (d))
```
>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/e8f698c1-c0b2-6f62-f74b-238d9e272dff.png)

``` python
from sklearn import model_selection, preprocessing, linear_model, svm

clf_svr = svm.SVR(kernel='rbf', C=1e3, gamma=0.1, epsilon=0.1)
clf_svr.fit(data, target)
y_rbf = clf_svr.fit(data, target).predict(data)

plt.scatter(data, target, color='darkorange', label='data')
plt.plot(data, y_rbf, color='red', label='Support Vector Regression (RBF)')
plt.legend()
plt.show()
```
>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/5bb529e8-066f-3827-8264-7112f304f602.png)

``` python
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.1, random_state=0)
from keras.callbacks import EarlyStopping, TensorBoard, ModelCheckpoint

cb_cp = ModelCheckpoint('out/checkpoints/weights.{epoch:02d}-{val_loss:.2f}.hdf5', verbose=1, save_weights_only=True)
cb_tf  = TensorBoard(log_dir='out/tensorBoard', histogram_freq=0)

def relu_reg_model():
    model = Sequential()
    model.add(Dense(10, input_dim=1, activation='relu'))
    model.add(Dense(1000, activation='relu'))
    model.add(Dense(1000, activation='relu'))
    model.add(Dense(1000, activation='relu'))
    model.add(Dense(1000, activation='relu'))
    model.add(Dense(1000, activation='relu'))
    model.add(Dense(1000, activation='relu'))
    model.add(Dense(1000, activation='relu'))
    model.add(Dense(1000, activation='linear'))
    model.add(Dense(1))

    model.compile(loss='mean_squared_error', optimizer='adam')
    return model

from keras.models import Sequential
from keras.layers import Input, Dense, Dropout, BatchNormalization
from keras.wrappers.scikit_learn import KerasRegressor

estimator = KerasRegressor(build_fn=relu_reg_model, epochs=100, batch_size=5, verbose=1)

history = estimator.fit(x_train, y_train, callbacks=[cb_cp, cb_tf], validation_data=(x_test, y_test))
y_pred = estimator.predict(x_train)
```

(5)ロジスティック回帰モデル

ロジスティック回帰は教師ありの分類モデルで、出力の際に活性化関数としてシグモイド関数を用いるので、出力を確率として解釈できる。

シグモイド関数は、全ての実数を定義域、(0,1)を値域とする関数である。
微分した形を自分自身だけで表せる。
$$\sigma(x)=\frac{1}{1+\exp(-ax)}=\frac{1}{1+e^{-ax}}$$
$$\sigma^{\prime}(x)=a\sigma(x)\big(1-\sigma(x) \big)$$
$$P(Y=1|x)=\sigma(w_0+w_1x_1+w_2x_2+w_3x_3+\cdots+w_mx_n)$$

最尤推定法は、尤度関数を最大化させる未知のパラメータを探す方法である。

尤度関数は、1回の試行で$y=y_1$となる確率である。
$$p(y)=p^y(1-p)^{1-y}$$

$n$回の試行で$y_1,y_2,y_3,\cdots,y_n$が同時に起こる確率。
$$P(y_1,y_2,y_3,\cdots,y_n ;p)=\prod_{i=1}^np^{y_i}(1-p)^{1-y_i} \\
=\prod_{i=1}^n \Big(\sigma(w^Tx_i) \Big)^{y_i}\Big(1-\sigma(w^Tx_i)\Big)^{1-y_i} \\
= L(w)$$

最尤推定法は、尤度関数が対数をとると微分を計算しやすい、対数尤度関数と尤度関数が同時に最大になる、対数関数が単調増加であることから、対数尤度関数を用いる。

勾配降下法は目的関数の勾配を繰り返し計算することでパラメータを逐次的に更新する方法である。

(モデルの評価指標の例)

正解率
$$\frac{TP+TN}{TP+FN+FP+TN}$$

再現率
$$\frac{TP}{TP+FN}$$

適合率
$$\frac{TP}{TP+FP}$$

F値（再現率と適合率の調和平均）
$$\frac{2}{\frac{1}{Recall}+\frac{1}{Precision}}=\frac{2(Precision)(Recall)}{Recall+Precision}$$

(6)ロジスティック回帰実装演習

``` python
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('../data/titanic_train.csv')

titanic_df.head(5)
```

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

titanic_df[titanic_df.isnull().any(1)].head(10)
```

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

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

``` python
data1 = titanic_df.loc[:, ["Fare"]].values
label1 =  titanic_df.loc[:,["Survived"]].values
from sklearn.linear_model import LogisticRegression
model=LogisticRegression()
model.fit(data1, label1)
```
> LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
                   intercept_scaling=1, l1_ratio=None, max_iter=100,
                   multi_class='warn', n_jobs=None, penalty='l2',
                   random_state=None, solver='warn', tol=0.0001, verbose=0,
                   warm_start=False)

``` python
model.predict([[61]])
```
> array([0])


``` python
model.predict_proba([[62]])
```
> array([[0.49968899, 0.50031101]])

``` python
print (model.intercept_)
print (model.coef_)
```
> [-0.93290045]
[[0.01506685]]

``` python
titanic_df['Gender'] = titanic_df['Sex'].map({'female': 0, 'male': 1}).astype(int)

titanic_df['Pclass_Gender'] = titanic_df['Pclass'] + titanic_df['Gender']

titanic_df = titanic_df.drop(['Pclass', 'Sex', 'Gender','Age'], axis=1)
```

``` python
np.random.seed = 0

xmin, xmax = -5, 85
ymin, ymax = 0.5, 4.5

index_survived = titanic_df[titanic_df["Survived"]==0].index
index_notsurvived = titanic_df[titanic_df["Survived"]==1].index

from matplotlib.colors import ListedColormap
fig, ax = plt.subplots()
cm = plt.cm.RdBu
cm_bright = ListedColormap(['#FF0000', '#0000FF'])
sc = ax.scatter(titanic_df.loc[index_survived, 'AgeFill'],
                titanic_df.loc[index_survived, 'Pclass_Gender']+(np.random.rand(len(index_survived))-0.5)*0.1,
                color='r', label='Not Survived', alpha=0.3)
sc = ax.scatter(titanic_df.loc[index_notsurvived, 'AgeFill'],
                titanic_df.loc[index_notsurvived, 'Pclass_Gender']+(np.random.rand(len(index_notsurvived))-0.5)*0.1,
                color='b', label='Survived', alpha=0.3)
ax.set_xlabel('AgeFill')
ax.set_ylabel('Pclass_Gender')
ax.set_xlim(xmin, xmax)
ax.set_ylim(ymin, ymax)
ax.legend(bbox_to_anchor=(1.4, 1.03))
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/7f3b9637-04e9-44fb-c7cf-8ccd7770fae6.png)


``` python
data2 = titanic_df.loc[:, ["AgeFill", "Pclass_Gender"]].values
label2 =  titanic_df.loc[:,["Survived"]].values
model2 = LogisticRegression()
model2.fit(data2, label2)
```
> LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
                   intercept_scaling=1, l1_ratio=None, max_iter=100,
                   multi_class='warn', n_jobs=None, penalty='l2',
                   random_state=None, solver='warn', tol=0.0001, verbose=0,
                   warm_start=False)

``` python
model2.predict([[10,1]])
```
> array([1], dtype=int64)

``` python
model2.predict_proba([[10,1]])
```
> array([[0.06072391, 0.93927609]])

``` python
h = 0.02
xmin, xmax = -5, 85
ymin, ymax = 0.5, 4.5
xx, yy = np.meshgrid(np.arange(xmin, xmax, h), np.arange(ymin, ymax, h))
Z = model2.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:, 1]
Z = Z.reshape(xx.shape)

fig, ax = plt.subplots()
levels = np.linspace(0, 1.0)
cm = plt.cm.RdBu
cm_bright = ListedColormap(['#FF0000', '#0000FF'])

sc = ax.scatter(titanic_df.loc[index_survived, 'AgeFill'],
                titanic_df.loc[index_survived, 'Pclass_Gender']+(np.random.rand(len(index_survived))-0.5)*0.1,
                color='r', label='Not Survived', alpha=0.3)
sc = ax.scatter(titanic_df.loc[index_notsurvived, 'AgeFill'],
                titanic_df.loc[index_notsurvived, 'Pclass_Gender']+(np.random.rand(len(index_notsurvived))-0.5)*0.1,
                color='b', label='Survived', alpha=0.3)

ax.set_xlabel('AgeFill')
ax.set_ylabel('Pclass_Gender')
ax.set_xlim(xmin, xmax)
ax.set_ylim(ymin, ymax)

x1 = xmin
x2 = xmax
y1 = -1*(model2.intercept_[0]+model2.coef_[0][0]*xmin)/model2.coef_[0][1]
y2 = -1*(model2.intercept_[0]+model2.coef_[0][0]*xmax)/model2.coef_[0][1]
ax.plot([x1, x2] ,[y1, y2], 'k--')
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/af459b81-1f40-787f-7928-588862e6f19f.png)

``` python
from sklearn.model_selection import train_test_split
traindata1, testdata1, trainlabel1, testlabel1 = train_test_split(data1, label1, test_size=0.2)
traindata2, testdata2, trainlabel2, testlabel2 = train_test_split(data2, label2, test_size=0.2)
data = titanic_df.loc[:, ].values
label =  titanic_df.loc[:,["Survived"]].values
traindata, testdata, trainlabel, testlabel = train_test_split(data, label, test_size=0.2)
eval_model1=LogisticRegression()
eval_model2=LogisticRegression()
predictor_eval1=eval_model1.fit(traindata1, trainlabel1).predict(testdata1)
predictor_eval2=eval_model2.fit(traindata2, trainlabel2).predict(testdata2)
```

``` python
eval_model1.score(traindata1, trainlabel1)
```
> 0.6558988764044944

``` python
eval_model1.score(testdata1,testlabel1)
```
> 0.6983240223463687

``` python
eval_model2.score(traindata2, trainlabel2)
```
> 0.7893258426966292

``` python
eval_model2.score(testdata2,testlabel2)
```
> 0.7206703910614525

``` python
from sklearn import metrics
print(metrics.classification_report(testlabel1, predictor_eval1))
print(metrics.classification_report(testlabel2, predictor_eval2))
```

``` python
from sklearn.metrics import confusion_matrix
confusion_matrix1=confusion_matrix(testlabel1, predictor_eval1)
confusion_matrix2=confusion_matrix(testlabel2, predictor_eval2)
confusion_matrix1
```
> array([[107,  10],
       [ 44,  18]], dtype=int64)

``` python
confusion_matrix2
```
> array([[92, 13],
       [37, 37]], dtype=int64)

``` python

import seaborn as sns
sns.set(style="whitegrid")

titanic = sns.load_dataset("titanic")

g = sns.PairGrid(titanic, y_vars="survived",
                 x_vars=["class", "sex", "who", "alone"],
                 size=5, aspect=.5)

g.map(sns.pointplot, color=sns.xkcd_rgb["plum"])
g.set(ylim=(0, 1))
sns.despine(fig=g.fig, left=True)

plt.show()
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/0cf62755-5507-fc3b-dfcd-fd9bfff8befc.png)


``` python

import seaborn as sns
sns.set(style="darkgrid")

df = sns.load_dataset("titanic")

pal = dict(male="#6495ED", female="#F08080")

g = sns.lmplot(x="age", y="survived", col="sex", hue="sex", data=df,
               palette=pal, y_jitter=.02, logistic=True)
g.set(xlim=(0, 80), ylim=(-.05, 1.05))
plt.show()
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/2a46acc3-4e0b-e4cc-aa2e-6b121403b924.png)

(7)主成分分析

多変量データの情報をなるべく保ったまま指標の数を減らす方法で、次元削減や
データの可視化に用いられる。1次元データの第一主成分の分散は、元の分散と一致する。また、第k主成分の分散は主成分に対応する固有値となっている。

寄与率は、第k主成分の分散の全分散に対する割合で、第1-k主成分まで圧縮した時点での情報損失量の割合を累積寄与率という。

(8)主成分分析ハンズオン

``` python
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegressionCV
from sklearn.metrics import confusion_matrix
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
%matplotlib inline
cancer_df = pd.read_csv('../data/cancer.csv')

cancer_df.drop('Unnamed: 32', axis=1, inplace=True)
cancer_df
```

``` python
y = cancer_df.diagnosis.apply(lambda d: 1 if d == 'M' else 0)
X = cancer_df.loc[:, 'radius_mean':]

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

logistic = LogisticRegressionCV(cv=10, random_state=0)
logistic.fit(X_train_scaled, y_train)

print('Train score: {:.3f}'.format(logistic.score(X_train_scaled, y_train)))
print('Test score: {:.3f}'.format(logistic.score(X_test_scaled, y_test)))
print('Confustion matrix:\n{}'.format(confusion_matrix(y_true=y_test, y_pred=logistic.predict(X_test_scaled))))
```
> Train score: 0.988
Test score: 0.972
Confustion matrix:
[[89  1]
 [ 3 50]]

``` python
pca = PCA(n_components=30)
pca.fit(X_train_scaled)
plt.bar([n for n in range(1, len(pca.explained_variance_ratio_)+1)], pca.explained_variance_ratio_)
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/25f7369c-c927-b6cc-2ba9-e074a2d9ec35.png)


``` python
pca = PCA(n_components=2)
X_train_pca = pca.fit_transform(X_train_scaled)
print('X_train_pca shape: {}'.format(X_train_pca.shape))

print('explained variance ratio: {}'.format(pca.explained_variance_ratio_))

temp = pd.DataFrame(X_train_pca)
temp['Outcome'] = y_train.values
b = temp[temp['Outcome'] == 0]
m = temp[temp['Outcome'] == 1]
plt.scatter(x=b[0], y=b[1], marker='o')
plt.scatter(x=m[0], y=m[1], marker='^') 
plt.xlabel('PC 1')
plt.ylabel('PC 2') 
```
> X_train_pca shape: (426, 2)
explained variance ratio: [0.43315126 0.19586506]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/179741c6-c158-9bc4-2854-dff96a6fb5a9.png)

(9)k-NN

k-NNは、教師なしの分類モデルで、近い方からk(奇数)個データ点を取り、より多くデータ点が属するクラスに分類するものである。kの値によって分類結果も変わり、一般にkの値が大きいほど決定境界はなめらかになる。

(10)k近傍法実装演習

``` python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
```

``` python
def gen_data():
    x0 = np.random.normal(size=50).reshape(-1, 2) - 1
    x1 = np.random.normal(size=50).reshape(-1, 2) + 1.
    x_train = np.concatenate([x0, x1])
    y_train = np.concatenate([np.zeros(25), np.ones(25)]).astype(np.int)
    return x_train, y_train
```

``` python
X_train, ys_train = gen_data()
plt.scatter(X_train[:, 0], X_train[:, 1], c=ys_train)
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/d41e7131-4ef8-b522-7826-4254fb6832b4.png)

``` python
def distance(x1, x2):
    return np.sum((x1 - x2)**2, axis=1)

def knc_predict(n_neighbors, x_train, y_train, X_test):
    y_pred = np.empty(len(X_test), dtype=y_train.dtype)
    for i, x in enumerate(X_test):
        distances = distance(x, X_train)
        nearest_index = distances.argsort()[:n_neighbors]
        mode, _ = stats.mode(y_train[nearest_index])
        y_pred[i] = mode
    return y_pred

def plt_resut(x_train, y_train, y_pred):
    xx0, xx1 = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100))
    xx = np.array([xx0, xx1]).reshape(2, -1).T
    plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
    plt.contourf(xx0, xx1, y_pred.reshape(100, 100).astype(dtype=np.float), alpha=0.2, levels=np.linspace(0, 1, 3))
```

``` python
n_neighbors = 3

xx0, xx1 = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100))
X_test = np.array([xx0, xx1]).reshape(2, -1).T

y_pred = knc_predict(n_neighbors, X_train, ys_train, X_test)
plt_resut(X_train, ys_train, y_pred)
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/cb59dfa8-21dc-9bb6-e47d-8365614c8e1e.png)

``` python
xx0, xx1 = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100))
xx = np.array([xx0, xx1]).reshape(2, -1).T
```

``` python
from sklearn.neighbors import KNeighborsClassifier
knc = KNeighborsClassifier(n_neighbors=n_neighbors).fit(X_train, ys_train)
plt_resut(X_train, ys_train, knc.predict(xx))
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/ac822be8-43a6-4278-7511-5a6a5c8327ba.png)

(11)k-means

k-meansは、教師なしのクラスタリングモデルである。アルゴリズムは(1.クラスターの中心の初期値を設定する。2.各データ点に、各中心との距離からクラスターを割り当てる。3.クラスターの中心を計算する。4.収束するまで2と3を繰り返す。)というものである。kの値や最初のクラスターの中心で結果が変わる。
(12)k-means実装演習

``` python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
```

``` python
def gen_data():
    x1 = np.random.normal(size=(100, 2)) + np.array([-5, -5])
    x2 = np.random.normal(size=(100, 2)) + np.array([5, -5])
    x3 = np.random.normal(size=(100, 2)) + np.array([0, 5])
    return np.vstack((x1, x2, x3))

X_train = gen_data()
plt.scatter(X_train[:, 0], X_train[:, 1])
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/02bf24b6-5eec-9a5b-e836-ddd7eb6aca51.png)


``` python
def distance(x1, x2):
    return np.sum((x1 - x2)**2, axis=1)

n_clusters = 3
iter_max = 100

centers = X_train[np.random.choice(len(X_train), n_clusters, replace=False)]

for _ in range(iter_max):
    prev_centers = np.copy(centers)
    D = np.zeros((len(X_train), n_clusters))
    for i, x in enumerate(X_train):
        D[i] = distance(x, centers)
    cluster_index = np.argmin(D, axis=1)
    for k in range(n_clusters):
        index_k = cluster_index == k
        centers[k] = np.mean(X_train[index_k], axis=0)
    if np.allclose(prev_centers, centers):
        break
```

``` python
def plt_result(X_train, centers, xx):
    plt.scatter(X_train[:, 0], X_train[:, 1], c=y_pred, cmap='spring')
    plt.scatter(centers[:, 0], centers[:, 1], s=200, marker='X', lw=2, c='black', edgecolor="white")
    pred = np.empty(len(xx), dtype=int)
    for i, x in enumerate(xx):
        d = distance(x, centers)
        pred[i] = np.argmin(d)
    plt.contourf(xx0, xx1, pred.reshape(100, 100), alpha=0.2, cmap='spring')
```

``` python
y_pred = np.empty(len(X_train), dtype=int)
for i, x in enumerate(X_train):
    d = distance(x, centers)
    y_pred[i] = np.argmin(d)

xx0, xx1 = np.meshgrid(np.linspace(-10, 10, 100), np.linspace(-10, 10, 100))
xx = np.array([xx0, xx1]).reshape(2, -1).T

plt_result(X_train, centers, xx)
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/45cf7040-c829-284b-651a-c95338b9635b.png)

``` python
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3, random_state=0).fit(X_train)

print("labels: {}".format(kmeans.labels_))
print("cluster_centers: {}".format(kmeans.cluster_centers_))
kmeans.cluster_centers_
```

``` python
plt_result(X_train, kmeans.cluster_centers_, xx)
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/83789bd4-d935-8d38-7d94-e91ba8dbb07f.png)


(13)SVM

SVMは、2値分類モデルである。線形の決定境界によってデータ点を分類する。決定境界とそれに最も近いデータ点であるサポートベクトルの距離をマージンといい、これを最大化するのがSVMの目的である。

$$\frac{\| w^{\rm T}x_i+b\| }{ \| \| x \| \|}=\frac{t_i( w^{\rm T}x_i+b) }{ \| \| x \| \|}$$

$w$(パラメータ)、$x$(説明変数)、$b$(切片)、$t_i$(分類)

$$\min_{i}\frac{t_i( w^{\rm T}x_i+b) }{ \| \| w \| \|}$$
$$\max_{w,b}\bigg(\min_{i}\frac{t_i( w^{\rm T}x_i+b) }{ \| \| w \| \|}\bigg)$$

$t_i( w^{\rm T}x_i+b)=1$
$t_i( w^{\rm T}x_i+b)\geqq 1$
$$\max_{w.b}=\frac{1}{\| \| w \| \|}$$

SVMの目的関数は制約条件の下で、ラグランジュ未定乗数法によって解く。
$$\min_{w.b}\frac12 \| \| w \| \|$$
$$t_i( w^{\rm T}x_i+b)\geqq 1\qquad (i=1,2,3,\cdots,n)$$

$$L(w,b,a)=\frac{1}{2}\| \| w \| \|^2 -\sum_{i=1}^n a_i \Big(t_i( w^{\rm T}x_i+b)-1\Big) $$
$a_i\geqq 0\quad (i=1,2,3,\cdots,n)$(ラグランジュ乗数)
$$\frac{\partial L}{\partial w}=w-\sum_{i=1}^na_it_ix_i=0$$
$$\frac{\partial L}{\partial b}=-\sum_{i=1} a_it_i=0$$

$$w=\sum_{i=1}^na_it_ix_i$$
$$\sum_{i=1} a_it_i=0$$

(14)SVM実装演習

``` python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

def gen_data():
    x0 = np.random.normal(size=50).reshape(-1, 2) - 2.
    x1 = np.random.normal(size=50).reshape(-1, 2) + 2.
    X_train = np.concatenate([x0, x1])
    ys_train = np.concatenate([np.zeros(25), np.ones(25)]).astype(np.int)
    return X_train, ys_train

X_train, ys_train = gen_data()
plt.scatter(X_train[:, 0], X_train[:, 1], c=ys_train)
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/d4a79454-4f62-51cf-9cef-f532420af15d.png)

``` python
t = np.where(ys_train == 1.0, 1.0, -1.0)

n_samples = len(X_train)
K = X_train.dot(X_train.T)

eta1 = 0.01
eta2 = 0.001
n_iter = 500

H = np.outer(t, t) * K

a = np.ones(n_samples)
for _ in range(n_iter):
    grad = 1 - H.dot(a)
    a += eta1 * grad
    a -= eta2 * a.dot(t) * t
    a = np.where(a > 0, a, 0)
```

``` python
index = a > 1e-6
support_vectors = X_train[index]
support_vector_t = t[index]
support_vector_a = a[index]

term2 = K[index][:, index].dot(support_vector_a * support_vector_t)
b = (support_vector_t - term2).mean()

xx0, xx1 = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100))
xx = np.array([xx0, xx1]).reshape(2, -1).T

X_test = xx
y_project = np.ones(len(X_test)) * b
for i in range(len(X_test)):
    for a, sv_t, sv in zip(support_vector_a, support_vector_t, support_vectors):
        y_project[i] += a * sv_t * sv.dot(X_test[i])
y_pred = np.sign(y_project)

plt.scatter(X_train[:, 0], X_train[:, 1], c=ys_train)
plt.scatter(support_vectors[:, 0], support_vectors[:, 1],
                    s=100, facecolors='none', edgecolors='k')
plt.contour(xx0, xx1, y_project.reshape(100, 100), colors='k',
                     levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])

plt.quiver(0, 0, 0.1, 0.35, width=0.01, scale=1, color='pink')
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/e3531a5a-0b64-f4fe-344b-2dd3da9816cc.png)

``` python
factor = .2
n_samples = 50
linspace = np.linspace(0, 2 * np.pi, n_samples // 2 + 1)[:-1]
outer_circ_x = np.cos(linspace)
outer_circ_y = np.sin(linspace)
inner_circ_x = outer_circ_x * factor
inner_circ_y = outer_circ_y * factor

X = np.vstack((np.append(outer_circ_x, inner_circ_x),
               np.append(outer_circ_y, inner_circ_y))).T
y = np.hstack([np.zeros(n_samples // 2, dtype=np.intp),
               np.ones(n_samples // 2, dtype=np.intp)])
X += np.random.normal(scale=0.15, size=X.shape)
x_train = X
y_train = y

plt.scatter(x_train[:,0], x_train[:,1], c=y_train)
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/8689e50a-854c-0fca-75d6-e76af03470cd.png)

``` python
def rbf(u, v):
        sigma = 0.8
        return np.exp(-0.5 * ((u - v)**2).sum() / sigma**2)
    
X_train = x_train
t = np.where(y_train == 1.0, 1.0, -1.0)

n_samples = len(X_train)
K = np.zeros((n_samples, n_samples))
for i in range(n_samples):
    for j in range(n_samples):
        K[i, j] = rbf(X_train[i], X_train[j])

eta1 = 0.01
eta2 = 0.001
n_iter = 5000

H = np.outer(t, t) * K

a = np.ones(n_samples)
for _ in range(n_iter):
    grad = 1 - H.dot(a)
    a += eta1 * grad
    a -= eta2 * a.dot(t) * t
    a = np.where(a > 0, a, 0)
```

``` python
index = a > 1e-6
support_vectors = X_train[index]
support_vector_t = t[index]
support_vector_a = a[index]

term2 = K[index][:, index].dot(support_vector_a * support_vector_t)
b = (support_vector_t - term2).mean()

xx0, xx1 = np.meshgrid(np.linspace(-1.5, 1.5, 100), np.linspace(-1.5, 1.5, 100))
xx = np.array([xx0, xx1]).reshape(2, -1).T

X_test = xx
y_project = np.ones(len(X_test)) * b
for i in range(len(X_test)):
    for a, sv_t, sv in zip(support_vector_a, support_vector_t, support_vectors):
        y_project[i] += a * sv_t * rbf(X_test[i], sv)
y_pred = np.sign(y_project)

plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
plt.scatter(support_vectors[:, 0], support_vectors[:, 1],
                    s=100, facecolors='none', edgecolors='k')
plt.contourf(xx0, xx1, y_pred.reshape(100, 100), alpha=0.2, levels=np.linspace(0, 1, 3))
plt.contour(xx0, xx1, y_project.reshape(100, 100), colors='k',
                     levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/7b2b5601-4812-23c4-5a05-1885c28bdaa5.png)

``` python
x0 = np.random.normal(size=50).reshape(-1, 2) - 1.
x1 = np.random.normal(size=50).reshape(-1, 2) + 1.
x_train = np.concatenate([x0, x1])
y_train = np.concatenate([np.zeros(25), np.ones(25)]).astype(np.int)
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/2a3c1ea6-032a-bc95-02d1-49dbe1f2a3ff.png)

``` python
X_train = x_train
t = np.where(y_train == 1.0, 1.0, -1.0)

n_samples = len(X_train)
K = X_train.dot(X_train.T)

C = 1
eta1 = 0.01
eta2 = 0.001
n_iter = 1000

H = np.outer(t, t) * K

a = np.ones(n_samples)
for _ in range(n_iter):
    grad = 1 - H.dot(a)
    a += eta1 * grad
    a -= eta2 * a.dot(t) * t
    a = np.clip(a, 0, C)
```

``` python
index = a > 1e-8
support_vectors = X_train[index]
support_vector_t = t[index]
support_vector_a = a[index]

term2 = K[index][:, index].dot(support_vector_a * support_vector_t)
b = (support_vector_t - term2).mean()

xx0, xx1 = np.meshgrid(np.linspace(-4, 4, 100), np.linspace(-4, 4, 100))
xx = np.array([xx0, xx1]).reshape(2, -1).T

X_test = xx
y_project = np.ones(len(X_test)) * b
for i in range(len(X_test)):
    for a, sv_t, sv in zip(support_vector_a, support_vector_t, support_vectors):
        y_project[i] += a * sv_t * sv.dot(X_test[i])
y_pred = np.sign(y_project)

plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
plt.scatter(support_vectors[:, 0], support_vectors[:, 1],
                    s=100, facecolors='none', edgecolors='k')
plt.contourf(xx0, xx1, y_pred.reshape(100, 100), alpha=0.2, levels=np.linspace(0, 1, 3))
plt.contour(xx0, xx1, y_project.reshape(100, 100), colors='k',
                     levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])
```
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043122/200de08c-561e-a29f-bbc4-cdeb200be5e6.png)