Next: この文書について ...
Up: 無題
Previous: 付 録A Btype気温予測学習プログラム
/*一日の気温だけを入力、出力1日分とゴミ六日分 c_type*/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <local/bgi.h>
#define Iunits 14 /* 各ユニットの個数 */
#define Hunits 200
#define Ounits 14
#define Tunits 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 hkeep[Hunits]; /* houtをとっておく */
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[]; /*メインへのいん数引渡し 実際にはkaisuumaxを決める*/
{
FILE *fp,*fp2;
int gd,gm,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;
Eta=atof(argv[1]);
Alpha=atof(argv[2]);
if (argc != 4){
printf(" Usage : kion \n" );
exit(-1);
}
kaisuumax=3; /*学習年数*/
kaisuumax =kaisuumax*365+1;
kk=3000; /*学習回数*/
/*気温データファイルの指定*/
strcpy(kion,argv[3]);
error = serror = 0;
/*気温データファイルのオープン*/
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);
/*学習中における誤差変化ファイルのオープン*/
sprintf(name,"Cerror_varE_A%0.1f.dat2",Alpha);
fp = fopen(name,"w");
if (fp == NULL){
fprintf(stderr,"error\n");
exit(1);
}
/*ニューロンの初期化*/
initialize();
for (k=1; k<=kk ; k++){
/*初期値入力*/
for (i=0 ; i<Tunits ; i++){
iout[i] = data[i];
}
/*一定の学習回数で定数を変化*/
if(k==3000)Eta=0.00004;
if(k==8000)Eta=0.00002;
if(k==16200)Eta=0.00001;
/*六日分空回りさせる*/
for ( kaisuu = 1 ; kaisuu < 7 ; kaisuu++ ){
tsignal[0]=data[kaisuu*2];
tsignal[1]=data[kaisuu*2+1];
foward_propagation();
for (i =Tunits ; i < Iunits; i++){
iout[i] = oout[i];
}
iout[0] = tsignal[0];
iout[1] = tsignal[1];
}
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<Hunits;i++){
hkeep[i]=hout[i];
}
for (i =Tunits ; i < Iunits; i++){
iout[i] = oout[i];
}
iout[0] = tsignal[0];
iout[1] = tsignal[1];
}
/*500回ごとに各ニューロンの重みの記録をする*/
if (k%500 == 0){
dn=k/100;
sprintf(name,"c%d_E%0.5f_A%0.1f.data",dn,Eta,Alpha);
printf("500data OK\n");
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<Tunits ; i++){
iout[i] = data[i];
}
serror=0;
/*六日分空回りさせる*/
for ( kaisuu = 1 ; kaisuu < 7 ; kaisuu++ ){
tsignal[0]=data[kaisuu*2];
tsignal[1]=data[kaisuu*2+1];
foward_propagation();
for (i =Tunits ; i < Iunits; i++){
iout[i] = oout[i];
}
iout[0] = tsignal[0];
iout[1] = tsignal[1];
}
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 < Tunits; i++){
dummy = tsignal[i] - oout[i];
error += (dummy * dummy);
}
error =sqrt(error);
serror += error;
for (i =Tunits ; i < Iunits; i++){
iout[i] = oout[i];
}
iout[0] = tsignal[0];
iout[1] = tsignal[1];
}
averror=serror/kaisuumax;
printf( "%d\tavERROR = %5.10f\n",k,averror);
fprintf(fp,"%d\t%f\n",k,averror);
}
}
fclose(fp);
printf("\nkaisuu = %d\n",k);
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 < Tunits; i++){
/*出力の伝達関数はy=xという形になっているので
伝達関数の微分は1ということになる*/
/*出力層の学習信号の計算*/
dho[i] = (tsignal[i] - oout[i]);
}
/*出力の重み補正、教師信号ありの部分*/
for (i = 0; i < Hunits; i++){
for (sum = 0, j = 0; j < Tunits; j++){
dwho[j][i] = (Eta * dho[j] * hout[i]) + (Alpha * dwho[j][i]);
who[j][i] += dwho[j][i];
sum += (dho[j] * who[j][i]);
}
/*中間層の学習信号の計算*/
dih[i] = hout[i] * (1 - hout[i]) * sum;
}
/*出力のしきい値補正教師信号ありの部分*/
for (i = 0; i < Tunits; i++){
dshikiio[i] = (Eta * dho[i]) + (Alpha * dshikiio[i]);
shikiio[i] += dshikiio[i];
}
/*中間層の重み補正*/
for (i = 0; i < Iunits; i++){
for (sum = 0, j = 0; j < Hunits; j++){
dwih[j][i] = (Eta * dih[j] * iout[i]) + (Alpha * dwih[j][i]);
wih[j][i] += dwih[j][i];
sum+= (dih[j] * wih[j][i]);
}
if(i>Tunits-1)
dho[i] = sum;
}
/*中間層のしきい値補正*/
for (i = 0; i < Hunits; i++){
dshikiih[i] = (Eta * dih[i]) + (Alpha * dshikiih[i]);
shikiih[i] += dshikiih[i];
}
/*出力の重み補正、教師信号なしの部分*/
for (i=0; i<Hunits; i++){
for (j=Tunits; j<Ounits; j++){
dwho[j][i]=(Eta * dho[j] * hkeep[i])+ (Alpha * dwho[j][i]);
who[j][i]+= dwho[j][i];
}
}
/*出力のしきい値補正教師信号なしの部分*/
for (i = Tunits; i < Ounits; i++){
dshikiio[i]=(Eta*dho[i]) + (Alpha * dshikiio[i]);
shikiio[i]+= dshikiio[i];
}
}
Deguchi Toshinori
Tue Feb 23 15:28:33 JST 1999