/* 内部記憶を持つニューラルネット */ #include <stdio.h> /* ヘッダ */ #include <stdlib.h> #include <string.h> #include <math.h> #define STUDY #include "grobal.h" /* 自作のヘッダ */ /* 変数の定義 */ #include "protfunc.h" /* 関数の定義 */ #include "funcdef.h" /* 関数の内容 */ /* main関数 */ int main( int argc , char **argv ){ srand48( Seed ); /* 乱数の設定 */ options_study( argc , argv ); /* コマンド入力から変数を読みとる */ set_teach( Data ); /* 教師信号をセットする */ set_file(); /* 出力ファイルをセットする */ initialize(); /* ニューロンの初期化 */ teach_change(); /* 教師信号を変更する */ /* 学習ループ */ r = 0; while( Flag_continue != 0 ){ Flag_success = 0; study(); /* 学習部分 */ check_recall(); /* 想起できるか確認 */ if( r >= Saidai ) Flag_continue = 0; /* 学習最大値を越えたら強制終了 */ } output_weight(); /* 重みを記録する */ return 0; } /* オプションを決定する関数 */ void options_study( int argc , char **argv ){ while( --argc ){ if( **++argv == '-' ){ switch( *++*argv ){ case 'z': /* 内部記憶を全て0にする */ if( --argc ){ Flag_zero = 1; break; } case 'n': /* ノイズを混ぜる */ if( --argc ){ Flag_noize = 1; break; } default: usage: fprintf( stderr , "Usage: naiburand23plus [-z]\n" ); exit(-1); } } else { break; } } } /* 各重み、しきい値にランダムな値を与える 関数:initialize() */ void initialize(){ int i,j; for( j = 0 ; j < Midunit ; j++ ){ /* 入力層〜中間層 */ for( i = 0 ; i < Inunit ; i++ ){ wim[j][i] = urand(); dwim[j][i] = 0; } sikiiim[j] = urand(); dim[j] = 0; dsikiiim[j] = 0; midkeep[j] = 0; } for( j = 0 ; j < Outunit ; j++ ){ /* 中間層〜出力層 */ for( i = 0 ; i < Midunit ; i++ ){ wmo[j][i] = urand(); dwmo[j][i] = 0; } sikiimo[j] = urand(); dmo[j] = 0; dsikiimo[j] = 0; outkeep[j] = 0; } } /* 特殊な教師信号をセットする */ void teach_change(){ int i,j,h; /* 補助入力層の教師信号を作る */ for( i = 0 ; i < Lunit ; i = i + 2 ){ inkeep[Tunit + i][0] = inkeep[0][tsmax - ( i / 2 ) - 1]; inkeep[Tunit + i + 1][0] = inkeep[1][tsmax - ( i / 2 ) - 1]; } for( t = 1 ; t < tsmax ; t++ ){ h = t - 1; for( i = 0 ; i < Lunit ; i = i + 2 ){ inkeep[Tunit + i][t] = inkeep[i][h]; inkeep[Tunit + i + 1][t] = inkeep[i + 1][h]; } } /* 入力にランダムなデータを与える */ for( t = 0 ; t < tsmax ; t++ ){ for( i = TL ; i < Inunit ; i++ ){ inkeep[i][t] = qrand(); inkeep[i][t] = quantum( inkeep[i][t] ); } } if( Flag_zero != 0 ){ /* 内部記憶層の第一音を0にするようにする */ for( i = TLC ; i < Inunit ; i++ ){ inkeep[i][0] = 0; } } if( Flag_noize != 0 ){ for( t = 0 ; t < tsmax ; t++ ){ noisein[0][t] = inkeep[0][t] + lenrand(); noisein[1][t] = inkeep[1][t] + heirand(); } } } /* 内部記憶を作った時の学習の関数 */ void study(){ int i,j; int g; kk = r + Gakusyu; for( k = r ; k < kk ; k++ ){ Flag_success = 0; if( k % 1000 == 0 ) printf( "Study %d\n", k / 1000 ); /* 学習回数の表示 */ gosasumcloseteach = gosasumcloseall = 0; for( t = 0 ; t < tsmax ; t++ ){ g = t + 1; if( g >= tsmax ) g = 0; /* 教師信号を入れる */ for( i = 0 ; i < TLC ; i++ ){ inout[i][t] = inkeep[i][t]; } if( Flag_noize != 0 ){ for( i = 0 ; i < Tunit ; i++ ){ inout[i][t] = noisein[i][t]; } } forward_propagation(); /* フォワードプロパゲーション */ learn_check(); /* 学習が成功しているかを調べる */ back_propagation(); /* バックプロパゲーション */ if( t == 0 && k % 1000 == 0 ){ /* 誤差信号を測定する */ gosa_plot(); if( Flag_gosaplotnew != 0 ) gosa_plot_new(); } /* 各出力を保存する*/ for( i = 0 ; i < Midunit ; i++ ){ midkeep3[i] = midkeep2[i]; midkeep2[i] = midkeep[i]; midkeep[i] = midout[i]; } for( i = 0 ; i < Outunit ; i++ ){ outkeep3[i] = outkeep2[i]; outkeep2[i] = outkeep[i]; outkeep[i] = outout[i]; } for( i = TLC ; i < Outunit ; i++ ){ outkept[i][t] = outout[i]; } output_correct(); /* 量子化する */ feedback(); /* 出力をフィードバックする */ } /* 最大値以上であれば強制終了処理 */ if( kk >= Saidai ){ kk = Saidai; Flag_continue = 0; } } r = k; } /* 内部記憶を作った時の想起 */ void check_recall(){ int i,j; int g; chsuccess = chfault = 0; Flag_success = 0; for( k = 0 ; k < Souki ; k++ ){ if( k % 1000 == 0 ) printf( "Recall_close %d\n", k / 1000 ); for( t = 0 ; t < tsmax ; t++ ){ if( t == 0 ){ for( i = 0 ; i < TLC ; i++ ){ inout[i][t] = inkeep[i][t]; } } g = t + 1; if( g >= tsmax ) g = 0; forward_propagation(); /* フォワードプロパゲーション */ /* 内部記憶の時間的変移特性を記録する */ if( k >= Souki - 1 ){ for( i = TLC ; i < Inunit ; i++ ){ cyclekeep[i][t] = outout[i]; } } output_correct(); /* 量子化をする*/ feedback(); /* 次の時間の入力にする */ if( k == Souki - 1 ){ for( i = 0 ; i < Tunit ; i++ ){ if( (float)inkeep[i][g] != (float)outout[i] ){ /* 教師信号との比較 */ Flag_success++; chfault++; } else { chsuccess++; /* 全て間違っていなければ学習成功 */ } } fprintf( fprecall , "%f %f %f ",inkeep[0][g],outout[0],( inkeep[0][g] - outout[0] ) ); fprintf( fprecall , "%f %f %f\n",inkeep[1][g],outout[1],( inkeep[1][g] - outout[1] ) ); if( Flag_success == 0 ){ Flag_continue = 0; } else { Flag_continue = 1; } } } } fprintf( fpplot ,"\n" ); fprintf( fpnaibu ,"\n" ); fprintf( fprecall ,"\n" ); } void learn_check(){ int i; int g; g = t + 1; if( g >= tsmax ) g = 0; if( k % 1000 == 0 || k == kk - 1 ){ for( i = 0 ; i < TLC ; i++ ){ gosa[i][t] = inkeep[i][g] - outout[i]; kekka[i] = sqrt( gosa[i][t] * gosa[i][t] ); } for( i = TLC ; i < Outunit ; i++ ){ gosa[i][t] = outkept[i][t] - outout[i]; kekka[i] = sqrt( gosa[i][t] * gosa[i][t] ); } if( kekka[0] > 0.1 || kekka[1] > 0.0125 ){ printf( " t = %d is fault %f %f %f %f\n",t,outout[0],inkeep[0][g],outout[1],inkeep[1][g] ); } if( t == 36 ){ fprintf( fpplot , "%d %f",( k / 100 ) , kekka[0] ); fprintf( fpplot , " %f\n" , kekka[1] ); fprintf( fpnaibu , "%d ",( k / 100 ) ); for( i = 0 ; i < Nunit ; i++ ){ if( i > 2 && i < 7 ) fprintf( fpnaibu , "%f ", outout[TLC + i] ); } fprintf( fpnaibu , "\n" ); fflush( fpplot ); } } if( k == kk - 1 ){ for( i = 0 ; i < Tunit ; i++ ){ gosasumcloseteach += sqrt( gosa[i][t] * gosa[i][t] ); } for( i = 0 ; i < Outunit ; i++ ){ gosasumcloseall += sqrt( gosa[i][t] * gosa[i][t] ); } if( kekka[0] > 0.1 || kekka[1] > 0.0125 ){ if( Flag_success == 0 ){ kk = kk + 1000; Flag_success++; } } } if( kk >= Saidai ){ for( i = 0 ; i < Tunit ; i++ ){ gosa[i][t] = inkeep[i][g] - outout[i]; gosasumcloseteach += sqrt( gosa[i][t] * gosa[i][t] ); } for( i = 0 ; i < Outunit ; i++ ){ gosa[i][t] = inkeep[i][g] - outout[i]; gosasumcloseall += sqrt( gosa[i][t] * gosa[i][t] ); } kk = Saidai; Flag_continue = 0; } } /* 最後にニューロンの重みなどを記録する */ void output_weight(){ int i; int dn; /* 内部記憶に関してのt - t+1 特性をとる */ for( t = 0 ; t < tsmax ; t++ ){ if( t >= tsmax - 1 ){ for( i = 1 ; i < 6 ; i++ ){ fprintf( fpnaibu2 ,"%f %f ",inout[TLC + i][t],inout[TLC + i][0]); } fprintf( fpnaibu2 ,"\n" ); }else{ for( i = 1 ; i < 6 ; i++ ){ fprintf( fpnaibu2 ,"%f %f ",inout[TLC + i][t],inout[TLC + i][t + 1]); } fprintf( fpnaibu2 ,"\n" ); } } /* 周期的な内部記憶の特性を出力する */ for( i = TLC ; i < Inunit ; i++ ){ for( t = 0 ; t < tsmax ; t++ ){ fprintf( fpnaibu4 ,"%d %d %f\n",i,t,cyclekeep[i][t] ); } } dn = r / 100; sprintf( fiout,"kekka19/%dc%d_E%0.3f_A%0.3f.data",Filenumber,dn,Eta,Alpha ); fpout = fopen( fiout,"w" ); if( fpout == NULL ){ fprintf( stderr,"Error\n" ); exit(1); } /* 最終的な各ユニット、その他のデータをファイルに書き込む */ fwrite( inout , sizeof( double ),Inunit * Time ,fpout ); fwrite( inkeep , sizeof( double ) , Inunit * Time , fpout ); fwrite( wim,sizeof( double ),Inunit * Midunit ,fpout ); fwrite( wmo,sizeof( double ),Midunit * Outunit ,fpout ); fwrite( sikiiim,sizeof( double ),Midunit ,fpout ); fwrite( sikiimo,sizeof( double ),Outunit ,fpout ); fclose( fpout ); fprintf( fprecall ,"success = %d , fault = %d\n",chsuccess,chfault ); fprintf( fprecall ,"%f %f\n" ,gosasumcloseteach ,gosasumcloseall ); fclose( fpplot ); fclose( fpsumplot ); fclose( fpnaibu ); fclose( fpnaibu2 ); fclose( fprecall ); fclose( fpnaibu4 ); fclose( fpnaibucheck ); printf( "\nkaisuu = %d \n",r ); putchar( 'G' - '@' ); } /* 伝搬させる誤差の比率を測定する */ void gosa_plot(){ int i; double gettmax,gettmin; double getnmax,getnmin; double dmotmax,dmotmin; double dmonmax,dmonmin; gettmax = gettmin = dmoteach[0]; for( i = 1 ; i < TLC ; i++ ){ if( dmoteach[i] > gettmax ) gettmax = dmoteach[i]; if( dmoteach[i] < gettmin && dmoteach[i] != 0 ) gettmin = dmoteach[i]; } getnmax = getnmin = dmonaibu[0]; for( i = 1 ; i < Nunit ; i++ ){ if( dmonaibu[i] > getnmax ) getnmax = dmonaibu[i]; if( dmonaibu[i] < getnmin && dmonaibu[i] != 0 ) getnmin = dmonaibu[i]; } fprintf( fpsumplot , "%d %f %f %f %f %f %f %f %f\n" , ( k / 100 ) , gettmax , gettmin , getnmax , getnmin , ( getnmax / gettmax ) , ( getnmin / gettmin ) , ( getnmax / gettmin ) , ( getnmin / gettmax ) ); } /* 遅れ学習による中間層での誤差信号の大きさを測定する */ void gosa_plot_new(){ int i; fprintf( fpdimplot , "%d " , ( k / 100 ) ); for( i = 0 ; i < Midunit ; i++ ){ fprintf( fpdimplot , "%f " , dimget[i] ); } for( i = 0 ; i < Midunit ; i++ ){ fprintf( fpdimplot , "%f " , dimlate[i] ); } for( i = 0 ; i < Midunit ; i++ ){ fprintf( fpdimplot , "%f " , dimlate2[i] ); } fprintf( fpdimplot , "\n" ); } /* バックプロパゲーション 関数:back_propagation() */ void back_propagation(){ int i,j,g,h,f,e; double sum; /* 誤差 */ g = t + 1; /* 前の時間・先の時間を決める */ if( g >= tsmax ) g = 0; h = t - 1; if( t == 0 ) h = tsmax - 1; f = t - 2; if( t == 0 ) f = tsmax - 2; if( t == 1 ) f = tsmax - 1; e = t - 3; if( t == 0 ) e = tsmax - 3; if( t == 1 ) e = tsmax - 2; if( t == 2 ) e = tsmax - 1; /* t : 出力層の誤差信号の計算 */ for( j = 0 ; j < TLC ; j++ ){ dmo[j] = outout[j] * ( 1 - outout[j] ) * ( inkeep[j][g] - outout[j] ); dmoteach[j] = sqrt( ( inkeep[j][g] - outout[j] ) * ( inkeep[j][g] - outout[j] ) ); } switch( Flag_backpro ){ /* ******** 普通のBP ************************** */ case 1: /* t : 出力層の重み補正 */ for( j = 0 ; j < Midunit ; j++ ){ for( sum = 0 , i = 0 ; i < TLC ; i++ ){ dwmo[i][j] = ( Eta * dmo[i] * midout[j] ) + ( Alpha * dwmo[i][j] ); sum += ( dmo[i] * wmo[i][j] ); wmo[i][j] += dwmo[i][j]; } /* t : 中間層の誤差信号の計算 */ dim[j] = midout[j] * ( 1 - midout[j] ) * sum; dimget[j] = sqrt( sum * sum ); } /* t : 出力層の閾値補正 */ for( i = 0 ; i < TLC ; i++ ){ dsikiimo[i] = ( Eta * dmo[i] ) + ( Alpha * dsikiimo[i] ); sikiimo[i] += dsikiimo[i]; } /* t : 中間層の重み補正 */ for( j = 0 ; j < Inunit ; j++ ){ for( sum = 0 , i = 0 ; i < Midunit ; i++ ){ dwim[i][j] = ( Eta * dim[i] * inout[j][t] ) + ( Alpha * dwim[i][j] ); sum += ( dim[i] * wim[i][j] ); wim[i][j] += dwim[i][j]; } /* t : 内部記憶層の誤差信号の計算 */ if( j >= TLC && j < TLCN ){ dmo[j] = outkeep[j] * ( 1 - outkeep[j] ) * sum; dmonaibu[j - TLC] = sqrt( sum * sum ); } } /* t : 中間層の重み補正 */ for( i = 0 ; i < Midunit ; i++ ){ dsikiiim[i] = ( Eta * dim[i] ) + ( Alpha * dsikiiim[i] ); sikiiim[i] += dsikiiim[i]; } /* t-1 : 内部記憶層の重み補正 */ for( j = 0 ; j < Midunit ; j++ ){ for( i = TLC ; i < TLCN ; i++ ){ dwmo[i][j] = ( Eta2 * dmo[i] * midkeep[j] ) + ( Alpha * dwmo[i][j] ); wmo[i][j] += dwmo[i][j]; } } /* t-1 : 内部記憶層の閾値補正 */ for( i = TLC ; i < TLCN ; i++ ){ dsikiimo[i] = ( Eta2 * dmo[i] ) + ( Alpha * dsikiimo[i] ); sikiimo[i] += dsikiimo[i]; } break; /* ******** 2-step Learning ************************** */ case 2: /* t : 出力層の誤差伝搬 */ for( j = 0 ; j < Midunit ; j++ ){ for( sum = 0 , i = 0 ; i < TLC ; i++ ){ sum += ( dmo[i] * wmo[i][j] ); } /* t : 中間層の誤差信号の計算 */ dim[j] = midout[j] * ( 1 - midout[j] ) * sum; dimget[j] = sqrt( sum * sum ); } /* t : 中間層の誤差伝搬 */ for( j = 0 ; j < Inunit ; j++ ){ for( sum = 0 , i = 0 ; i < Midunit ; i++ ){ sum += ( dim[i] * wim[i][j] ); } /* t : 内部記憶層の誤差信号の計算 */ if( j >= TLC && j < TLCN ){ dmo[j] = outkeep[j] * ( 1 - outkeep[j] ) * sum; dmonaibu[j - TLC] = sqrt( sum * sum ); } } /* t-1 : 出力層の誤差信号の計算 */ for( i = 0 ; i < TLC ; i++ ){ dmo[i] = outkeep[i] * ( 1 - outkeep[i] ) * ( inkeep[i][t] - outkeep[i] ); } /* t-1 : 出力層と内部記憶層の重み補正 */ for( j = 0 ; j < Midunit ; j++ ){ for( sum = 0 , i = 0 ; i < TLC ; i++ ){ dwmo[i][j] = ( Eta * dmo[i] * midkeep[j] ) + ( Alpha * dwmo[i][j] ); sum += ( dmo[i] * wmo[i][j] ); wmo[i][j] += dwmo[i][j]; } for( i = TLC ; i < TLCN ; i++ ){ dwmo[i][j] = ( Eta2 * dmo[i] * midkeep[j] ) + ( Alpha * dwmo[i][j] ); sum += ( dmo[i] * wmo[i][j] ); wmo[i][j] += dwmo[i][j]; } dim[j] = midkeep[j] * ( 1 - midkeep[j] ) * sum; dimlate[j] = sqrt( sum * sum ); } /* t-1 : 出力層の閾値補正 */ for( i = 0 ; i < TLC ; i++ ){ dsikiimo[i] = ( Eta * dmo[i] ) + ( Alpha * dsikiimo[i] ); sikiimo[i] += dsikiimo[i]; } /* t-1 : 内部記憶層の閾値補正 */ for( i = TLC ; i < TLCN ; i++ ){ dsikiimo[i] = ( Eta2 * dmo[i] ) + ( Alpha * dsikiimo[i] ); sikiimo[i] += dsikiimo[i]; } /* t-1 : 中間層の重み補正 */ for( j = 0 ; j < Inunit ; j++ ){ for( i = 0 ; i < Midunit ; i++ ){ dwim[i][j] = ( Eta * dim[i] * inout[j][h] ) + ( Alpha * dwim[i][j] ); wim[i][j] += dwim[i][j]; } } /* t-1 : 中間層の閾値補正 */ for( i = 0 ; i < Midunit ; i++ ){ dsikiiim[i] = ( Eta * dim[i] ) + ( Alpha * dsikiiim[i] ); sikiiim[i] += dsikiiim[i]; } break; /* ******** 3-step Learning ************************** */ default: /* t : 出力層の誤差伝搬 */ for( j = 0 ; j < Midunit ; j++ ){ for( sum = 0 , i = 0 ; i < TLC ; i++ ){ sum += ( dmo[i] * wmo[i][j] ); } /* t : 中間層の誤差信号の計算 */ dim[j] = midout[j] * ( 1 - midout[j] ) * sum; dimget[j] = sqrt( sum * sum ); } /* t : 中間層の誤差伝搬 */ for( j = 0 ; j < Inunit ; j++ ){ for( sum = 0 , i = 0 ; i < Midunit ; i++ ){ sum += ( dim[i] * wim[i][j] ); } /* t : 内部記憶層の誤差信号の計算 */ if( j >= TLC && j < TLCN ){ dmo[j] = outkeep[j] * ( 1 - outkeep[j] ) * sum; dmonaibu[j - TLC] = sqrt( sum * sum ); } } /* t-1 : 出力層の誤差信号の計算 */ for( i = 0 ; i < TLC ; i++ ){ dmo[i] = outkeep[i] * ( 1 - outkeep[i] ) * ( inkeep[i][t] - outkeep[i] ); } /* t-1 : 出力層と内部記憶層の重み補正 */ for( j = 0 ; j < Midunit ; j++ ){ for( sum = 0 , i = 0 ; i < TLCN ; i++ ){ sum += ( dmo[i] * wmo[i][j] ); } dim[j] = midkeep[j] * ( 1 - midkeep[j] ) * sum; dimlate[j] = sqrt( sum * sum ); } /* t-1 : 中間層の重み補正 */ for( j = 0 ; j < Inunit ; j++ ){ for( sum = 0 , i = 0 ; i < Midunit ; i++ ){ sum += ( dim[i] * wim[i][j] ); } /* t-2 : 内部記憶層の誤差信号の計算 */ if( j >= TLC && j < TLCN ){ dmo[j] = outkeep2[j] * ( 1 - outkeep2[j] ) * sum; } } /* t-2 : 出力層の誤差信号の計算 */ for( i = 0 ; i < TLC ; i++ ){ dmo[i] = outkeep2[i] * ( 1 - outkeep2[i] ) * ( inkeep[i][h] - outkeep2[i] ); } /* t-2 : 出力層と内部記憶層の重み補正 */ for( j = 0 ; j < Midunit ; j++ ){ sum = 0; for( i = 0 ; i < TLC ; i++ ){ dwmo[i][j] = ( Eta * dmo[i] * midkeep2[j] ) + ( Alpha * dwmo[i][j] ); sum += ( dmo[i] * wmo[i][j] ); wmo[i][j] += dwmo[i][j]; } for( i = TLC ; i < TLCN ; i++ ){ dwmo[i][j] = ( Eta * dmo[i] * midkeep2[j] ) + ( Alpha * dwmo[i][j] ); sum += ( dmo[i] * wmo[i][j] ); wmo[i][j] += dwmo[i][j]; } dim[j] = midkeep2[j] * ( 1 - midkeep2[j] ) * sum; dimlate2[j] = sqrt( sum * sum ); } /* t-2 : 出力層の閾値補正 */ for( i = 0 ; i < TLC ; i++ ){ dsikiimo[i] = ( Eta * dmo[i] ) + ( Alpha * dsikiimo[i] ); sikiimo[i] += dsikiimo[i]; } /* t-2 : 内部記憶層の閾値補正 */ for( i = TLC ; i < TLCN ; i++ ){ dsikiimo[i] = ( Eta2 * dmo[i] ) + ( Alpha * dsikiimo[i] ); sikiimo[i] += dsikiimo[i]; } /* t-2 : 中間層の重み補正 */ for( j = 0 ; j < Inunit ; j++ ){ for( i = 0 ; i < Midunit ; i++ ){ dwim[i][j] = ( Eta * dim[i] * inout[j][f] ) + ( Alpha * dwim[i][j] ); wim[i][j] += dwim[i][j]; } } /* t-2 : 中間層の閾値補正 */ for( i = 0 ; i < Midunit ; i++ ){ dsikiiim[i] = ( Eta * dim[i] ) + ( Alpha * dsikiiim[i] ); sikiiim[i] += dsikiiim[i]; } break; /* ******** 4-step Learning ************************** */ case 4: /* t : 出力層の誤差伝搬 */ for( j = 0 ; j < Midunit ; j++ ){ for( sum = 0 , i = 0 ; i < TLC ; i++ ){ sum += ( dmo[i] * wmo[i][j] ); } /* t : 中間層の誤差信号の計算 */ dim[j] = midout[j] * ( 1 - midout[j] ) * sum; dimget[j] = sqrt( sum * sum ); } /* t : 中間層の誤差伝搬 */ for( j = 0 ; j < Inunit ; j++ ){ for( sum = 0 , i = 0 ; i < Midunit ; i++ ){ sum += ( dim[i] * wim[i][j] ); } /* t : 内部記憶層の誤差信号の計算 */ if( j >= TLC && j < TLCN ){ dmo[j] = outkeep[j] * ( 1 - outkeep[j] ) * sum; dmonaibu[j - TLC] = sqrt( sum * sum ); } } /* t-1 : 出力層の誤差信号の計算 */ for( i = 0 ; i < TLC ; i++ ){ dmo[i] = outkeep[i] * ( 1 - outkeep[i] ) * ( inkeep[i][t] - outkeep[i] ); } /* t-1 : 出力層と内部記憶層の重み補正 */ for( j = 0 ; j < Midunit ; j++ ){ for( sum = 0 , i = 0 ; i < TLCN ; i++ ){ sum += ( dmo[i] * wmo[i][j] ); } dim[j] = midkeep[j] * ( 1 - midkeep[j] ) * sum; dimlate[j] = sqrt( sum * sum ); } /* t-1 : 中間層の重み補正 */ for( j = 0 ; j < Inunit ; j++ ){ for( sum = 0 , i = 0 ; i < Midunit ; i++ ){ sum += ( dim[i] * wim[i][j] ); } /* t-2 : 内部記憶層の誤差信号の計算 */ if( j >= TLC && j < TLCN ){ dmo[j] = outkeep2[j] * ( 1 - outkeep2[j] ) * sum; } } /* t-2 : 出力層の誤差信号の計算 */ for( i = 0 ; i < TLC ; i++ ){ dmo[i] = outkeep2[i] * ( 1 - outkeep2[i] ) * ( inkeep[i][h] - outkeep2[i] ); } /* t-2 : 出力層と内部記憶層の重み補正 */ for( j = 0 ; j < Midunit ; j++ ){ for( sum = 0 , i = 0 ; i < TLCN ; i++ ){ sum += ( dmo[i] * wmo[i][j] ); } dim[j] = midkeep2[j] * ( 1 - midkeep2[j] ) * sum; dimlate2[j] = sqrt( sum * sum ); } /* t-2 : 中間層の重み補正 */ for( j = 0 ; j < Inunit ; j++ ){ for( sum = 0 , i = 0 ; i < Midunit ; i++ ){ sum += ( dim[i] * wim[i][j] ); } if( j >= TLC && j < TLCN ){ dmo[j] = outkeep3[j] * ( 1 - outkeep3[j] ) * sum; } } /* t-3 : 出力層の誤差信号の計算 */ for( i = 0 ; i < TLC ; i++ ){ dmo[i] = outkeep3[i] * ( 1 - outkeep3[i] ) * ( inkeep[i][f] - outkeep3[i] ); } /* t-3 : 出力層と内部記憶層の重み補正 */ for( j = 0 ; j < Midunit ; j++ ){ sum = 0; for( i = 0 ; i < TLC ; i++ ){ dwmo[i][j] = ( Eta * dmo[i] * midkeep3[j] ) + ( Alpha * dwmo[i][j] ); sum += ( dmo[i] * wmo[i][j] ); wmo[i][j] += dwmo[i][j]; } for( i = TLC ; i < TLCN ; i++ ){ dwmo[i][j] = ( Eta2 * dmo[i] * midkeep3[j] ) + ( Alpha * dwmo[i][j] ); sum += ( dmo[i] * wmo[i][j] ); wmo[i][j] += dwmo[i][j]; } dim[j] = midkeep3[j] * ( 1 - midkeep3[j] ) * sum; dimlate2[j] = sqrt( sum * sum ); } /* t-3 : 出力層の閾値補正 */ for( i = 0 ; i < TLC ; i++ ){ dsikiimo[i] = ( Eta * dmo[i] ) + ( Alpha * dsikiimo[i] ); sikiimo[i] += dsikiimo[i]; } /* t-3 : 内部記憶層の閾値補正 */ for( i = TLC ; i < TLCN ; i++ ){ dsikiimo[i] = ( Eta2 * dmo[i] ) + ( Alpha * dsikiimo[i] ); sikiimo[i] += dsikiimo[i]; } /* t-3 : 中間層の重み補正 */ for( j = 0 ; j < Inunit ; j++ ){ for( i = 0 ; i < Midunit ; i++ ){ dwim[i][j] = ( Eta * dim[i] * inout[j][e] ) + ( Alpha * dwim[i][j] ); wim[i][j] += dwim[i][j]; } } /* t-3 : 中間層の閾値補正 */ for( i = 0 ; i < Midunit ; i++ ){ dsikiiim[i] = ( Eta * dim[i] ) + ( Alpha * dsikiiim[i] ); sikiiim[i] += dsikiiim[i]; } break; } }