next up previous contents
Next: C.2 改良プログラム(変更部分のみ抜粋) Up: 付録C サーチアクセスプログラム Previous: 付録C サーチアクセスプログラム

C.1 内積値と想起度の関係調査用プログラム

 

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

#define U               100 /* ニューロンへの入力線の総数 */
#define PATTERN           4 /* 記憶するパターン数 */
#define SOUKITIME        15 /* 連続して同じパターンが想起されたときを
                               検索終了とする回数 */
#define SHOKI_N_MAX     100 /* 初期値を変更してサーチを行なう回数の最大値 */

#define B                 1 /* 黒 */
#define W                 0 /* 白 */

#define fout(x) (1/(1+ exp(-(x)))) /* シグモイド関数 */
 
static int levo[U],levn[U]; /* 量子化した値を格納する */
static int kai;             /* サーチ回数 */
static int time;            /* 連続して同じパターンが想起された回数 */
static int hi;              /* 連続して同じパターンが想起されたかどうかの
                               判定 */
static int search;          /* 記憶させるパターンの番号 */
int out_in[PATTERN][U];     /* 学習パターン */
int kai_max;                /* 最大サーチ回数 */

static int keika_ari;              /* 途中経過のデータ出力の有無 */
static int shoki_n;                /* 初期値を変更してサーチを行なう回数 */
unsigned long shoki;               /* 乱数の初期化値 */
int nai_s_s[PATTERN][SHOKI_N_MAX]; /*学習パターンと初期パターンとの内積 */
 
/* シナプス前抑制関数に関する変数 */
static double z;    /* 入力 */
static double rsnp; /* 出力 */
static double rcha; /* カオス状態をとる値 */
static double gs;   /* しきい値 */

/* カオスニューロンに関する変数 */
static double alp;  /* 定数パラメータ */
static double km;   /* 相互結合入力に関する記憶の減衰定数 */
static double kr;   /* 不応性に関する減衰定数 */
static double x[U]; /* 出力パターン */
static double m[U]; /* シナプス結合入力に関する項 */
static double n[U]; /* しきい値に関する項 */
static double gaib; /* しきい値に関する定数パラメータ */

static double eps; /* シグモイド関数の定数パラメータ */

/* 自己相関学習 */
static double sok;     /* 結合荷重パラメータ */
static double w[U][U]; /* シナプス結合荷重 */

double drand48(); /* 乱数関数 */

FILE *fp; /* 学習パターンの入力ファイル */
FILE *fd; /* サーチ結果の出力ファイル */
FILE *fk; /* 途中経過の出力ファイル */

char fname[50]; /* ファイル名 */

