パーセプトロンとNNのコード書いてみた
タイトルの通り。紙の上で行列とかごにょごにょやるのもいいけど、Emacsたんとキャッキャウフフしたくなったでござる。
#!/usr/bin/python # -*- coding: utf-8 -*- from scipy import * import matplotlib.pyplot as plt if __name__ == '__main__': # 学習パターンの個数 N = 30 # wの真の値 w0 = array([-0.2, 0.5, -1]) x1, x2 = -1 + random.rand(N)*2, -1 + random.rand(N)*2 t = (w0[0]+x1*w0[1]+x2*w0[2] >= 0) * 2 - 1 # wの初期値。 w = array([0, 1, 1], dtype=float) # N個に対して誤分類が無くなるまでループ count = i = 0 while count < N: if dot(w, [1, x1[i], x2[i]])*t[i]>=0: count += 1 else: w += array([1, x1[i], x2[i]])*t[i] count = 1 i = (i+1)%N x = linspace(-1.0, 1.0, 50) y = -w[0]/w[2]-w[1]/w[2]*x plt.plot(x, y) for i in range(N): c = 'r' if t[i] >= 0 else 'b' plt.scatter([x1[i]], [x2[i]], color=c) plt.xlim(-1.0,1.0) plt.ylim(-1.0,1.0) plt.show()
実行すると。。。
みたく線形分離できた気分に。*1
5章のNNも。ただし2層限定
!/usr/bin/python # -*- coding: utf-8 -*- from scipy import * import matplotlib.pyplot as plt class NN(object): """ 2層ニューラルネットワーク PRML5.3までの知識が元 """ def __init__(self, inputs, hidden, outputs, hidden_activation_func=tanh, hidden_activation_func_diff=lambda h:1-h*h, output_activation_func=lambda x:x): self._d = inputs self._m = hidden self._k = outputs self._h = hidden_activation_func self._h_diff = hidden_activation_func_diff self._f = output_activation_func self.w_init() def w_init(self): self._w1 = random.rand(self._m, self._d+1) self._w1 = resize(self._w1, (self._m, self._d+1)) self._w2 = random.rand(self._k, self._m+1) self._w2 = resize(self._w2, (self._k, self._m+1)) def calc(self, x0): x = insert(x0, 0, 1.0) a = dot(self._w1, x) z = insert(self._h(a), 0, 1.0) b = dot(self._w2, z) return self._f(b) def train(self, x0, t, n=0.1): x = insert(x0, 0, 1.0) a = dot(self._w1, x) z = insert(self._h(a), 0, 1.0) b = dot(self._w2, z) y = self._f(b) d2 = y - t d1 = dot(self._w2.T, d2)*self._h_diff(z) dE2 = dot(array([d2]).T, array([z])) dE1 = dot(array([d1[1:]]).T, array([x])) self._w1 -= n*dE1 self._w2 -= n*dE2
ipythonで適当にimportして戯れつつ、
y=x, y=x**2, y=x*(x-0.5)*(x+0.5), y=tanh(x) 等を学習させてみると
みたいな感じに。ほー。
ネットワークの更新は逐次的勾配降下法でやってるんだが、どーも遅いというか何というか。凖ニュートン法とか共役勾配法とか調べて見ようかし。。。
*1:なんて適当な気分だ