Python機械学習プログラミング 達人データサイエンティストによる理論と実践 part. 2
Python機械学習プログラミング 達人データサイエンティストによる理論と実践
前回の復習
人口ニューロン
重み $\boldsymbol{w} = [w_{1}, \cdots , w_{m}]^{\mathrm{T}}$,訓練データ $\boldsymbol{x} = [x_{1}, \cdots , x_{m}]^{\mathrm{T}}$ の線形結合である総入力 $z = \boldsymbol{w}^{\mathrm{T}} \boldsymbol{x}$ を引数に持つ決定関数を
\begin{align} \phi(z) = \begin{cases} 1 & (z \geq \theta) \cr -1 & (z < \theta) \end{cases} \end{align}
とします.$\theta$ はしきい値です.
上記を簡略化するために,$w_0 = -\theta$, $x_{0} = 1$ として,総入力を $z = w_{0}x_{0} + \boldsymbol{w}^{\mathrm{T}} \boldsymbol{x}$ とし,
\begin{align} \phi(z) = \begin{cases} 1 & (z \geq 0) \cr -1 & (z < 0) \end{cases} \end{align}
とします.
ソースコード
update = self.eta * (target - self.predict(xi))
この部分はパーセプトロンの更新式において,$η(y - \hat{y})$ に該当します.
第2章
ADALINE
コスト関数 $J(\cdot)$ として,
\begin{align} J(\boldsymbol{w}) = \dfrac{1}{2} \sum_{i}(\hat{y} - \phi(z)) \end{align}
を最小化する $\boldsymbol{w}$ を勾配降下法によって求めます.
更新式は,
\begin{align} \boldsymbol{w} \leftarrow \boldsymbol{w} + \Delta \boldsymbol{w} \end{align}
\begin{align} \Delta \boldsymbol{w} = -η \Delta J(\boldsymbol{w}) \end{align}
であり,
\begin{align} \dfrac{\partial J}{\partial w_{i}} = - \sum_{i} (\hat{y} - \phi (z)) \end{align}
です.
adaline.py
import numpy as np class AdalineGD(object): def __init__(self, eta=0.01, n_iter=50, random_state=1): self.eta = eta self.n_iter = n_iter self.random_state = random_state def fit(self, X, y): rgen = np.random.RandomState(self.random_state) self.w_ = rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1]) self.cost_ = [] for i in range(self.n_iter): net_input = self.net_input(X) output = self.activation(net_input) errors = (y - output) self.w_[1:] += self.eta * X.T.dot(errors) self.w_[0] += self.eta * errors.sum() cost = (errors**2).sum() / 2.0 self.cost_.append(cost) return self def net_input(self, X): return np.dot(X, self.w_[1:]) + self.w_[0] def activation(self, X): return X def predict(self, X): return np.where(self.activation(self.net_input(X)) >= 0.0, 1, -1)
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10, 4)) ada1 = adaline.AdalineGD(n_iter=10, eta=0.01).fit(X, y) ax[0].plot(range(1, len(ada1.cost_) + 1), np.log10(ada1.cost_), marker='o') ax[0].set_xlabel('Epochs') ax[0].set_ylabel('log(Sum-squared-error)') ax[0].set_title('Adaline - Learning rate 0.01') ada2 = adaline.AdalineGD(n_iter=10, eta=0.0001).fit(X, y) ax[1].plot(range(1, len(ada2.cost_) + 1), ada2.cost_, marker='o') ax[1].set_xlabel('Epochs') ax[1].set_ylabel('Sum-squared-error') ax[1].set_title('Adaline - Learning rate 0.0001') plt.show()
学習率を適切に選ぶのは難しいみたいです.
最小二乗法
ディープラーニングは最小二乗法であるとかいう記事が炎上してたと見たことがあります.それはともかく,コスト関数見ると勾配降下法を使わなくても最小二乗法で解けるので,pythonで試してみました.
import os import pandas as pd import numpy as np path = os.path.join('D:\\Book\\python-machine-learning-book-3rd-edition-master\\ch02\\', 'iris.data') df = pd.read_csv(path, header=None, encoding='utf-8') y = df.iloc[0:100, 4].values y = np.where(y == 'Iris-setosa', -1, 1) X = df.iloc[0:100, [0, 2]].values T = np.dot(X.T, X) T = np.dot(np.linalg.inv(T), X.T) para = np.dot(T, y) print(para) def phi(X, v): if np.dot(X, v) >= 0: return 1 else: return -1 cnt = 0 cost = 0.0 for xi, target in zip(X, y): if target != phi(xi, para): cnt += 1 cost += (target - np.dot(xi, para)) * (target - np.dot(xi, para)) / 2.0 print(cnt) print(cost)
$J(\boldsymbol{w}^{*}) = 2.604$
となり,勾配降下法よりもコストが小さいです.まあ,当たり前なんですが.