main(argc,argv)
     int argc;
     char *argv[];
{
  int i,j;
  
  /* 各パラメータの初期設定 */
  sok = 0.25;
  alp = 10.0;
  eps = 0.015;
  gaib = 2.0;
  rcha = 0.4;
  km = 0.5;
  kr = 0.5;
  gs = 0.25;
  shoki_n = 25;
  shoki = 0;
  kai_max = 3000;

  /* コマンドラインからの入力方法の説明表示 */
  if (argc < 2 || argc > 9){
    printf("search <パターンファイル記号> <最大時間> <乱数初期値>");
    printf(" <初期値数> <経過> <km> <kr> <gs>\n");
    printf("\tファイル名: pat_<パターンファイル記号>.dat\n");
    printf("\最大時間 == 入力なし:%d\n",kai_max);
    printf("\t乱数初期値 == 入力なし:%d\n",shoki);
    printf("\t初期値数 == 入力なし: %d\n",shoki_n);
    printf("\t経過: 有 == 1, 無 == 0; 入力なし: 無\n");
    printf("\t<km> <kr> <gs> == 入力なし: km=%1.2lf kr=%1.2lf gs=%1.2lf\n"
           ,km,kr,gs);
    exit(-1);
  }

  /* コマンドラインからの入力値の設定 */
  if(argc == 9)
    gs = atof(argv[8]);
  if(argc >= 8)
    kr = atof(argv[7]);
  if(argc >= 7)
    km = atof(argv[6]);
  if(argc >= 6)
    keika_ari = atoi(argv[5]);
  if(argc >= 5)
    shoki_n = atoi(argv[4]);
  if(argc >= 4)
    shoki = atoi(argv[3]);
  if(argc >= 3)
    kai_max = atoi(argv[2]);

  /* 学習パターンの入力ファイルの設定 */
  sprintf(fname,"pat_%s.dat",argv[1]);
  if((fp = fopen(fname,"r")) == NULL){
    /* 指定した入力ファイルがない場合の終了ベル */
    printf("ファイルなし\n\007");
    usleep(500000);
    printf("\007");
    exit(-1);
  }

  /* 途中経過出力ファイルの設定 */
  if(keika_ari == 1){
    sprintf(fname,"srh/keika_%s_%lu.dat",argv[1],shoki);
    fk = fopen(fname,"w");
  }

  /* サーチ結果出力ファイルの設定 */
  sprintf(fname,"srh/search_%s_%lu.dat",argv[1],shoki);
  fd = fopen(fname,"w");
  fprintf(fd,"km\t%1.3lf\nkr\t%1.3lf\ng\t%1.3lf\n",km,kr,gs);
  fprintf(fd,"m\t%d\n\n",kai_max);

  /* パターンの取り込み */
  torikomi();

  /* 自己相関学習 */
  soukan();

  /* 各学習パターンについてのサーチ */
  for(search = 0; search < PATTERN; search++){
    
    /* 学習パターン番号出力 */
    fprintf(fd,"\npt%d\n",search);

    /* 初期値パターン設定 */
    srand48(shoki);

    /* 一つのパターンにつき初期値数 shoki_n 回のサーチを行なう */
    for(j = 0; j < shoki_n ; j++){

      /* 初期パターンの作成と内積計算 */
      shoki_p(j);

      /* 最大 kai_max 回のサーチを行なう */
      for(kai = 0; kai < kai_max ; kai++){
        
        /* 量子化 */
        ryoushika();
      
        /* 直前の出力と比較(検索終了判定) */
        hikaku();
        if (hi == 0 && kai != 0)
          time++; /* 変化していない場合 */
        else 
          time=0; /* 変化した場合 */

        /* 量子化値の代入 */
        for(i=0; i<U; i++)
          levn[i] = levo[i];
      
        /* 距離計算 */
        kyori();
        
        /* 途中経過の出力 */
        if(keika_ari == 1)
          keika();
        
        /* 検索終了 */
        if(time == SOUKITIME){
          jikosouki(j);
          break;
        }
        
        /* カオスニューロンの出力計算 */
        for(i = 0; i < U; i++)
          neuro(i);
      
      }
    
      /* 検索失敗による終了 */
      if(kai == kai_max)
        jikosouki(j);
    }
    
    fprintf(fd,"\n");
  }  

  /* 内積値の出力 */  
  for(i=0; i<PATTERN; i++){
    fprintf(fd,"\nnp%d\n",i); /* 学習パターン番号の出力 */
    for(j=0; j<shoki_n; j++){
      fprintf(fd,"%5d",nai_s_s[i][j]);
      if(j%10 == 9)
        fprintf(fd,"\n");
    }
    fprintf(fd,"\n");
  }

  fclose(fd);
  fclose(fp);
  if(keika_ari == 1)
    fclose(fk);

  /* 終了ベル */
  for(i=0; i<5; i++){
    printf("終了!!\n\007");
    usleep(250000);
  }

}

/* 自己相関学習 */
soukan()
{
  int i,j,k;

  for(i = 0; i < PATTERN; i++){
    for(j = 0; j < U; j++){
      for(k = 0; k < U; k++){
        w[j][k] += sok * (2 * out_in[i][j] - 1) * (2 * out_in[i][k] - 1);
      }
    }
  }
}

/* 初期パターンの作成と内積計算 */
shoki_p(j)
     int j;
{
  int i;
  
  nai_s_s[search][j] = 0;
  for(i = 0; i < U; i++){
    /* 初期パターン作成 */
    if(drand48() < 0.5)
      x[i] = W;
    else
      x[i] = B;
    /* 初期パターンとサーチパターンとの内積値 */
    if(out_in[search][i] == x[i])
      nai_s_s[search][j]++;
    else
      nai_s_s[search][j]--;
    /* 初期化 */
    m[i] = n[i] = 0;
  }
}

