/*内部記憶を持つ一つのネットワークに*/
/*二つの写像を学習させるプログラム*/
/*学習回数百万回ごとに定数を半分にしながら*/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <local/bgi.h>
#define Iunits 8 /* 各ユニットの個数 */
#define Hunits 50
#define Ounits 8
#define Tunits 2 /*教師信号を受けとるユニット数*/
#define TP 300 /*教師信号を変化させる学習回数*/
#define Rlow -0.30
#define Rhigh 0.30
#define X_SYOKICHI 0.1
#define Y_SYOKICHI 0.1
#define A 1.4
#define B 0.3
#define AA 0.4
#define BB -1.2
double Eta = 0.01;
double Alpha = 0.5;
#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 hkeep[Hunits];
double tsignal[2][Tunits]; /* 教師信号 */
double *tsignal1 = tsignal[0],
*tsignal2 = tsignal[1];
double drand48();
void teach_signal1();
void teach_signal2();
void (*teach_signal[2])() = {teach_signal1, teach_signal2};
main()
{
FILE *fp;
long kaisuu;
long kaisuumax;
int i,j,sw;
char name[64];
double dummy,error,serror,herror;
double eta = Eta,
alpha = Alpha;
void foward_propagation();
void back_propagation();
void initialize();
printf("file name = ?");
scanf("%s",name);
fp = fopen(name,"w");
if (fp == NULL){
fprintf(stderr,"error\n");
exit(1);
}
initialize();
tsignal1[0] = tsignal2[0] = X_SYOKICHI;
tsignal1[1] = tsignal2[1] = Y_SYOKICHI;
for (i = 0; i < Tunits / 2; i++) {
teach_signal1();
teach_signal2();
}
for (i = 0; i < Tunits; i++)
iout[i] = tsignal1[i];
for (i = Tunits; i < Ounits; i++)
iout[i] = 0.0;
error = 2;
serror = 0;
herror = 0;
sw = 0;
kaisuu = 1;
kaisuumax = 10000000;
while (kaisuu <= kaisuumax){
for ( j = 0; j < 5; j++){
foward_propagation();
teach_signal[sw]();
for (i = 0; i < Hunits; i++){
hkeep[i] = hout[i];
}
for (i = 0; i < Tunits; i++){
iout[i] = tsignal[sw][i];
}
for (i = Tunits; i < Ounits; i++){
iout[i] = oout[i];
}
}
for ( j = 0; j < TP; j++, kaisuu++){
if (kaisuu % 1000000 == 0) { /*学習回数百万回ごとに*/
Eta /= 2.0; /*定数を半分にする*/
Alpha /= 2.0;
}
teach_signal[sw]();
foward_propagation();
error = 0;
for (i = 0; i < Tunits; i++){
dummy = tsignal[sw][i] - oout[i];
error += (dummy * dummy);
}
error *= 0.5;
herror += error;
if (serror < error){
serror = error;
}
if (kaisuu % 100000 == 0){
herror /= 100000;
/*10万回ごとに各ユニットの状態を表示*/
printf( "\n%5d\n",kaisuu);
printf( " x(t) = %3.5f",iout[0]);
printf( " x(t+1) = %3.5f",oout[0]);
printf( " kyoushi = %3.5f",tsignal[sw][0]);
printf( "\n y(t) = %3.5f",iout[1]);
printf( " y(t+1) = %3.5f",oout[1]);
printf( " kyoushi = %3.5f",tsignal[sw][1]);
printf( "\nMaxEr = %5.10f Er_Heikin = %5.10f",serror,herror);
/*10万回ごとに各ユニットのデータをファイルに書き込む*/
fwrite(tsignal1,sizeof(double),Tunits,fp);
fwrite(tsignal2,sizeof(double),Tunits,fp);
fwrite(wih,sizeof(double),Iunits * Hunits,fp);
fwrite(who,sizeof(double),Hunits * Ounits,fp);
fwrite(shikiih,sizeof(double),Hunits,fp);
fwrite(shikiio,sizeof(double),Ounits,fp);
serror = 0;
}
back_propagation(sw);
for (i = 0; i < Hunits; i++){
hkeep[i] = hout[i];
}
for (i = 0; i < Tunits; i++){
iout[i] = tsignal[sw][i];
}
for (i = Tunits; i < Ounits; i++){
iout[i] = oout[i];
}
}
sw = 1 - sw;
}
fclose(fp);
printf("\nkaisuu = %d\n",kaisuu);
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 teach_signal1()
{
int i;
double x, y;
#if 0
for (i = Tunits - 1; i > 2; i -= 2) {
tsignal1[i] = tsignal1[i - 2];
tsignal1[i - 1] = tsignal1[i - 3];
}
#endif
x = tsignal1[0];
y = tsignal1[1];
tsignal1[0] = y + 1 - A * x * x;
tsignal1[1] = B * x;
#if 0
tsignal1[2] = A;
tsignal1[3] = B;
#endif
}
/*教師信号折り曲げ写像の計算*/
void teach_signal2()
{
int i;
double x, y;
#if 0
for (i = Tunits - 1; i > 2; i -= 2) {
tsignal2[i] = tsignal2[i - 2];
tsignal2[i - 1] = tsignal2[i - 3];
}
#endif
x = tsignal2[0];
y = tsignal2[1];
tsignal2[0] = y + AA * x;
tsignal2[1] = BB + x * x;
#if 0
tsignal2[2] = AA;
tsignal2[3] = BB;
#endif
}
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];
}
oout[i] = sum + shikiio[i];
}
}
void back_propagation(x)
int x;
{
int i,j;
double dih[Hunits],dht[Tunits],dho[Ounits]; /* 学習信号 */
double sum;
for (i = 0; i < Tunits; i++){
dht[i] = (tsignal[x][i] - oout[i]);
}
for (i = 0; i < Hunits; i++){
for (sum = 0, j = 0; j < Tunits; j++){
dwho[j][i] = (Eta * dht[j] * hout[i]) + (Alpha * dwho[j][i]);
who[j][i] += dwho[j][i];
sum += (dht[j] * who[j][i]);
}
dih[i] = hout[i] * (1 - hout[i]) * sum;
}
for (i = 0; i < Tunits; i++){
dshikiio[i] = (Eta * dht[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]);
}
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];
}
}