/*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];
}
}