/* 出力パターンの量子化 */
ryoushika()
{
  int i;

  for(i = 0; i < U; i++){
    if(x[i] < 0.1){
      levo[i] = 0;
    } else if(x[i] < 0.25){
      levo[i] = 1;
    } else if(x[i] < 0.5){
      levo[i] = 2;
    } else if(x[i] < 0.75){
      levo[i] = 3;
    } else if(x[i] < 0.90){
      levo[i] = 4;
    } else {
      levo[i] = 5;
    }
  }
}

/* 量子化したパターンが変化したかどうかの比較 */
hikaku()
{
  int i;
  
  for(i = 0; i < U; i++){
    if(levo[i] != levn[i]){
      hi = 1; /* 変化している */
      return;
    }
  } 
  hi = 0; /* 変化していない */
}

/* カオスニューロンの出力計算 */
neuro(i)
     int i;
{
  int j;
  double kas = 0;

  for(j = 0; j < U; j++)
    kas += (w[i][j] * x[j]);
  m[i] = rsnp * kas + km * m[i];
  n[i] = -alp * x[i] + kr * n[i] + gaib;
  x[i] = fout((m[i] + n[i]) / eps);
}

/* 想起時間または想起失敗(-1,-2)の出力 */
jikosouki(j)
     int j;
{
  int i;

  if(kai != kai_max){
    for(i=0; i<U; i++)
      if(out_in[search][i]*5 != levo[i]){
        fprintf(fd,"%5d",-2); /* 想起失敗(他のパターンを想起した場合)*/
        break;
      }
    fprintf(fd,"%5d",kai-SOUKITIME); /* 想起時間 */
  }
  else
    fprintf(fd,"%5d",-1); /* 想起失敗(どのパターンも想起されない場合) */
  if(j%10 == 9)
    fprintf(fd,"\n");
}

/* 入力ファイルからのデータの取り込みおよびその出力 */
torikomi()
{
  int i,j,naiseki;

  for(i=0; i<PATTERN; i++){
    fprintf(fd,"p%d\n",i); /* 学習パターン番号の出力 */
    /* 学習パターンの入出力 */
    for(j=0; j<U; j++){
      fscanf(fp,"%d",&out_in[i][j]);
      fprintf(fd,"%d ",out_in[i][j]);
      if(j%10 == 9)
        fprintf(fd,"\n");
    }
    fprintf(fd,"\n");
  }
  /* 各パターンごとの内積値の入出力 */
  j = 1;
  for(i=1; i<PATTERN; i++)
    j *= i;
  fprintf(fd,"n");
  for(i=0; i<j; i++){
    if(fscanf(fp,"%d",&naiseki) == EOF){
      /* 指定した入力ファイルに内積値が書き込まれていない場合の終了ベル */
      printf("内積値なし\n\007");
      exit(-1);
    }
    fprintf(fd,"\t%3d ",naiseki);
  }
  /* 初期値変更回数と乱数初期化値 */
  fprintf(fd,"\n\ns\t%lu\nsn\t%3d\n\n",shoki,shoki_n);
}

/* サーチパターンと出力パターンの距離と抑制関数の計算 */
kyori()
{
  int i;
  
  z=0;
  /* 距離計算 */
  for(i=0; i<U; i++)
    z += fabs(x[i] - out_in[search][i]); /* 絶対値関数 */
  z /= U;
  /* 抑制関数の出力計算 */
  if(z < gs)
    rsnp = 1;
  else
    rsnp = rcha;
}

/* 途中経過の各データの出力 */
keika()
{
  int i;
  
  fprintf(fk,"pt=%d t=%d time=%d hi=%d rsnp=%1.3lf z=%1.3lf\n",
          search,kai,time,hi,rsnp,z);
  for(i=0; i<U; i++){
    fprintf(fk,"%d ",levo[i]);
    if(i%10 == 9)
      fprintf(fk,"\n");
  }
  fprintf(fk,"\n");
}



Deguchi Toshinori
1996年09月05日 (木) 11時50分24秒 JST