next up previous contents
Next: 付録C 曲を想起させるプログラム Up: 無題 Previous: 付録A 学習プログラム(ニューラルネットワーク)

付録B 学習プログラム(内部記憶を持つニューラルネットワーク)

/* 学習プログラム(内部記憶を持つニューラルネットワーク) */

/* ヘッダ */

#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];
  }

}



Deguchi Toshinori
Wed Feb 21 11:55:53 JST 2001