/*b_type 学習プログラム*/ #include <stdio.h> #include <math.h> #include <string.h> #include <local/bgi.h> #define Iunits 14 /* 各ユニットの個数 */ #define Hunits 200 #define Ounits 2 #define Rlow -0.30 #define Rhigh 0.30 #define A 1.4 #define B 0.3 #define fout(x) ( 1 / (1 + exp( -(x) ) )) #define urand() ( drand48()* (Rhigh - Rlow) + Rlow ) double wih[Hunits][Iunits]; /* 結合荷重(重み) */ double who[Ounits][Hunits]; double dwih[Hunits][Iunits]; /* 重みの変化量 */ double dwho[Ounits][Hunits]; double shikiih[Hunits]; /* しきい値 */ double shikiio[Ounits]; double dshikiih[Hunits]; /* しきい値の変化量 */ double dshikiio[Ounits]; double iout[Iunits]; /* 各層の出力 */ double hout[Hunits]; double oout[Ounits]; double tsignal[Ounits]; /* 教師信号 */ double drand48(); double Eta,Alpha; double data[5000]; /*気温データ配列*/ FILE *fpkion; /*気温ファイルポインタ*/ void foward_propagation(); void back_propagation(); void initialize(); main(argc,argv) int argc; char *argv[]; /*メインへのいん数引渡し 実際にはEta,Alphaを決める*/ { FILE *fp,*fp2; int cc,ave,j; long kaisuu; long kaisuumax; unsigned int i,dn,k,kk; char name[64],kion[64],a[64],graph[64]; double averror,dummy,error,serror,max_syokichi,mim_syokichi,x,dsitudo; Eta=atof(argv[1]); Alpha=atof(argv[2]); cc=0; if (argc != 4){ printf(" Usage : kion \n" ); exit(-1); } kaisuumax=3; /*学習年数*/ kaisuumax =(kaisuumax*365)+1; /*dn=atoi(argv[4]);*/ kk=30000; /*学習 回数*/ /*気温データファイルの指定*/ strcpy(kion,argv[3]); /*ニューロンの初期化*/ initialize(); /*気温データファイルのオープン*/ fpkion = fopen(kion,"r"); if (fpkion==NULL){ printf("can't open the file\n"); exit(1); } /*気温データを配列に代入*/ for (i=0 ; i< kaisuumax*2 ; i++){ fscanf(fpkion,"%lf\n",&x); data[i]=x; } /*気温データファイルのクローズ*/ fclose(fpkion); error=0; serror=0; /*学習中における誤差変化ファイルのオープン*/ sprintf(name,"Berror_E%0.4f_A%0.2f.data",Eta,Alpha); fp = fopen(name,"w"); if (fp == NULL){ fprintf(stderr,"error\n"); exit(1); } for (k=1; k<=kk ; k++){ /*初期値入力*/ for (i=0 ; i<14 ; i++){ iout[i] = data[i]; } for ( kaisuu = 7; kaisuu < kaisuumax ;kaisuu++ ){ tsignal[0]=data[kaisuu*2]; tsignal[1]=data[kaisuu*2+1]; foward_propagation(); back_propagation(); for (i = 0; i < 12; i++){ iout[i] = iout[i+2]; } iout[12] = tsignal[0]; iout[13] = tsignal[1]; } /*500回ごとに各ニューロンの重みの記録をする*/ if(k%500==0){ dn=k/100; sprintf(name,"b%d_E%0.4f_A%0.2f.data",dn,Eta,Alpha); fp2 = fopen(name,"w"); if (fp2 == NULL){ fprintf(stderr,"error\n"); exit(1); } /*最終的な各ユニット、その他のデータをファイルに書き込む*/ fwrite(wih,sizeof(double),Iunits * Hunits,fp2); fwrite(who,sizeof(double),Hunits * Ounits,fp2); fwrite(shikiih,sizeof(double),Hunits,fp2); fwrite(shikiio,sizeof(double),Ounits,fp2); fclose(fp2); } /*50回ごとにネットワークに予測をさせ誤差を記録*/ if(k%50==0){ for (i=0 ; i<14 ; i++){ iout[i] = data[i]; } serror=0; for ( kaisuu = 7; kaisuu < kaisuumax ;kaisuu++ ){ tsignal[0]=data[kaisuu*2]; tsignal[1]=data[kaisuu*2+1]; foward_propagation(); error = 0; for (i = 0; i < Ounits; i++){ dummy = tsignal[i] - oout[i]; error += (dummy * dummy); } error =sqrt(error); serror += error; for (i = 0; i < 12; i++){ iout[i] = iout[i+2]; } iout[12] = tsignal[0]; iout[13] = tsignal[1]; } averror=serror/kaisuumax; fprintf(fp,"%d\t%f\n",k,averror); printf("%d\t%f\n",k,averror); } } fclose(fp); putchar('G'-'@'); } void initialize()/*各ユニットに乱数で重みを振り当てる*/ { int i,j; for (i = 0; i < Hunits; i++){ for (j = 0; j < Iunits; j++){ wih[i][j] = urand(); } shikiih[i] = urand(); } for (i = 0; i < Ounits; i++){ for (j = 0; j < Hunits; j++){ who[i][j] = urand(); } shikiio[i] = urand(); } } void foward_propagation() { int i,j; double sum; for (i = 0; i < Hunits; i++){ sum = 0; for (j = 0; j < Iunits; j++){ sum += wih[i][j] * iout[j]; } hout[i] = fout(sum + shikiih[i]); } for (i = 0; i < Ounits; i++){ sum = 0; for (j = 0; j < Hunits; j++){ sum += who[i][j] * hout[j]; } /*出力は0~1ではないので伝達関数にはかけない*/ oout[i] = sum + shikiio[i]; } } void back_propagation() { int i,j; double dih[Hunits],dho[Ounits]; /* 学習信号 */ double sum; for (i = 0; i < Ounits; i++){ /*出力の伝達関数はy=xという形になっているので 伝達関数の微分は1ということになる*/ /*出力層の学習信号の計算*/ dho[i] = (tsignal[i] - oout[i]); } /*出力の重み補正*/ for (i = 0; i < Hunits; i++){ for (sum = 0, j = 0; j < Ounits; j++){ dwho[j][i] = (Eta * dho[j] * hout[i]) + (Alpha * dwho[j][i]); sum += (dho[j] * who[j][i]); who[j][i] += dwho[j][i]; } /*中間層の教師信号の計算*/ dih[i] = hout[i] * (1 - hout[i]) * sum; } /*出力のしきい値補正*/ for (i = 0; i < Ounits; i++){ dshikiio[i] = (Eta * dho[i]) + (Alpha * dshikiio[i]); shikiio[i] += dshikiio[i]; } /*中間層の重み補正*/ for (i = 0; i < Iunits; i++){ for (j = 0; j < Hunits; j++){ dwih[j][i] = (Eta * dih[j] * iout[i]) + (Alpha * dwih[j][i]); wih[j][i] += dwih[j][i]; } } /*中間層のしきい値補正*/ for (i = 0; i < Hunits; i++){ dshikiih[i] = (Eta * dih[i]) + (Alpha * dshikiih[i]); shikiih[i] += dshikiih[i]; } }