KDOG Notebook

どうも、古くからの友人です。

二乗和誤差を用いた学習

はじめに

ステップ関数を用いて予測ラベルを決定し、教師ラベルとの差分を誤差関数として用いた場合、誤差関数がとる値は離散的になる。 重み wも飛び飛びの値をとることになり、初期条件に強く依存した結果が得られる。

今回は二乗和誤差を誤差関数として用いて学習の精度を高める。

理論

二乗和誤差

二乗和誤差は以下の式で表される。

\begin{eqnarray}
E({\bf w})=\frac{1}{2}\sum_{k}(y_{k}-y'_{k})^2
\end{eqnarray}

ここで yおよび y’はそれぞれ教師ラベルと予測ラベルである。 この誤差関数は下に凸な関数である。したがって、関数 Eが最小になるような重 {\bf w}を求めることができればよい。 重みの更新は以下の通りである。

\begin{eqnarray}
{\bf w} := {\bf w} - \eta\nabla E({\bf w})
\end{eqnarray}
\begin{eqnarray}
\frac{\partial E}{\partial w_j} &=& \frac{\partial}{\partial w_j} \frac{1}{2}\sum_{i=1}^{m}\left(y^{(i)}-u^{(i)}\right)^2 \\
&=& \sum_{i=1}^{m} \left(y^{(i)}-u^{(i)}\right)\frac{\partial}{\partial w_j}\left(-u^{(i)}\right) \\
&=& -\sum_{i=1}^{m} \left(y^{(i)}-u^{(i)}\right)x_{j}^{(i)}
\end{eqnarray}

したがって、実装すべき式は

\begin{eqnarray}
w_j &:=& w_j + \eta\sum_{i=1}^{m} \left(y^{(i)}-u^{(i)}\right)x_{j}^{(i)} \qquad (i = 1,2,\cdots,n) \\
b &:=& b + \eta\sum_{i=1}^{m} \left(y^{(i)}-u^{(i)}\right)
\end{eqnarray}

データの標準化

学習効率を向上するために特徴量のスケーリングを行う。ここでは標準化(standardization)を用いる。

\begin{eqnarray}
x'_{j} = \frac{x_{j}-\mu}{\sigma}
\end{eqnarray}

実装

class Adaline():
    def __init__(self, eta=0.01, n_iter=10):
        self.eta = eta
        self.n_iter = n_iter
    def train(self, X, y):
        self.w_ = np.zeros(X.shape[1])
        self.b_ = np.zeros(1)
        update_w = 0.
        update_b = 0.
        self.w_history = np.zeros((self.n_iter,2))
        self.b_history = np.zeros(self.n_iter)
        self.cost_history = np.zeros(self.n_iter)
        
        for i in range(self.n_iter):
            errors = y - self.predict(X)
            update_w = np.sum(X*errors[:,np.newaxis],axis=0)
            update_b = np.sum(errors,axis=0)
            self.w_ += self.eta * update_w
            self.b_ += self.eta * update_b
            cost = 0.5 * np.sum(errors**2)
            
            self.w_history[i] = self.w_
            self.b_history[i] = self.b_
            self.cost_history[i] = cost
            
        return self
        
    def predict(self,X):
        return np.dot(X,self.w_) + self.b_

結果

学習を繰り返すに連れて誤差関数が収束している。しかし、完全に0にはなっていない。

f:id:kdog08:20170502022804p:plain:w300

メモ

どのような生データに対しても一律に標準化の操作は可能なのだろうか。 例えば、ポアソン分布に従うようなデータに対しても同様の手続きで標準化を実行して良いのか。

参考文献

Sebastian Raschka 「Python機械学習プログラミング」第2章, インプレス, 2016.