ニューラルネットワーク

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
パナソニック

ニューラルネットワーク

#1

投稿記事 by パナソニック » 10年前

ニューラルネットワークを使って、為替未来値を予測するプログラムを作ろうとしています。
ソースコードは以下になります。 使用するデータも添付します。

コード:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>


#define Iunits 5 //入力層
#define Hunits 10 //中間層
#define Ounits 1 //出力層
#define SMAX 256


#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 iout[Iunits];          /*    各層の出力  */ 
double hout[Hunits];
double oout[Ounits];

double dshikiih[Hunits];//しきい値の変化量
double dshikiio[Ounits];

double Eta,Alpha ;/*η,α値*/

double ts[SMAX];/*boxデータを配列*/
double st[SMAX];//教師信号を配列
int tsmax ;//教師信号数

double drand48();

double tsignal[Ounits]; //教師信号

FILE *fpbox;

void initialize();
void foward_propagation();
void back_propagation();


int main (int argc, char *argv[])
{
	unsigned int i,j,kk,k,dn;
	int ct = 0, flag1 = 0 , flag2 = 0;
	int count = 0,number = 0;
	FILE *fp , *fp2;
	char name[SMAX];
	
	if(argc != 3){
		printf("///can't action the program.///\n");
		printf(" ./a.out , Eta , Alpha , boxname ,please \n");
		exit(1);
	}
	
	Eta = atof(argv[1]);
	Alpha = atof(argv[2]);
	
	kk = 15 ; //学習回数
	
	//ニューロンの初期化
	initialize();
	
	/* 為替データのopen */
	fpbox = fopen("data.txt","r");
	if( fpbox == NULL){
		printf("Can't open the file \n");
		exit(1);
	}

	/*為替・データの読み込みとデータ数のカウント*/
	while( fscanf(fpbox,"%lf %lf %lf %lf %lf %lf",&ts[ct],&ts[ct+1],&ts[ct+2],&ts[ct+3],&ts[ct+4],&st[number]) == 6 ){
	ct += 5 ;//入力信号数
	number++;
	}
	
	
	for(i = 0 ; i < ct ; i++){
		printf("boxdate ts[%d]=[ %f ]\n", i,ts[i]);
	}
	
	
	tsmax = ct / 5;//教師信号数
	fclose(fpbox);
	
	
//処理スタート
while(count < tsmax){	
	//データを入力層を格納
	
	printf("ct = %d\n",ct);
	getchar();
	
	printf("Eta = %f Alpha = %f ct = %d tsmax = %d \n",Eta,Alpha,ct,tsmax);
	getchar();
	
	
for(i = 0 ; i < 5 ; i++){
	iout[i] = ts[flag1];
	flag1 = flag1 + 1 ;
}

//教師信号
tsignal[0] = st[flag2];


//学習
for(k = 1 ; k <= kk ; k++){
	foward_propagation();
	
	back_propagation();
	
	}
	
	printf("out[] = %lf\n",oout[0]);
	
	/*
	if( k == kk ){
		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);
	}*/
	
	flag2 ++ ;
	count ++ ;
	printf("count = %d tsmax = %d tsignal = %f \n",count,tsmax,tsignal[0]);
}
}
	
	
	//各ユニットの結合加重に重みを振り分ける
				
void initialize()
{
			int i,j;
			
			for(i = 0 ; i < Hunits ; i++){
				for(j = 0 ; j < Iunits ; j++){
					wih[i][j] = urand(); //結合加重
					
					/*
					printf("wih[i][j] = %lf urand() = %lf",wih[i][j],urand());
					getchar();
					*/
					
				}
				shikiih[i] = urand();
				//printf("shikiih[] = %lf\n",shikiih[i]); //しきい値
			}
			
			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];
		}
		//printf("sum = %lf shikiih = %lf\n",sum , shikiih[i]); 
		hout[i] = fout (sum + shikiih[i]);
	}
	
		//printf("hout[%d] = %f\n",i,hout[i]);
	
	for ( i = 0 ; i < Ounits ; i++ ){
		sum = 0 ;
		for(j = 0 ; j < Hunits ; j++ ){
			sum += who[i][j] * hout[j];
		}
	
		oout[i] = fout(sum + shikiio[i]);
		printf("oout[] = %lf ",oout[i]);
	}
	printf("sum = %f\n",sum);
}


