アプリ版:「スタンプのみでお礼する」機能のリリースについて

//出力層と中間層2の結合荷重を更新
for ( i = 0; i < NUM_hh+1; i++)
  {
 for ( j = 0; j < NUM_o; j++)
{
deltaw3[i][j][ilearn+1] = (y[j] - teach[j]) * y[j] * (1.0 - y[j]) * hh[i];
w3[i][j][ilearn+1] = w3[i][j][ilearn] -0.05 * H2[i][j][ilearn] * deltaw3[i][j][ilearn];
//中間層2と中間層1の結合荷重更新
for ( i = 0; i < NUM_hh+1; i++ )
 {
  net_input1[j] = 0;
 for ( j = 0; j < NUM_o; j++ )
  {
net_input1[j] += w3[i][j][ilearn] * deltaw3[i][j][ilearn];
  }
    net_input1[i] = net_input1[j];
 }
for ( i = 0; i < NUM_h+1; i++)
 {
 for ( j = 0; j < NUM_hh; j++)
  {
deltaw2[i][j][ilearn+1] = net_input1[j] * (1.0 - hh[j]) * h[i];
w2[i][j][ilearn+1] = w2[i][j][ilearn] - (0.005 * H2[i][j][ilearn] * deltaw2[i][j][ilearn] );
  }
 }
//中間層1と入力層の結合荷重更新
for ( i = 0; i < NUM_h; i++ )
 {
 net_input2[j] = 0;
 for ( j = 0; j < NUM_hh; j++ )
  {
 net_input2[j] += w2[i][j][ilearn] * deltaw2[i][j][ilearn];
  }
 net_input2[i] = net_input2[j];
 }
for ( i = 0; i < NUM_i+1; i++)
 {
 for ( j = 0; j < NUM_h; j++)
  {
deltaw1[i][j][ilearn+1] = net_input2[j] * (1.0 - h[j]) * x[i];
w1[i][j][ilearn+1] = w1[i][j][ilearn] - (0.005 * H2[i][j][ilearn] * deltaw1[i][j][ilearn] );
  }
 }
for ( i = 0; i < NUM_h; i++) // Hの更新 //
 {
  for ( j = 0; j < NUM_hh; j++)
  {
sigma2[i][j] = w2[i][j][ilearn+1] - w2[i][j][ilearn];
gamma2[i][j] = deltaw2[i][j][ilearn+1] - deltaw2[i][j][ilearn];
  }
 }
for ( i = 0; i < NUM_h; i++)
{
 for ( j = 0; j < NUM_hh; j++)
  {
H2[i][j][ilearn+1] = H2[i][j][ilearn] + ((sigma2[i][j] * sigma2[j][i]) / (sigma2[j][i] * gamma2[i][j])) - ((H2[i][j][ilearn]*gamma2[i][j]*gamma2[j][i]*H2[i][j][ilearn])/(gamma2[j][i]*H2[i][j][ilearn]*gamma2[i][j]));
  }
}
プログラムの最初に戻り学習を繰り返す。

準ニュートン法(DFP)を階層型ニューラルネットに用いて学習を行うプログラムを作成しているのですが、ヘッセ行列の逆行列を更新がうまくできず、学習ができません。どこに問題があるのかわからず困っています。。
※各層のニューロン数は、NUM_i:5 NUM_hhとNUM_h:30 NUM_o:31
w123は結合荷重、deltaw123は勾配 gamma2は勾配の差分 sigma2は結合係数の差分

学習結果を見るために関数近似を行ってます。誤差は二乗誤差を用いているのですが、結果が学習回数2回目辺りから1.#qNaN0になり、それ以降は-1.#ind00という出力になってしまいます。

A 回答 (1件)

 Cは、ソースを部分的に明示されてもそれに精通した人でないと解答することは極めて困難です。

というか、プログラムは走らせてみないとわからないので、特にこのような専門的な内容の場合は質問自体が無謀のように思います。とりあえずいわせてもらえば「学習」がテーマということですので、学習の係数マトリックスが係数として本当に予想通り更新されているかどうか内容をチェックされることがまず初めにやるべきことではないでしょうか(あてずっぽうです)。
 その代わり、ここであなたに解答できないものの助言することはできます。それは「自身で何処に間違いがあるかを見つける方法」を教えてあげることです。
 ここでは Linux や Mac OSX などのUNIX系OSのパソコンを使っている場合の話をします。チェックの仕方は、プログラムの頭の方からあなたが想定した数値となっているかどうかを調べる、いわゆる「人間デバッガ」のやり方です。使うのは fprintf(stderr, “○×△ ....) を使います。
 たとえば↓のように、ループの中に fprintf() を組み入れて(間違えても、ループ内では複数の別の処理を入れないこと)コンパイルし、


//出力層と中間層2の結合荷重を更新
?fprintf(stderr,”\nコメント\n”); //ループ前に置き、 一行あけて見易く区切りを付ける
for ( i = 0; i < NUM_hh+1; i++) {?
 for ( j = 0; j < NUM_o; j++) {
?fprintf(stderr, “teach[%d]=%f deltaw3[%d][%d][%d]....?n”, j, teach[j], i, j, ilearn+1, deltaw3[i][j][ilearn+1], ....);
  deltaw3[i][j][ilearn+1] = (y[j] - teach[j]) * y[j] * (1.0 - y[j]) * hh[i];? w3[i][j][ilearn+1] = w3[i][j][ilearn] -0.05 * H2[i][j][ilearn] * deltaw3[i][j][ilearn];?}}
  ......
exit(0); // ループ毎にひとつひとつ区切ってチェックする


プログラムの起動の際に、シェルプロンプトから
   ./a.out 2>>my_errfile
と打鍵して、エラー出力パスを my_errfile という名のファイルにリダイレクトして追加書き込みし、実行後、その都度ファイルをエディタなどで開いては各数値がどのように展開しているのか確認するやり方です。最初はひとつのループ毎に終わるようにして、各ループにおける諸数値がどのような状況となっているのか my_errfile を開いて確認します。なお、出力ファイル名はとりあえず my_errfile としましたが、それは自由です。
 一通り最初のこの人間デバッグ作業が終われば、次は if() を使って、任意ループ回数毎に 同じように my_errfile に追加書き込みするようにします。これで、どこでどのように数値が変わったのか更にわかるでしょう。
 ただし、これはひとつひとつの項目についてチェックする気の遠くなる作業です。焦らず、根気よく確認するしかありません。ちょっと大きな、あるいは難解なプログラムのデバッグはそのようなものです。プログラム作成が1日なら、間違い探しのデバックはその数倍の3日以上の労力を必要とします。頑張ってください。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
自分が使ってる開発環境はvisual c++ 2005/2008なのでwindowsを使ってます。LinuxやUNIXはあまり手を付けたことが無いのですいません。。
デバッグ機能は付いているのでそれを頼りにいろいろ値の変化を調べることは行っているのですが、それだけでは足りないのですね。。確かに一つ一つチェックするのは時間が掛かってしまうかもしれないですがそれが一番いいですよね。
アドバイスありがとうございました。fprintfでファイル出力なども行ったりして変化を見てみたりして、もっと頑張ってみます。

お礼日時:2009/12/27 03:02

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!