前提・実現したいこと
c言語でNNによるsin波の学習を行うプログラムを書いています。
発生している問題・エラーメッセージ
出力信号が全てnanとなってしまったり,すべて1になってしまうなど期待の動作をしない
該当のソースコード
C言語
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> #define ITERATIONS (100000)//繰り返し回数 //重みの初期値設定(乱数) double default_value(){//重みを−1~1で初期設定 return (rand() / (double)RAND_MAX)*2-1; } int main() { srand((unsigned) time(NULL)); double num = -M_PI; FILE*fp; fp = fopen("data.txt","w"); //教師データ double x[50]; double y[50]; int count = 0; //入力信号,教師データ生成 for(;num <= M_PI;num = num + (double)(2*M_PI/49)){ x[count] = num; y[count] = sin(num); count++; } //バイアス・重みの初期値設定 double bias[9] = {0,0,0,0,0,0,0,0,0}; double w1[9]; //入力層→隠れ層の重み double w2[10];//隠れ層→出力層の重み(w_2[0]はバイアス) for(count = 0;count<=9;count++){ if(count == 9){//訂正 w2[count] = default_value(); } else{ w1[count] = default_value(); w2[count] = default_value(); } } w2[0] = 0;//バイアスの初期値は0に設定 double p = 0.01;//学習率 double net2[9];//隠れ層への入力 double out2[10];//出力層への出力 out2[0] = 1/(1 + exp(-1)); double net3 = 0;//出力層への入力 double out3[50];//出力信号 double E = 0;//二乗誤差 double delta3; //double delta2; //double del_E;//∂E/∂w(or ∂E/∂bias) int i = 0; for(count = 0;count<50;count++){//サンプルされた50点のに対するそ処理 for(int count2 = 0;count2<=9;count2++){//重みの初期値設定 if(count2 == 9){//訂正 w2[count2] = default_value(); } else{ w1[count2] = default_value(); w2[count2] = default_value(); } } w2[0] = 0;//バイアスの初期値は0に設定 for(int learing_count=0;learing_count < ITERATIONS+1;learing_count++){//学習回数10万回についての処理,*「ITERATIONS+1」にした理由→10万回学習させた後に最終的な出力を出すため for(i = 0;i < 9;i++){ net2[i] = w1[i]*x[count] + bias[i]; out2[i+1] = 1/(1 + exp(-net2[i])); } for(i=0;i < 10;i++){ net3 += w2[i]*out2[i]; } out3[count] = 1/(1 + exp(-net3)); //二乗誤差 E = 0.50*(y[count] - out3[count])*(y[count] - out3[count]); if(E == 0.0){ //printf("%d %lf\n",count,out3[count]); break; } else{ //NR } //重み更新(出力~隠れ層間) delta3 = (out3[count] - y[count])*out3[count]*(1-out3[count]);//(out3[count] - y[count])*exp(-net3)/((1+exp(-net3))*(1+exp(-net3))); for(i = 0;i < 10;i++){//w_2の各重み更新 w2[i] = w2[i] - p*delta3*out2[i]; } for(i = 0;i < 9;i++){ bias[i] = bias[i] - p*delta3 * w2[i+1]*out2[i+1]*(1-out2[i+1]);//bias[i] -= p*delta3 * w2[i+1]*exp(-net2[i])/((1+exp(-net2[i]))*(1+exp(-net2[i]))); w1[i] = w1[i] - p*x[count]*delta3 * w2[i+1]*out2[i+1]*(1-out2[i+1]);//w1[i] -= p*x[count]*delta3 * w2[i+1]*exp(-net2[i])/((1+exp(-net2[i]))*(1+exp(-net2[i]))); } if(learing_count < 100){ printf("%lf %lf %lf %lf %lf %lf %lfだよ\n",E,delta3*out2[3],w1[3],w2[3],net2[3],out2[3],out3[count]); } } } for(count = 0;count<50;count++){ fprintf(fp,"%lf\t%lf\t%lf\n",x[count],y[count],out3[count]); } fclose(fp); return 0; }
###一言
自分のできる範囲で参考書を調べ、導出式などを確認してみたのですが、改善されませんでした。どうか相談に乗っていただけると助かります。
計算過程で二乗誤差が小さくならないなど計算過程に問題があるようなのですが・・
回答3件
あなたの回答
tips
プレビュー