/* 学習プログラム(内部記憶を持つニューラルネットワーク) */
/* ヘッダ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define ON ( 1.0 )
#define OFF ( 0.0 )
/* 各層の値 */
/* 教師信号を増やす時は( 2 + 10 + 15 )と書いておく */
#define Inunit ( 2 + 25 )
#define Midunit 50
#define Outunit ( 2 + 25 )
#define Tunit 2
#define SMAX 256
#define Time 40
#define Rhigh 0.30
#define Rlow -0.30
#define urand() ( drand48() * ( Rhigh - Rlow ) + Rlow )
#define Lhigh 1.0
#define Llow 0
#define Kaisou ( 20 + 1 )
#define zoubun 0.05
#define filenumber 1
#define qrand() ( drand48() * ( Lhigh - Llow ) + Llow )
/* 各層の重み */
double wim[Midunit][Inunit];
double wmo[Outunit][Midunit];
/* 各層重みの変化分 */
double dwim[Midunit][Inunit];
double dwmo[Outunit][Midunit];
/* しきい値 */
double sikiiim[Midunit];
double sikiimo[Outunit];
/* しきい値の変化分 */
double dsikiiim[Midunit];
double dsikiimo[Outunit];
/* 各層の出力 */
double inout[Inunit][Time];
double midout[Midunit];
double outout[Outunit];
double tout[Tunit];
double inkeep[Inunit][Time];
double midkeep[Midunit];
double tsignal[Outunit];
double outkeep[Outunit];
double drand48();
double Eta,Alpha;
double ts[SMAX];
int g,m;
double gosa[Outunit][Time];
double kekka[Outunit];
int tsmax,count;
int t;
FILE *fpmusic , *fi;
FILE *fpplot;
FILE *fpin;
FILE *fpkakunin;
FILE *fpnaibu;
FILE *fpfault;
char figosa[SMAX],fiplot[SMAX];
char fiin[SMAX];
char fikakunin[SMAX];
char finaibu[SMAX];
char fifault[SMAX];
/* シグモイド関数 */
double fsig( double in ){
double out;
if( in <= -24 ){
in = -24;
}
out = ( 1 / ( 1 + exp ( - ( in ) )));
return( out );
}
/* 関数の定義 */
double fl();
double lenseik();
double pitseik();
int rd();
void initialize();
void zettaiti();
void bunbetu();
void forward_propagation();
void back_propagation();
/* main関数 */
void main( int argc , char *argv[] ){
int ct;
int a,b;
int flag,fault;
unsigned int dn,i,k,kk;
long kaisuu;
double averror,dummy,error,serror;
double gsritu;
char c,music[SMAX],name[SMAX],nyu[Inunit];
FILE *fp,*fp2;
char infile[Inunit * Time],infile2[Inunit * Time];
FILE *infi,*infi2;
if( argc != 4 ){
printf( "Usage : main Eta Alpha songname\n" );
exit(1);
}
Eta = atof( argv[1] );
Alpha = atof( argv[2] );
/* musicファイルの指定 */
strcpy( music , argv[3] );
error = serror = 0;
/* musicファイルのオープン */
fpmusic = fopen( music,"r" );
if( fpmusic == NULL ){
printf( "Can't open the file \n " );
exit(1);
}
/* データの読み込みとデータ数のカウント */
ct = 0;
while( fscanf( fpmusic,"%lf %lf",&ts[ct],&ts[ct + 1] ) == 2 ){
ct += 2;
}
/* 教師信号を記憶 */
tsmax = ct / 2;
/* musicファイルのクローズ */
fclose( fpmusic );
/* ニューロンの初期化 */
initialize();
/* 誤差をファイルに書き込む */
sprintf( figosa , "kekka9/gosa_ver%dE%0.3f_A%0.3f.dat" ,filenumber,Eta ,Alpha );
fi = fopen( figosa ,"w" );
if( fi == NULL ){
fprintf( stderr, "File not open!\n" );
exit(1);
}
sprintf( fikakunin , "kekka9/kakunin_ver%d.dat",filenumber );
fpkakunin = fopen( fikakunin ,"w" );
if( fpkakunin == NULL ){
fprintf( stderr , "File(plot) not open!\n" );
exit(1);
}
sprintf( finaibu , "kekka9/naibu_ver%d.dat",filenumber );
fpnaibu = fopen( finaibu ,"w" );
if( fpnaibu == NULL ){
fprintf( stderr , "File(plot) not open!\n" );
exit(1);
}
sprintf( fiplot , "kekka9/plot_ver%dE%0.3f_A%0.3f.dat",filenumber,Eta,Alpha );
fpplot = fopen( fiplot ,"w" );
if( fpplot == NULL ){
fprintf( stderr , "File(plot) not open!\n" );
exit(1);
}
sprintf( fifault , "kekka9/fault_ver%dE%0.3f_A%0.3f.dat",filenumber,Eta,Alpha );
fpfault = fopen( fifault ,"w" );
if( fpfault == NULL ){
fprintf( stderr , "File(fault) not open!\n" );
exit(1);
}
/* 入力を確認 */
sprintf( fiin,"kekka9/inoutfile%d.dat",filenumber );
fpin = fopen( fiin ,"w" );
if( fpin == NULL ){
fprintf( stderr, "File not open!\n" );
exit(1);
}
/* 初期値入力 */
for( t = 0 ; t < tsmax ; t++ ){
for( i = 0 ; i < Tunit ; i++ ){
inout[i][t] = ts[t * Tunit + i];
}
}
for( t = 0 ; t < tsmax ; t++ ){
for( i = 0 ; i < Inunit ; i++ ){
inkeep[i][t] = inout[i][t];
}
}
/* 過去10音を入力として与える */
/*b = 0;
for( t = 0 ; t < tsmax ; t++ ){
b = 0;
for( i = 2 , a = 28 + t ; i < 22 ; i = i + 2 , a++ ){
if( a >= tsmax + 0 ){
a = 0 + b;
b++;
if( b >= tsmax ){
b = 0;
}
}
inout[i][t] = inkeep[0][a];
inout[i + 1][t] = inkeep[1][a];
}
}*/
/* ランダムに2値を与える */
for( t = 0 ; t < tsmax ; t++ ){
for( i = 2 ; i < 12 ; i++ ){
inout[i][t] = urand();
if( inout[i][t] < -0.04 ){
inout[i][t] = 0.0;
}else{
inout[i][t] = 1.0;
}
}
}
for( t = 0 ; t < tsmax ; t++ ){
for( i = 0 ; i < Inunit ; i++ ){
inkeep[i][t] = inout[i][t];
}
}
/* 学習開始 */
kk = 150000; /* 学習回数 */
for( k = 0 ; k < kk ; k++ ){
m = k;
/* 初期値入力 */
for( t = 0 ; t < tsmax ; t++ ){
for( i = 0 ; i < Tunit ; i++ ){
inout[i][t] = ts[t * Tunit + i];
}
}
for( t = 0 ; t < tsmax ; t++ ){
for( i = 2 ; i < 12 ; i++ ){
inout[i][t] = inkeep[i][t];
}
}
/* 学習部分 */
serror = 0;
flag = 0;
for( t = 0 ; t < tsmax ; t++ ){
/*fprintf( fpkakunin , "\n" );*/
if ( t + 2 < tsmax ) {
tsignal[0] = ts[t * 2 + 2];
tsignal[1] = ts[t * 2 + 3];
} else {
tsignal[0] = ts[0];
tsignal[1] = ts[1];
}
for( a = 0 ; a < Outunit ; a++ ){
outkeep[a] = outout[a];
}
forward_propagation();
g = t + 1;
if( g >= tsmax ){
g = 0 ;
}
if( k % 1000 == 0 || k == kk - 1 ){
for( a = 0 ; a < Outunit ; a++ ){
gosa[a][t] = inkeep[a][g] - outout[a];
kekka[a] = sqrt( gosa[a][t] * gosa[a][t] );
}
if( t == 0 ){
fprintf( fpplot , "%d %f",( k / 1000 ) , kekka[0] );
fprintf( fpplot , " %f\n" , kekka[1] );
fprintf( fpnaibu , "%d %f",( k / 1000 ) , outout[14] );
fprintf( fpnaibu , " %f %f\n", outout[15],outout[16] );
}
}
bunbetu();
/*for( b = 2 ; b < 22 ; b = b + 2 ){
outout[b] = lenseik( outout[b] );
outout[b + 1] = pitseik( outout[b + 1] );
}*/
/*for( b = 2 ; b < 22 ; b++ ){
if( outout[b] >= 0.5 ){
outout[b] = 1.0;
}else{
outout[b] = 0.0;
}
}*/
/*outout[0] = lenseik( outout[0] );
outout[1] = pitseik( outout[1] );*/
if( k % 1000 == 0 || k == kk - 1 ){
for( a = 0 ; a < Outunit ; a++ ){
gosa[a][t] = inkeep[a][g] - outout[a];
kekka[a] = sqrt( gosa[a][t] * gosa[a][t] );
}
}
if( k % 10000 == 0 || k == kk - 1 ){
printf( "%d\n", k / 10000 );
}
if( k == 0 || k == 150000 ){
fprintf( fpin , "t = %d\n",t );
for( b = 0 ; b < Inunit ; b++ ){
fprintf( fpin , "inout[%d][%d] = %f",b,t,inout[b][t] );
fprintf( fpin , " outout[%d] = %f\n",b,outout[b] );
}
}
if( k == kk - 1 ){
/* 量子化できる範囲でなければ学習回数を増やす */
if( kekka[0] > 0.1 || kekka[1] > 0.01 ){
fprintf( fpfault ,"%d %d", ( k / 1000 ),t );
fprintf( fpfault ," %f",kekka[0] );
fprintf( fpfault ," %f\n",kekka[1] );
if( flag == 0 ){
kk = kk + 1000;
flag++;
}
}
}
back_propagation();
/*bunbetu();*/
/* 音の高さ、長さを量子化する */
outout[0] = lenseik( outout[0] );
outout[1] = pitseik( outout[1] );
for( b = 0 ; b < Midunit ; b++ ){
midkeep[b] = midout[b];
}
/* 状態を次に記憶させる */
for( b = 12 ; b < Inunit ; b++ ){
/*for( b = Tunit ; b < Inunit ; b++ ){*/
if( t >= tsmax - 1 ){
inout[b][0] = outout[b];
}
inout[b][t + 1] = outout[b];
}
}
/*printf( "kaisuu = %d \n",k );*/
}
fprintf( fi , "k = %d\n",( k + 1 ) );
for( t = 0 ; t < tsmax ; t++ ){
for( b = 0 ; b < Outunit ; b++ ){
fprintf( fi , "inout[%d][%d] = %f",b,t,inout[b][t]);
fprintf( fi , " outkeep[%d] = %f",b,outkeep[b] );
fprintf( fi , " outout[%d] = %f\n",b,outout[b] );
}
}
/* 最後にニューロンの重みを記録する */
/*printf( "ok7\n" );*/
if( k == kk ){
dn = k / 100;
sprintf( name,"kekka9/%dc%d_E%0.3f_A%0.3f.data",filenumber,dn,Eta,Alpha );
fp2 = fopen( name,"w" );
if( fp2 == NULL ){
fprintf( stderr,"Error\n" );
exit(1);
}
/* 最終的な各ユニット、その他のデータをファイルに書き込む */
fwrite( inout , sizeof( double ),Inunit * Time ,fp2 );
fwrite( wim,sizeof( double ),Inunit * Midunit ,fp2 );
fwrite( wmo,sizeof( double ),Midunit * Outunit ,fp2 );
fwrite( sikiiim,sizeof( double ),Midunit ,fp2 );
fwrite( sikiimo,sizeof( double ),Outunit ,fp2 );
fclose( fp2 );
}
/*fclose( fpkakunin );*/
fclose( fpin );
fclose( fpplot );
fclose( fpnaibu );
fclose( fpfault );
/*fclose( fp );*/
fclose( fi );
printf( "\nkaisuu = %d \n",k );
putchar( 'G' - '@' );
}
/* 各重み、しきい値にランダムな値を与える 関数:initialize() */
void initialize(){
int i,j;
int a,b;
for( j = 0 ; j < Midunit ; j++ ){
for( i = 0 ; i < Inunit ; i++ ){
wim[j][i] = urand();
}
sikiiim[j] = urand();
}
for( j = 0 ; j < Outunit ; j++ ){
for( i = 0 ; i < Midunit ; i++ ){
wmo[j][i] = urand();
}
sikiimo[j] = urand();
}
/* 各差分値を初期化しておく */
for( a = 0 ; a < Inunit ; a++ ){
for( b = 0 ; b < Midunit ; b++ ){
dwim[b][a] = 0;
}
}
for( a = 0 ; a < Midunit ; a++ ){
for( b = 0 ; b < Outunit ; b++ ){
dwmo[b][a] = 0;
}
}
for( a = 0 ; a < tsmax ; a++ ){
for( b = 0 ; b < Inunit ; b++ ){
inout[b][a] = 0;
inkeep[b][a] = 0;
}
}
for( a = 0 ; a < Midunit ; a++ ){
midkeep[a] = 0;
dsikiiim[a] = 0;
}
for( a = 0 ; a < Outunit ; a++ ){
dsikiimo[a] = 0;
}
}
/* ランダムデータを階層化する */
void bunbetu(){
int i,j;
double k;
double hanbetu[Kaisou];
for( i = 0 , k = -( zoubun / 2 ) ; i < Kaisou ; i++ , k = k + zoubun ){
hanbetu[i] = k;
}
hanbetu[Kaisou] = 100.0;
/*for( i = Tunit ; i < Outunit ; i++ ){*/
for( i = 12 ; i < Outunit ; i++ ){
for( j = 0 ; j < Kaisou ; j++ ){
if( outout[i] < hanbetu[j + 1] && outout[i] >= hanbetu[j] ){
outout[i] = hanbetu[j] + ( zoubun / 2 );
}
}
}
}
double fl( double x ){
return( -log( x ) / ( M_LN2 * 5 ) + 1 );
}
double lenseik( double len ){
if( len <= ( fl(12) - fl(16) ) / 2 + fl(16) ){
return( fl(16) );
}else if( len <= ( fl(8) - fl(12) ) / 2 + fl(12) ){
return( fl(12) );
}else if( len <= ( fl(6) - fl(8) ) / 2 + fl(8) ){
return( fl(8) );
}else if( len <= ( fl(4) - fl(6) ) / 2 + fl(6) ){
return( fl(6) );
}else if( len <= ( fl(3) - fl(4) ) / 2 + fl(4) ){
return( fl(4) );
}else if( len <= ( fl(2) - fl(3) ) / 2 + fl(3) ){
return( fl(3) );
}else if( len <= ( fl(1.5) - fl(2) ) / 2 + fl(2) ){
return( fl(2) );
}else if( len <= ( 1 - fl(1.5) ) / 2 + fl(1.5) ){
return( fl(1.5) );
}else if( len <= 1 ){
return( 1 );
}
}
double pitseik( double pit ){
int p;
pit *= 40.0;
p = rd( pit );
return( ( double ) p / 40 );
}
int rd( double a ){
char buf[10],*s;
int b;
sprintf( buf,"%lf",a );
s = strchr( buf,'.' );
if( s == NULL ){
return( ( int ) a );
}
s++;
if( *s - '0' < 4 ){
b = a;
}else{
b = a + 1;
}
return( b );
}
/* フォワードプロパゲーション 関数:forward_propagation() */
void forward_propagation(){
int i,j,h;
double sum;
for( j = 0 ; j < Midunit ; j++ ){
sum = 0;
for( i = 0 ; i < Inunit ; i++ ){
sum += wim[j][i] * inout[i][t];
}
midout[j] = fsig( sum + sikiiim[j] );
}
for( j = 0 ; j < Outunit ; j++ ){
sum = 0;
for( i = 0 ; i < Midunit ; i++ ){
sum += wmo[j][i] * midout[i];
}
outout[j] = fsig( sum + sikiimo[j] );
/*outout[j] = sum + sikiimo[j];*/
}
}
/* バックプロパゲーション 関数:back_propagation() */
void back_propagation(){
int i,j,h;
/* 誤差 */
double dim[Midunit];
double dmo[Outunit];
double sum;
h = t + 1;
if( h >= tsmax ){
h = 0;
}
for( j = 0 ; j < 12 ; j++ ){
/*for( j = 0 ; j < Tunit ; j++ ){*/
dmo[j] = outout[j] * ( 1 - outout[j] ) * ( inkeep[j][h] - outout[j] );
/*dmo[j] = ( inkeep[j][h] - outout[j] );*/
}
/* 出力の重み補正 */
for( j = 0 ; j < Midunit ; j++ ){
for( sum = 0 , i = 0 ; i < 12 ; i++ ){
/*for( sum = 0 , i = 0 ; i < Tunit ; i++ ){*/
dwmo[i][j] = ( Eta * dmo[i] * midout[j] ) + ( Alpha * dwmo[i][j] );
/*wmo[i][j] += dwmo[i][j];*/
sum += ( dmo[i] * wmo[i][j] );
wmo[i][j] += dwmo[i][j];
}
/* 中間層の学習信号の計算 */
dim[j] = midout[j] * ( 1 - midout[j] ) * sum;
}
/* 出力のしきい値補正 */
for( j = 0 ; j < 12 ; j++ ){
/*for( j = 0 ; j < Tunit ; j++ ){*/
dsikiimo[j] = ( Eta * dmo[j] ) * ( Alpha * dsikiimo[j] );
sikiimo[j] += dsikiimo[j];
}
/* 中間層の重み補正 */
for( j = 0 ; j < Inunit ; j++ ){
for( sum = 0 , i = 0 ; i < Midunit ; i++ ){
dwim[i][j] = ( Eta * dim[i] * inout[j][t] ) + ( Alpha * dwim[i][j] );
/*wim[i][j] += dwim[i][j];*/
sum += ( dim[j] * wim[j][i] );
wim[i][j] += dwim[i][j];
}
if( j > Tunit -1 ){
/*dmo[j] = sum;*/
dmo[j] = inout[j][t] * ( 1 - inout[j][t] ) * sum;
}
}
/* 中間層のしきい値補正 */
for( j = 0 ; j < Midunit ; j++ ){
dsikiiim[j] = ( Eta * dim[j] ) + ( Alpha * dsikiiim[j] );
sikiiim[j] += dsikiiim[j];
}
/* 出力層の補正(教師信号なしの部分) */
for( i = 0 ; i < Midunit ; i++ ){
for( j = 12 ; j < Outunit ; j++ ){
/*for( j = Tunit ; j < Outunit ; j++ ){*/
dwmo[j][i] = ( Eta * dmo[j] * midkeep[i] ) + ( Alpha * dwmo[j][i] );
wmo[j][i] += dwmo[j][i];
}
}
/* 出力層のしきい値補正(教師信号なしの部分) */
for( i = 12 ; i < Outunit ; i++ ){
/*for( i = Tunit ; i < Outunit ; i++ ){*/
dsikiimo[i] = ( Eta * dmo[i] ) + ( Alpha * dsikiimo[i] );
sikiimo[i] += dsikiimo[i];
}
}