筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (9)

前回
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (8) 確率的最急降下法を自作](https://qiita.com/legacyworld/items/663fcd8189f0bdf38f64)
https://github.com/legacyworld/sklearn-basic

# 課題 5.3 ヒンジ損失と二乗損失
2つの塊を分類するのだが、塊から大きく外れた外れ値がある場合とない場合で問題が分かれている。

## 外れ値無しのヒンジ損失
Youtubeの解説は第6回(1)の54分あたり
外れ値が無い方のヒンジ損失は実はscikit-learnのexampleそのままである。
SVMの部分よりもmatplotlibの使い方の方が難しかった。
元ネタはこれ　https://scikit-learn.org/stable/auto_examples/svm/plot_separating_hyperplane.html#sphx-glr-auto-examples-svm-plot-separating-hyperplane-py
自分の学習のためにコメントを追記した。

```python:Homework_5.3_hinge_no_outlier.py
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_blobs

# 40個のランダムな分類データセット作成　centersで塊の数を指定
X, y = make_blobs(n_samples=40, centers=2, random_state=6)
# kernel='linear'はヒンジ損失　Cが大きいほど正則化は効果が無くなる
clf = svm.SVC(kernel='linear', C=1000)
clf.fit(X, y)
#分類データを描画。cmapの部分で色を勝手に決めてくれる
plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)

# 決定境界の描画
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()

# 30x30の格子を作る
xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
# 各格子での分類
Z = clf.decision_function(xy).reshape(XX.shape)

# 等高線を使って決定境界を描画 level=0がそれにあたる
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
           linestyles=['--', '-', '--'])
# マージンが一番小さいサポートベクタを描画
ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=100,
           linewidth=1, facecolors='none', edgecolors='k')
plt.savefig("5.3.png")
```

実際に計算している部分は2行だけ。結果はこんな感じ。
![5.3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629456/a1d342a9-4060-4aa8-5b2f-f1c127d6bab5.png)

## 外れ値無しの二乗損失
これは解説映像にソースコードがあったので理解できたが、無ければまず無理だった。

```python:Homework_5.3_square_no_outlier.py
import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model
from sklearn.datasets import make_blobs

# 40個のランダムな分類データセット作成　centersで塊の数を指定
X, y = make_blobs(n_samples=40, centers=2, random_state=6)
# yの値を-1,1にする
y = y*2-1
# 二乗損失
clf = linear_model.LinearRegression(fit_intercept=True,normalize=True,copy_X=True)
clf.fit(X, y)
#分類データを描画。cmapの部分で色を勝手に決めてくれる
plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)

# 決定境界の描画
x_plot = np.linspace(4,10,100)
w = [clf.intercept_,clf.coef_[0],clf.coef_[1]]
y_plot = -(w[1]/w[2]) * x_plot - w[0]/w[2]
plt.plot(x_plot,y_plot)
plt.savefig("5.3.png")
```
考え方としては`make_blobs`で作った$X$が特徴量（2種類）、$y$が目標量として、線形重回帰を行う。
今回の例だと特徴量のサンプル数は40
上のグラフで横軸を$x_1$、縦軸を$x_2$として

```math
y = w_0 + w_1\times x_1 + w_2\times x_2
```
と表せる。
`make_blobs`では$y = 0,1$だがこれを`y = y*2-1`で$y = -1,1$に変えている。
$y=0$とすることで決定境界を描画することが出来る。

```math
0 = w_0 + w_1\times x_1 + w_2\times x_2 \\
x_2 = -\frac{w_0}{w_2} - \frac{w_1}{w_2}x_1
```
これがソースコードの最後の部分である。
描画したものがこれ。
![5.3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629456/75de8e13-62ed-eeb6-6831-380a9b7b1cee.png)

## この問題の意図
大きな外れ値が無い場合はヒンジ損失でも二乗損失でも同じような結果を得ることが出来る。
しかし大きな外れ値(Outlier)がある場合に、二乗損失では外れ値の損失が過大に見積もられてしまうため正しい結果を得ることが出来なくなる。
これは次回説明する。

# 過去の投稿
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (1)](https://qiita.com/legacyworld/items/a3763760e65774dc0e33)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (2)](https://qiita.com/legacyworld/items/5a72c83860c1d0b1d352)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (3)](https://qiita.com/legacyworld/items/c9cd7865efb343c42e5e)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (4)](https://qiita.com/legacyworld/items/9231c44206c8f0823ff5)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (5)](https://qiita.com/legacyworld/items/2d2db10024d7dfb5f89b)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (6)](https://qiita.com/legacyworld/items/e54c664fc138b75dd166)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (7) 最急降下法を自作](https://qiita.com/legacyworld/items/bdbb0cbdc5b9b33fd1eb)
https://github.com/legacyworld/sklearn-basic
https://ocw.tsukuba.ac.jp/course/systeminformation/machine_learning/