//バックプロパゲーション
void back_propagation()
{
	int i,j;
	double dih[Hunits],dho[Ounits]; //学習信号
	double sum = 0 ;
	
	for(i = 0 ; i < Ounits ; i++){
		//出力の伝達関数はy = x という形になっているので伝達関数の微分は1ということになる
		//出力層の学習信号の計算
		dho[i] = oout[i] * ( 1 - oout[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];
	}
}



データdata.txt

コード:

76.672 76.664 77.191 77.048 76.886 76.825
75.672 72.664 74.191 74.048 73.886 77.822

注:最初の5つのデータは、初値・高値・低値など、 最後のデータは教師信号です。


実行結果は:
k11067kk@pck11067kk$ cc nyu.c
k11067kk@pck11067kk$ ./a.out 0.75 0.8
shikiih[] = 0.231857
shikiih[] = -0.264685
shikiih[] = 0.049619
shikiih[] = -0.254677
shikiih[] = -0.298347
shikiih[] = -0.115929
shikiih[] = -0.208884
shikiih[] = 0.018977
shikiih[] = 0.266334
shikiih[] = -0.177022
boxdate ts[0]=[ 76.672000 ]
boxdate ts[1]=[ 76.664000 ]
boxdate ts[2]=[ 77.191000 ]
boxdate ts[3]=[ 77.048000 ]
boxdate ts[4]=[ 76.886000 ]
boxdate ts[5]=[ 75.672000 ]
boxdate ts[6]=[ 72.664000 ]
boxdate ts[7]=[ 74.191000 ]
boxdate ts[8]=[ 74.048000 ]
boxdate ts[9]=[ 73.886000 ]
ct = 10

Eta = 0.750000 Alpha = 0.800000 ct = 10 tsmax = 2

hout[10] = 76.672000
oout[] = 0.604669 sum = 0.449866
hout[10] = 76.672000
oout[] = 1.000000 sum = 68.924082
hout[10] = 76.672000
oout[] = 1.000000 sum = 123.516245
hout[10] = 76.672000
oout[] = 1.000000 sum = 167.176937
hout[10] = 76.672000
oout[] = 1.000000 sum = 202.081842
hout[10] = 76.672000
oout[] = 1.000000 sum = 229.971421
hout[10] = 76.672000
oout[] = 1.000000 sum = 252.241066
hout[10] = 76.672000
oout[] = 1.000000 sum = 270.011840
hout[10] = 76.672000
oout[] = 1.000000 sum = 284.185239
hout[10] = 76.672000
oout[] = 1.000000 sum = 295.485752
hout[10] = 76.672000
oout[] = 1.000000 sum = 304.494571
hout[10] = 76.672000
oout[] = 1.000000 sum = 311.676850
hout[10] = 76.672000
oout[] = 1.000000 sum = 317.404041
hout[10] = 76.672000
oout[] = 1.000000 sum = 321.972240
hout[10] = 76.672000
oout[] = 1.000000 sum = 325.617193
out[] = 1.000000
count = 1 tsmax = 2 tsignal = 76.825000
ct = 10

Eta = 0.750000 Alpha = 0.800000 ct = 10 tsmax = 2

hout[10] = 75.672000
oout[] = 1.000000 sum = 328.072610
hout[10] = 75.672000
oout[] = 1.000000 sum = 330.373848
hout[10] = 75.672000
oout[] = 1.000000 sum = 332.211104
hout[10] = 75.672000
oout[] = 1.000000 sum = 333.678426
hout[10] = 75.672000
oout[] = 1.000000 sum = 334.850643
hout[10] = 75.672000
oout[] = 1.000000 sum = 335.787342
hout[10] = 75.672000
oout[] = 1.000000 sum = 336.535999
hout[10] = 75.672000
oout[] = 1.000000 sum = 337.134469
hout[10] = 75.672000
oout[] = 1.000000 sum = 337.612949
hout[10] = 75.672000
oout[] = 1.000000 sum = 337.995542
hout[10] = 75.672000
oout[] = 1.000000 sum = 338.301494
hout[10] = 75.672000
oout[] = 1.000000 sum = 338.546175
hout[10] = 75.672000
oout[] = 1.000000 sum = 338.741869
hout[10] = 75.672000
oout[] = 1.000000 sum = 338.898392
hout[10] = 75.672000
oout[] = 1.000000 sum = 339.023589
out[] = 1.000000
count = 2 tsmax = 2 tsignal = 77.822000
実行結果をご覧になると、oout[]は2回目からすべて1に収束してしまいます。
原因がわかりません。
ご指摘をお願い致します。

sleep

Re: ニューラルネットワーク

#2

投稿記事 by sleep » 10年前

パナソニック さんが書きました: 実行結果をご覧になると、oout[]は2回目からすべて1に収束してしまいます。
原因がわかりません。
パナソニックさんの計算式の場合、
sum+shikiioの結果が36.736...を超えると、ooutは1.000000になるプログラムみたいですね。

コード:

#define fout(x) (1 / (1 + exp( -(x) ) ) )
oout[i] = fout(sum + shikiio[i]);
36.737 = sum + shikiio の場合

コード:

1.1100016345655433e-016 = exp(-(36.737))
つまり、
0.00000000000000011100016345655433 = exp(-(36.737))

1.00000000000000000 = 1 / (1 + 0.00000000000000011100016345655433)
36.736 = sum + shikiio の場合

コード:

1.1111121913859779e-016 = exp( -(36.736)
つまり、
0.00000000000000011111121913859779 = exp(-(36.736))

0.99999999999999978 = 1 / (1 + 0.00000000000000011111121913859779)
2回目以降は少なくともsumだけで36.736...を超えてますね。
パナソニック さんが書きました:
hout[10] = 76.672000
oout[] = 0.604669 sum = 0.449866
hout[10] = 76.672000
oout[] = 1.000000 sum = 68.924082
hout[10] = 76.672000
oout[] = 1.000000 sum = 123.516245
2回目の計算を例にします。

コード:

//#define fout(x) (1 / (1 + exp( -(x) ) ) )
//oout[i] = fout(sum + shikiio[i]);

//x = sum + shikiio[i]
82.564202967107391 = 68.924082269293081 + 13.640120697814311;

//exp( -(x) )
1.3893838572131751e-036 = exp(-(82.564202967107391));
つまり、
0.0000000000000000000000000000000000013893838572131751 = exp(-(82.564202967107391));

//#define fout(x) (1 / (1 + exp( -(x) ) ) )
1.000000 = 1 / (1 + 1.3893838572131751e-036);
つまり、
1.000000 = 1 / (1 + 0.0000000000000000000000000000000000013893838572131751);
oout[]が2回目からすべて1に収束している理由は上記のとおりです。

もし、プログラムが正しく動作するような指摘をお求めであるとすれば、恐らくそれは難しいです。
プログラムというよりは、計算過程などの仕様が正しいかどうかの問題なので
プログラムに落とす前の計算式やデータの集計方法などの仕様を基に、銀行や証券会社の金融アナリストなど為替計算に詳しい方に計算方法が正しいかどうか、ご相談された方が良い気がします。
少なくとも私には、sumなどの集計方法や計算過程に間違いがあるかどうかは、仕様が分からないので判断が付きませんし、指摘することはできません。

閉鎖

“C言語何でも質問掲示板” へ戻る