E資格ラビットチャレンジレポート　〜機械学習まとめ〜

#線形回帰
##理論（要点まとめ１点）
直線のみで予測する

```math
 \boldsymbol{\hat{y}} = \boldsymbol{w}^T\boldsymbol{x} + w_0
```

係数$w$は最小二乗法で求める。
個人的に感じたメリットは以下の通り。

:::note info
結果が理解しやすい
計算負荷が小さい
説明変数の重要度を係数の大小で比較できる（説明変数は正規化しておく必要）
:::

##演習（実装演習結果１点）
ボストンの住宅データセットを用いた線形回帰のモデル作成。
課題は以下の通り。
>部屋数が4で犯罪率が0.3の物件はいくらになるか？

この２変数だけで回帰するモデルを作成する想定だと解釈して、演習を行った。

:::note warn
なお、以下の２点はラビットチャレンジのドキュメントが正しくなさそう
・Google Driveのマウントの方法(古い)
・課題データのURL（存在しないと言われる）
:::
![スクリーンショット 2021-09-12 1.19.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009520/1be7f08e-6ecd-1b33-69e8-26a4c8e26a73.png)

#非線形回帰モデル
##理論（要点まとめ１点）
非線形の関数のみで予測する

```math
 \boldsymbol{\hat{y_i}} = \boldsymbol{w}^T\phi(\boldsymbol{x_i}) + w_0 + \epsilon_i
```

係数$w$は最小二乗法や最尤法で求める。
$ \phi $に使われる関数は、多項式関数やガウス型基底関数、スプライン関数、Bスプライン関数などがある。

過学習を防止するために、以下の二つの方法を学んだ。
 * 不要な基底関数を削除
 * 正則化法(罰則化法)

なお、正則化項の入れ方で名前が変わる。
L2ノルムの場合：Ridge推定量
L1ノルムの場合：Lasso推定量

:::note info
Lassoの場合はスパースになる
:::

##演習（実装演習結果１点）
課題は特になし。
実装のコードがあるので、回して遊んでみる。
100乗くらいの多項式入れてあげると、過学習してる様子が見て取れる。

```
deg = [100]
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))
```

![スクリーンショット 2021-09-12 2.03.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009520/813797df-e85c-6ae0-0365-b210bff8aa35.png)


#ロジスティック回帰
##理論（要点まとめ１点）
分類問題を解くための教師あり機械学習モデル(教師データから学習)
入力データとm次元パラメータの線形結合をシグモイド関数に入力して、y=1になる確率の値を出力するモデル

```math
p_i = \sigma( \boldsymbol{w}^T\boldsymbol{x} + w_0)
```

ちなみに、ロジスティック回帰モデルは一般化線形モデルの一種らしい。
https://ja.wikipedia.org/wiki/%E3%83%AD%E3%82%B8%E3%82%B9%E3%83%86%E3%82%A3%E3%83%83%E3%82%AF%E5%9B%9E%E5%B8%B0

##演習（実装演習結果１点）
タイタニックの乗客データを利用し、ロジスティック回帰モデルを作成。
課題は以下の通り。
>年齢が30歳で男の乗客は生き残れるか？

１）単純にまずは、コードを動かしてみる。

:::note warn
Google Driveのマウントのセルは削除して、Googleの誘導に従った
データ保存場所も異なっていたので変えた
:::

![スクリーンショット 2021-09-12 2.28.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009520/36af87a1-004d-7943-26db-97ece807f6f2.png)

上の図では、横軸が運賃であり、
- 青点が０であったデータ点
- オレンジ点が０となる確率
- 緑点が1となる確率
- 赤線がシグモイド関数の出力値
のようである。念の為、オレンジと緑の合計が１になることを確認した。

2）課題用のモデルを作成し、回答を作成する。

```
data2 = titanic_df.loc[:, ["AgeFill", "Gender"]].values
label2 =  titanic_df.loc[:,["Survived"]].values
model2 = LogisticRegression()
model2.fit(data2, label2)
model2.predict([[40,1]])
model2.predict_proba([[40,1]])
```
結果は以下の通り。
array([[0.81529326, 0.18470674]])
82%くらいの確率で生存しそうです。

