web-dev-qa-db-ja.com

PyBrainを使用したニューラルネットワークのトレーニングが収束しない

PyBrainチュートリアルからの次のコードがあります。

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

ds = SupervisedDataSet(2, 1)
ds.addSample((0,0), (0,))
ds.addSample((0,1), (1,))
ds.addSample((1,0), (1,))
ds.addSample((1,1), (0,))

net     = buildNetwork(2, 3, 1, bias=True, hiddenclass=TanhLayer)
trainer = BackpropTrainer(net, ds)

for inp, tar in ds:
     print [net.activate(inp), tar]

errors  = trainer.trainUntilConvergence()

for inp, tar in ds:
     print [net.activate(inp), tar]

ただし、その結果は、十分に訓練されていないニューラルネットワークになります。エラー出力を見ると、ネットワークは適切にトレーニングされますが、「continueEpochs」引数を使用してさらにトレーニングし、ネットワークのパフォーマンスが再び低下します。したがって、ネットワークは収束していますが、最適なトレーニング済みネットワークを取得する方法はありません。 PyBrainのドキュメンテーションは、ネットワークが返されることを示唆していますが、ネットワークは最適にトレーニングされていますが、タプルのエラーを返します。

ContinueEpochsを0に設定すると、エラーが発生するため(ValueError:max()argは空のシーケンスです)、continueEpochsは0より大きくなければなりません。

ドキュメントとコードに大きな違いがあるように見えるので、PyBrainは実際にメンテナンスされていますか?.

32
avanwieringen

さらに掘り下げた後、PyBrainのチュートリアルの例は完全に適切ではないことがわかりました。

ソースコードのメソッドシグネチャを見ると、次のことがわかります。

def trainUntilConvergence(self, dataset=None, maxEpochs=None, verbose=None, continueEpochs=10, validationProportion=0.25):

つまり、トレーニングセットの25%が検証に使用されます。データでネットワークをトレーニングする場合、これは非常に有効な方法ですが、可能性の完全な範囲、つまり4列XOR 2-in -1-outソリューションセット。XORセットをトレーニングしたいときに、検証のために行の1つを削除すると、すぐに結果として非常にまばらなトレーニングセットが得られ、可能な組み合わせは省略され、トレーニングされていないウェイトが自動的に作成されます。

通常、検証のためにデータの25%を省略した場合、それらの25%が、ネットワークがすでに多かれ少なかれ遭遇したソリューション空間の「大部分」をカバーしていると想定することでこれを行います。この場合、これは当てはまりません。検証のために削除したため、ネットワークにはまったく未知のソリューション空間の25%をカバーしています。

したがって、トレーナーはネットワークを正しくトレーニングしていましたが、XOR問題の25%を省略することにより、ネットワークのトレーニングが不十分になります。

この特定のXORの場合はこの例がまったく間違っているため、クイックスタートとしてのPyBrain Webサイトの別の例は非常に便利です。ランダムに不適切に訓練されたネットワークを出力します。

35
avanwieringen

私は、Andrew Ngが教えてくれた優れた Courseraの機械学習クラス を受講しました。クラスの一部は、xorを認識するための小さなニューラルネットのトレーニングをカバーしました。したがって、収束しなかった quickstart の一部に基づくpybrainの例に少し悩みました。

上記の最小データセットがトレーニングと検証に分割されることを含む、多くの理由があると思います。コースのある時点で、アンドリューは「最も優れたアルゴリズムを持つ人ではなく、データが最も多い人です。そして、2000年代のデータ可用性の急増が理由の一部であることを説明し続けました。 AIの復活、現在は機械学習と呼ばれています。

それをすべて念頭に置いて、私はそれを見つけました

  1. 検証セットは4つのサンプルを持つことができます。これは、トレーニングフェーズの後であるためです。
  2. クラスで学んだように、ネットワークには非表示層に2つのノードしか必要ありません。
  3. この場合、学習率は0.005のようにかなり小さくする必要があります。そうしないと、トレーニングが答えをスキップすることがあります(これは、数字で遊んで確認したクラスの重要なポイントです)。
  4. 学習率が小さいほど、maxEpochsを小さくできます。学習率が小さいということは、収束が最小化に向かう​​勾配に沿ってより小さなステップを取ることを意味します。大きい場合は、maxEpochsを大きくして、最小値に達したと判断するまでの待ち時間を長くする必要があります。
  5. ネットワークでbias = Trueが必要です(これにより、定数1ノードが入力レイヤーと非表示レイヤーに追加されます)。バイアスについて この質問 への回答を読んでください。
  6. 最後に、そして最も重要なのは、大きなトレーニングセットが必要であることです。約75%の確率で1000が正解に収束しました。これは最小化アルゴリズムに関係しているのではないかと思います。小さい数は頻繁に失敗します。

だからここに働くいくつかのコードがあります:

from pybrain.datasets import SupervisedDataSet

dataModel = [
    [(0,0), (0,)],
    [(0,1), (1,)],
    [(1,0), (1,)],
    [(1,1), (0,)],
]

ds = SupervisedDataSet(2, 1)
for input, target in dataModel:
    ds.addSample(input, target)

# create a large random data set
import random
random.seed()
trainingSet = SupervisedDataSet(2, 1);
for ri in range(0,1000):
    input,target = dataModel[random.getrandbits(2)];
    trainingSet.addSample(input, target)

from pybrain.tools.shortcuts import buildNetwork
net = buildNetwork(2, 2, 1, bias=True)

from pybrain.supervised.trainers import BackpropTrainer
trainer = BackpropTrainer(net, ds, learningrate = 0.001, momentum = 0.99)
trainer.trainUntilConvergence(verbose=True,
                              trainingData=trainingSet,
                              validationData=ds,
                              maxEpochs=10)

print '0,0->', net.activate([0,0])
print '0,1->', net.activate([0,1])
print '1,0->', net.activate([1,0])
print '1,1->', net.activate([1,1])
17
toddInPortland
trainer = BackpropTrainer(net, ds, learningrate = 0.9, momentum=0.0, weightdecay=0.0, verbose=True) 
trainer.trainEpochs(epochs=1000)

この方法で収束できます。学習率が小さすぎる場合(例:0.01)、極小値で失われます。私がテストしたように、学習率は0.3-30で収束します。

2
lym

以下は一貫して正しい結果を与えるようです:

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

#net = buildNetwork(2, 3, 1, bias=True, hiddenclass=TanhLayer)
net = buildNetwork(2, 3, 1, bias=True)

ds = SupervisedDataSet(2, 1)
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))

trainer = BackpropTrainer(net, ds, learningrate=0.001, momentum=0.99)

trainer.trainUntilConvergence(verbose=True)

print net.activate([0,0])
print net.activate([0,1])
print net.activate([1,0])
print net.activate([1,1])
0
bkanber