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


線形回帰

理論(要点まとめ1点)

直線のみで予測する

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

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

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

演習(実装演習結果1点)

ボストンの住宅データセットを用いた線形回帰のモデル作成。
課題は以下の通り。

部屋数が4で犯罪率が0.3の物件はいくらになるか?

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

なお、以下の2点はラビットチャレンジのドキュメントが正しくなさそう ・Google Driveのマウントの方法(古い) ・課題データのURL(存在しないと言われる)

非線形回帰モデル

理論(要点まとめ1点)

非線形の関数のみで予測する

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

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

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

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

Lassoの場合はスパースになる

演習(実装演習結果1点)

課題は特になし。
実装のコードがあるので、回して遊んでみる。
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))

ロジスティック回帰

理論(要点まとめ1点)

分類問題を解くための教師あり機械学習モデル(教師データから学習)
入力データとm次元パラメータの線形結合をシグモイド関数に入力して、y=1になる確率の値を出力するモデル

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

演習(実装演習結果1点)

タイタニックの乗客データを利用し、ロジスティック回帰モデルを作成。
課題は以下の通り。

年齢が30歳で男の乗客は生き残れるか?

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

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

上の図では、横軸が運賃であり、
- 青点が0であったデータ点
- オレンジ点が0となる確率
- 緑点が1となる確率
- 赤線がシグモイド関数の出力値
のようである。念の為、オレンジと緑の合計が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%くらいの確率で生存しそうです。

主成分分析

理論(要点まとめ1点)

多変量データの持つ構造をより少数個の指標に圧縮するときに使う。

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

分散共分散行列は、

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

主成分分析を計算する手順

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

演習(実装演習結果1点)

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

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

演習問題関連の発展(1点)

第三主成分まで含めるた場合について、自身で実装演習。
結果としては、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近傍法

理論(要点まとめ1点)

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

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

個人的な気づき

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

演習(実装演習結果1点)

課題

人口データと分類結果をプロットしてください

とあるが、人口データが見つからなくなってしまっているようだ。
そこで、ダミーデータの生成を行い、分類をおこなった。

k平均法

理論

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

k平均法を計算する手順

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

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

演習

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

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

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

Support Vector Machine

理論(要点まとめ1点)

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

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

演習(実装演習結果1点)

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

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)

分離すると以下のような図になる。

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