#主成分分析
##理論（要点まとめ１点）
多変量データの持つ構造をより少数個の指標に圧縮するときに使う。

学習データが１つあたり、m次元ベクトル
それがn個存在するとした時に、
データ行列$\bar{X}$は、n*m行列で、（各学習データ-平均ベクトル）

分散共分散行列は、

```math
\frac{\bar{X^T} \bar{X}}{n}
```

###主成分分析を計算する手順
1.分散共分散行列を計算
2.固有値問題を解く
3.(最大)m個の固有値と固有ベクトルのペアを得る



##演習（実装演習結果１点）

>32次元のデータを2次元上に次元圧縮した際に、うまく判別できるかを確認。

![スクリーンショット 2021-09-12 13.43.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009520/51a0ff7e-8af3-a196-fef1-36799a49e1a3.png)

かなり上手く分類できているようである。
60%程度の情報は復元できる様子。

##演習問題関連の発展（１点）
第三主成分まで含めるた場合について、自身で実装演習。
結果としては、70%くらいまで判別できる割合が上がった。


```
pca = PCA(n_components=3)
X_train_pca = pca.fit_transform(X_train_scaled)
print('explained variance ratio: {}'.format(pca.explained_variance_ratio_))
```
#アルゴリズム
#k近傍法
##理論（要点まとめ１点）

最近傍のデータをk個取ってきて、それらがもっとも多く所属するクラスに識別

:::note info
ポイント
- kを大きくすると決定境界は滑らかになる
:::

###個人的な気づき
k=1の場合を考えると、各データ点と最近傍のデータ点を結ぶ垂直二等分線を境界に分類されそう。
データ点が１個増えるごとに境界線が結構動く可能性があるので、堅牢性は低そう。


##演習（実装演習結果１点）
###課題
>人口データと分類結果をプロットしてください

とあるが、人口データが見つからなくなってしまっているようだ。
そこで、ダミーデータの生成を行い、分類をおこなった。
![スクリーンショット 2021-09-12 14.46.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009520/bd3ed955-deb1-4ae9-fbef-51d4928db353.png)


#k平均法
##理論
教師なし学習のクラスタリング手法で、与えられたデータをk個のクラスタに分類する


###k平均法を計算する手順
1.各クラスタ中心の初期値を設定する
2.各データ点に対して、各クラスタ中心との距離を計算し、最も距離が近いクラスタを割り当てる
3.各クラスタの平均ベクトル（中心）を計算する
4.収束するまで2, 3の処理を繰り返す

:::note warn
初期値の取り方で結果が変わる点に注意
:::

##演習
ワインのクラスタリング
本質的にクラスタリングに関わるプログラムは以下の部分。

```
model = KMeans(n_clusters=3)
labels = model.fit_predict(X)
```

上側のコードで指定しているクラスターの数を変更することで、異なる数のクラスターに分類することができる。


#Support Vector Machine
##理論（要点まとめ１点）
元来2クラス分類問題を解くための手法として発展してきた。
マージン最大化するような境界を選ぶ。
分離可能性を仮定したSV分類のことを一般にハードマージン(hard margin)と呼ぶ。
逆に多少の誤分類を許容したSV分類は、ソフトマージンと呼ぶ。
スラック変数(slack variable)と呼ばれるもので、どこまで誤分類を許容するか決める。
スラック変数にかかる係数Cが正則化係数と呼ばれる。

:::note info
正則化係数C→∞の極限で、ハードマージンになる。
:::

##演習（実装演習結果１点）

ランダムな線形分離可能なデータを生成して、ＳＶＭで境界線の決定を行う。

```
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
```
ただし、上で作成したデータは、0と1のラベルがついているので、
学習させるまでに、1と-1に変換しておく必要がある。

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

分離すると以下のような図になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009520/22aab105-789d-1fb3-806b-43aeebfa7c60.png)


より発展的には、ガウシアンカーネルなどを使えば、線形分離できない場合にも対応できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009520/0cc5b8f4-eac3-0d63-42d1-4f1464d537c8.png)