2

現在、ネットワークに回復力のある伝播を実装しようとしています。encog の実装に基づいてこれを行っていますが、理解できないことが 1 つあります。

RPROP および iRPROP+のドキュメントには、change > 0 の場合: weightChange = -sign(gradient) * delta と記載されています。

298行目と366行目のソースコードにマイナスがありません!

場合によっては両方とも正しいと思いますが、なぜ両者に違いがあるのでしょうか?

グラデーションに関しては、出力レイヤーでアクティブとして tanh を使用しています。これは勾配の正しい​​計算ですか?

gradientOutput = (1 - lastOutput[j] * lastOutput[j]) * (target[j] - lastOutput[j]);
4

2 に答える 2

3

関連する論文を読み直し、教科書を調べた後、encog のドキュメントは現時点では正しくないと思います。ソースコードにマイナス記号を一時的に追加して試してみませんか? ドキュメントが正しければ、同じ初期重みを使用すると、まったく同じ結果が得られるはずです。しかし、最終的には weightUpdate 変数をどのように使用するかが重要です。ドキュメントの作成者が weightUpdate を追加するのではなく、重みから削除することに慣れている場合、これは機能します。

編集:元の回答の勾配計算に関する部分を再訪しました。

まず、出力レイヤーの重みのグラデーションをどのように想像できるかについて簡単に説明します。まず、出力と目標値の間の誤差を計算します。

あなたが今やろうとしていることは、アクティブだった前の層のニューロンを「責める」ことです。出力ニューロンが「ここでエラーが発生しました。責任者は誰ですか?」と言っていると想像してください。責任があるのは、前の層のニューロンです。ターゲット値と比較して出力が小さすぎるか大きすぎるかによって、前のレイヤーの各ニューロンの重みが増減されます。

x は隠れ層のニューロンの活性化です。

o は出力ニューロンの活性化です。

φ は出力ニューロンの活性化関数であり、φ' はその導関数です。

Edit2 : 以下の部分を修正しました。バックプロパゲーションの行列スタイルの計算が追加されました。

各出力ニューロン j での誤差は次のとおりです。

(1) δアウト、j = φ'(o j )(t - o j )

非表示ニューロン i と出力ニューロン j を接続する重みの勾配:

(2) 勾配i, j = x i * δ out, j

重み w を使用した各隠れニューロン i での逆伝播誤差:

(3) δ hid, i = φ'(x)*∑w i, j * δ out, j

式 2 と 3 を繰り返し適用することで、入力層まで逆伝播できます。

1 つのトレーニング サンプルに関して、 loopsで記述します。

各出力ニューロン j での誤差は次のとおりです。

for(int j=0; j < numOutNeurons; j++) {
  errorOut[j] = activationDerivative(o[j])*(t[j] - o[j]);
}

非表示ニューロン i と出力ニューロン j を接続する重みの勾配:

for(int i=0; i < numHidNeurons; i++) {
  for(int j=0; j < numOutNeurons; j++) {
    grad[i][j] = x[i] * errorOut[j]        
  }      
}

各隠れニューロン i での逆伝播誤差:

for(int i=0; i < numHidNeurons; i++) {
  for(int j=0; j < numOutNeurons; j++) {
    errorHid[i] = activationDerivative(x[i]) * weights[i][j] * errorOut[j]        
  }      
}

畳み込みなどのない完全に接続された多層パーセプトロンでは、標準の行列演算を使用できます。これははるかに高速です。

各サンプルが入力行列の行であり、列がその属性であると仮定すると、次のようにネットワークを介して入力を伝播できます。

activations[0] = input;
for(int i=0; i < numWeightMatrices; i++){
  activations[i+1] = activations[i].dot(weightMatrices[i]);
  activations[i+1] = activationFunction(activations[i+1]);
}

バックプロパゲーションは次のようになります。

n = numWeightMatrices;
error = activationDerivative(activations[n]) * (target - activations[n]);
for (int l=n-1; l >= 0; l--){
  gradient[l] = activations[l].transposed().dot(error);
  if (l > 0) {
     error = error.dot(weightMatrices[l].transposed());
     error = activationDerivative(activations[l])*error;
  }
}

上記の説明では、バイアス ニューロンを省略しました。文献では、常に 1.0 である各活性化行列の追加の列としてバイアス ニューロンをモデル化することが推奨されています。いくつかのスライス割り当てを処理する必要があります。行列逆伝播ループを使用する場合は、各ステップの前にバイアスの位置の誤差を 0 に設定することを忘れないでください!

于 2013-04-11T00:22:08.230 に答える