som神经网络c程序

来源:互联网 发布:语言同步翻译软件 编辑:程序博客网 时间:2024/05/17 07:59
 Network:      Self-Organizing Map                      ===================         Application:  Control                      Pole Balancing Problem         Author:       Karsten Kutza        Date:         6.6.96         Reference:    T. Kohonen                          Self-Organized Formation                      of Topologically Correct Feature Maps                      Biological Cybernetics, 43, pp. 59-69, 1982  ******************************************************************************/    /******************************************************************************                            D E C L A R A T I O N S ******************************************************************************/  #include <stdlib.h>#include <stdio.h>#include <math.h>  typedef int           BOOL;typedef int           INT;typedef double        REAL; #define FALSE         0#define TRUE          1#define NOT           !#define AND           &&#define OR            || #define MIN_REAL      -HUGE_VAL#define MAX_REAL      +HUGE_VAL#define MIN(x,y)      ((x)<(y) ? (x) : (y))#define MAX(x,y)      ((x)>(y) ? (x) : (y)) #define PI            (2*asin(1))#define sqr(x)        ((x)*(x))  typedef struct {                     /* A LAYER OF A NET:                     */        INT           Units;         /* - number of units in this layer       */        REAL*         Output;        /* - output of ith unit                  */        REAL**        Weight;        /* - connection weights to ith unit      */        REAL*         StepSize;      /* - size of search steps of ith unit    */        REAL*         dScoreMean;    /* - mean score delta of ith unit        */} LAYER; typedef struct {                     /* A NET:                                */        LAYER*        InputLayer;    /* - input layer                         */        LAYER*        KohonenLayer;  /* - Kohonen layer                       */        LAYER*        OutputLayer;   /* - output layer                        */        INT           Winner;        /* - last winner in Kohonen layer        */        REAL          Alpha;         /* - learning rate for Kohonen layer     */        REAL          Alpha_;        /* - learning rate for output layer      */        REAL          Alpha__;       /* - learning rate for step sizes        */        REAL          Gamma;         /* - smoothing factor for score deltas   */        REAL          Sigma;         /* - parameter for width of neighborhood */} NET;  /******************************************************************************        R A N D O M S   D R A W N   F R O M   D I S T R I B U T I O N S ******************************************************************************/  void InitializeRandoms(){  srand(4715);}        REAL RandomEqualREAL(REAL Low, REAL High){  return ((REAL) rand() / RAND_MAX) * (High-Low) + Low;}        REAL RandomNormalREAL(REAL Mu, REAL Sigma){  REAL x,fx;   do {    x = RandomEqualREAL(Mu-3*Sigma, Mu+3*Sigma);    fx = (1 / (sqrt(2*PI)*Sigma)) * exp(-sqr(x-Mu) / (2*sqr(Sigma)));  } while (fx < RandomEqualREAL(0, 1));  return x;}        /******************************************************************************               A P P L I C A T I O N - S P E C I F I C   C O D E ******************************************************************************/  #define ROWS          25#define COLS          25 #define N             2#define C             (ROWS * COLS)#define M             1 #define TRAIN_STEPS   10000#define BALANCED      100 FILE*                 f;  void InitializeApplication(NET* Net){  INT i;      for (i=0; i<Net->KohonenLayer->Units; i++) {    Net->KohonenLayer->StepSize[i] = 1;    Net->KohonenLayer->dScoreMean[i] = 0;  }  f = fopen("SOM.txt", "w");}  void WriteNet(NET* Net){  INT  r,c;  REAL x,y,z;   fprintf(f, "nnn");  for (r=0; r<ROWS; r++) {    for (c=0; c<COLS; c++) {      x = Net->KohonenLayer->Weight[r*ROWS+c][0];      y = Net->KohonenLayer->Weight[r*ROWS+c][1];      z = Net->OutputLayer->Weight[0][r*ROWS+c];      fprintf(f, "([%5.1f? %5.1f癩, %5.1fN)    ", x, y, z);    }    fprintf(f, "n");  }}  void FinalizeApplication(NET* Net){  fclose(f);}  /******************************************************************************                     S I M U L A T I N G   T H E   P O L E ******************************************************************************/                                      /* SIMULATION PARAMETERS FOR THE POLE:   */#define L             1              /* - length of pole [m]                  */#define Mc            1              /* - mass of cart [kg]                   */#define Mp            1              /* - mass of pole [kg]                   */#define G             9.81           /* - acceleration due to gravity [m/s瞉  */#define T             0.1            /* - time step [s]                       */#define STEPS         10             /* - simulation steps in one time step   */  typedef struct {                     /* STATE VARIABLES OF A POLE:            */        REAL          x;             /* - position of cart [m]                */        REAL          xDot;          /* - velocity of cart [m/s]              */        REAL          w;             /* - angle of pole [癩                   */        REAL          wDot;          /* - angular velocity of pole [?s]      */        REAL          F;             /* - force applied to cart               */} POLE;                              /*   during current time step [N]        */  void InitializePole(POLE* Pole){  do {    Pole->x    = 0;    Pole->xDot = 0;    Pole->w    = RandomEqualREAL(-30, 30);    Pole->wDot = 0;    Pole->F    = 0;  } while (Pole->w == 0);}  void SimulatePole(POLE* Pole){  INT  s;  REAL x, xDot, xDotDot;             REAL w, wDot, wDotDot;                     REAL F;                       x    = Pole->x;  xDot = Pole->xDot;  w    = (Pole->w    / 180) * PI;  wDot = (Pole->wDot / 180) * PI;  F    = Pole->F;  for (s=0; s<STEPS; s++) {     wDotDot = (G*sin(w) + cos(w) * ((-F - Mp*L*sqr(wDot)*sin(w)) / (Mc+Mp))) /               (L * ((REAL) 4/3 - (Mp*sqr(cos(w))) / (Mc+Mp)));     xDotDot = (F + Mp*L * (sqr(wDot)*sin(w) - wDotDot*cos(w))) / (Mc+Mp);     x    += (T / STEPS) * xDot;    xDot += (T / STEPS) * xDotDot;    w    += (T / STEPS) * wDot;    wDot += (T / STEPS) * wDotDot;  }  Pole->x    = x;  Pole->xDot = xDot;  Pole->w    = (w    / PI) * 180;  Pole->wDot = (wDot / PI) * 180;}  BOOL PoleStillBalanced(POLE* Pole){  return (Pole->w >= -60) AND (Pole->w <= 60);}  REAL ScoreOfPole(POLE* Pole){  return -sqr(Pole->w);}  /******************************************************************************                          I N I T I A L I Z A T I O N ******************************************************************************/  void GenerateNetwork(NET* Net){  INT i;   Net->InputLayer   = (LAYER*) malloc(sizeof(LAYER));  Net->KohonenLayer = (LAYER*) malloc(sizeof(LAYER));  Net->OutputLayer  = (LAYER*) malloc(sizeof(LAYER));   Net->InputLayer->Units        = N;  Net->InputLayer->Output       = (REAL*)  calloc(N, sizeof(REAL));         Net->KohonenLayer->Units      = C;  Net->KohonenLayer->Output     = (REAL*)  calloc(C, sizeof(REAL));  Net->KohonenLayer->Weight     = (REAL**) calloc(C, sizeof(REAL*));  Net->KohonenLayer->StepSize   = (REAL*)  calloc(C, sizeof(REAL));  Net->KohonenLayer->dScoreMean = (REAL*)  calloc(C, sizeof(REAL));         Net->OutputLayer->Units       = M;  Net->OutputLayer->Output      = (REAL*)  calloc(M, sizeof(REAL));  Net->OutputLayer->Weight      = (REAL**) calloc(M, sizeof(REAL*));         for (i=0; i<C; i++) {    Net->KohonenLayer->Weight[i] = (REAL*) calloc(N, sizeof(REAL));  }  for (i=0; i<M; i++) {    Net->OutputLayer->Weight[i] = (REAL*) calloc(C, sizeof(REAL));  }}  void RandomWeights(NET* Net){  INT i,j;      for (i=0; i<Net->KohonenLayer->Units; i++) {    for (j=0; j<Net->InputLayer->Units; j++) {      Net->KohonenLayer->Weight[i][j] = RandomEqualREAL(-30, 30);    }  }  for (i=0; i<Net->OutputLayer->Units; i++) {    for (j=0; j<Net->KohonenLayer->Units; j++) {      Net->OutputLayer->Weight[i][j] = 0;    }  }}  void SetInput(NET* Net, REAL* Input){  INT i;      for (i=0; i<Net->InputLayer->Units; i++) {    Net->InputLayer->Output[i] = Input[i];  }}  void GetOutput(NET* Net, REAL* Output){  INT i;      for (i=0; i<Net->OutputLayer->Units; i++) {    Output[i] = Net->OutputLayer->Output[i];  }}  /******************************************************************************                     P R O P A G A T I N G   S I G N A L S ******************************************************************************/  void PropagateToKohonen(NET* Net){  INT  i,j;  REAL Out, Weight, Sum, MinOut;   for (i=0; i<Net->KohonenLayer->Units; i++) {    Sum = 0;    for (j=0; j<Net->InputLayer->Units; j++) {      Out = Net->InputLayer->Output[j];      Weight = Net->KohonenLayer->Weight[i][j];      Sum += sqr(Out - Weight);    }    Net->KohonenLayer->Output[i] = sqrt(Sum);  }  MinOut = MAX_REAL;  for (i=0; i<Net->KohonenLayer->Units; i++) {    if (Net->KohonenLayer->Output[i] < MinOut)      MinOut = Net->KohonenLayer->Output[Net->Winner = i];  }}  void PropagateToOutput(NET* Net){  INT i;   for (i=0; i<Net->OutputLayer->Units; i++) {    Net->OutputLayer->Output[i] = Net->OutputLayer->Weight[i][Net->Winner];  }}  void PropagateNet(NET* Net){  PropagateToKohonen(Net);  PropagateToOutput(Net);}  /******************************************************************************                        T R A I N I N G   T H E   N E T ******************************************************************************/  REAL Neighborhood(NET* Net, INT i){  INT  iRow, iCol, jRow, jCol;  REAL Distance;   iRow = i / COLS; jRow = Net->Winner / COLS;  iCol = i % COLS; jCol = Net->Winner % COLS;   Distance = sqrt(sqr(iRow-jRow) + sqr(iCol-jCol));   return exp(-sqr(Distance) / (2*sqr(Net->Sigma)));}  void TrainKohonen(NET* Net, REAL* Input){  INT  i,j;  REAL Out, Weight, Lambda, StepSize;   for (i=0; i<Net->KohonenLayer->Units; i++) {    for (j=0; j<Net->InputLayer->Units; j++) {      Out = Input[j];      Weight = Net->KohonenLayer->Weight[i][j];      Lambda = Neighborhood(Net, i);      Net->KohonenLayer->Weight[i][j] += Net->Alpha * Lambda * (Out - Weight);    }    StepSize = Net->KohonenLayer->StepSize[i];    Net->KohonenLayer->StepSize[i] += Net->Alpha__ * Lambda * -StepSize;  }}  void TrainOutput(NET* Net, REAL* Output){  INT  i,j;  REAL Out, Weight, Lambda;   for (i=0; i<Net->OutputLayer->Units; i++) {    for (j=0; j<Net->KohonenLayer->Units; j++) {      Out = Output[i];      Weight = Net->OutputLayer->Weight[i][j];      Lambda = Neighborhood(Net, j);      Net->OutputLayer->Weight[i][j] += Net->Alpha_ * Lambda * (Out - Weight);    }  }}  void TrainUnits(NET* Net, REAL* Input, REAL* Output){  TrainKohonen(Net, Input);  TrainOutput(Net, Output);}  void TrainNet(NET* Net){  INT  n,t;  POLE Pole;  REAL wOld, wNew, ScoreOld, ScoreNew, dScore, dScoreMean, StepSize;  REAL Input[N];  REAL Output[M];  REAL Target[M];   n = 0;  while (n<TRAIN_STEPS) {    t = 0;    InitializePole(&Pole);    fprintf(f, " Time     Angle     Forcen");    fprintf(f, "%4.1fs    %5.1f?   %5.1fNn", t * T, Pole.w, Pole.F);    wOld = Pole.w;    ScoreOld = ScoreOfPole(&Pole);    SimulatePole(&Pole);    wNew = Pole.w;    ScoreNew = ScoreOfPole(&Pole);    while (PoleStillBalanced(&Pole) AND (t<BALANCED)) {      n++;      t++;      Net->Alpha   = 0.5 * pow(0.01, (REAL) n / TRAIN_STEPS);      Net->Alpha_  = 0.5 * pow(0.01, (REAL) n / TRAIN_STEPS);      Net->Alpha__ = 0.005;      Net->Gamma   = 0.05;      Net->Sigma   = 6.0 * pow(0.2, (REAL) n / TRAIN_STEPS);      Input[0] = wOld;      Input[1] = wNew;      SetInput(Net, Input);      PropagateNet(Net);      GetOutput(Net, Output);      Pole.F = Output[0];      StepSize = Net->KohonenLayer->StepSize[Net->Winner];      Pole.F += StepSize * RandomNormalREAL(0, 10);      fprintf(f, "%4.1fs    %5.1f?   %5.1fNn", t * T, Pole.w, Pole.F);      wOld = Pole.w;      ScoreOld = ScoreOfPole(&Pole);      SimulatePole(&Pole);      wNew = Pole.w;      ScoreNew = ScoreOfPole(&Pole);      dScore = ScoreNew - ScoreOld;      dScoreMean = Net->KohonenLayer->dScoreMean[Net->Winner];      if (dScore > dScoreMean) {        Target[0] = Pole.F;        TrainUnits(Net, Input, Target);      }      Net->KohonenLayer->dScoreMean[Net->Winner] += Net->Gamma * (dScore - dScoreMean);    }    if (PoleStillBalanced(&Pole))      fprintf(f, "Pole still balanced after %0.1fs ...nn", t * T);    else      fprintf(f, "Pole fallen after %0.1fs ...nn", (t+1) * T);  }}  /******************************************************************************                                    M A I N ******************************************************************************/  void main(){  NET Net;   InitializeRandoms();  GenerateNetwork(&Net);  RandomWeights(&Net);  InitializeApplication(&Net);  TrainNet(&Net);  WriteNet(&Net);  FinalizeApplication(&Net);}
原创粉丝点击