PyBrainのテスト

ちょっとニューラルネットワークで試したいことがあるので,最初の段階として,PyBrainを用いてニューラルネットワークというものを使用してみる.

階層型ニューラルネットワークの例題としてXOR演算を学習させる.

以下,コード

from pybrain.datasets import SupervisedDataSet
from pybrain.tools.shortcuts import buildNetwork
from pybrain.supervised.trainers import BackpropTrainer

# Set teaching signals
target = SupervisedDataSet(2, 1)
target.addSample([0, 0], [0])
target.addSample([0, 1], [1])
target.addSample([1, 0], [1])
target.addSample([1, 1], [0])

network = buildNetwork(2, 2, 1)
trainer = BackpropTrainer(network, target)

# Training
for n in range(100000):
    error = trainer.train()
    print "%d    %f" % (n, error)
    if error < 0.0001:
        break

print "f(0, 0) = %f" % network.activate([0, 0])
print "f(0, 1) = %f" % network.activate([0, 1])
print "f(1, 0) = %f" % network.activate([1, 0])
print "f(1, 1) = %f" % network.activate([1, 1])

PyBrainはコードが簡単なのはいいですね.

何回か試して見たが,重み関数の初期条件よっては収束しないことが結構あるようだ.横軸が学習回数で,縦軸がエラーである.

f:id:fjkz:20141228014405p:plain

最初,急に誤差が減ってきて,減り方が緩やかになって,再び急になるという気持ち悪い学習の仕方をしている.

エラーが0.0001の場合の出力値は以下.

f(0, 0) = 0.020374
f(0, 1) = 0.987520
f(1, 0) = 0.987359
f(1, 1) = 0.007329

思ったより誤差が大きい.

収束しなかった場合の出力値は

99999    0.064225
f(0, 0) = 0.002815
f(0, 1) = 0.499337
f(1, 0) = 0.996132
f(1, 1) = 0.502938

99999    0.064870
f(0, 0) = 0.004271
f(0, 1) = 0.998503
f(1, 0) = 0.500618
f(1, 1) = 0.504393

どちらもエラーが0.064ぐらいで,出力のうち2つが0.5となっている.なんか対称的な点でぐるぐる回ってそう.

(追記 多分,最急勾配法で解いてるから普通に別の極地点極値点にハマっただけか?)

差分法で流体の方程式と解く時のチェッカーボード不安定性とか,有限要素法で構造解析するときの(名前忘れたけど)扇型の変形モードが要素ごとに交互に起こって,エネルギーが吸収される現象を連想する.

PyBrainが古いだけなのか,まだ安定な解法が見つかっていないだけなのか.

大規模になると大変そうだな.

追記2 2014-12-30

pybrainのbuildNetworkで作られる出力層がデフォルトだとLinearLayerになっている. LinearLayerは活性化関数がf(x)=xである.つまり重みを足し合わせるだけで何もしない. つまり多層パーセプトロンでない. なんでこれでXORが学習できたのだ?今度考える.

参考

Pybrainでsin関数を学習させるサンプル | anopara

パターン認識と機械学習 上

パターン認識と機械学習 上

C++とJavaでつくるニューラルネットワーク

C++とJavaでつくるニューラルネットワーク