经典的SOM人工神经网络例子源码
/******************************************************************************===================
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 = 1;
Net->KohonenLayer->dScoreMean = 0;
}
f = fopen("SOM.txt", "w");
}
void WriteNet(NET* Net)
{
INTr,c;
REAL x,y,z;
fprintf(f, "\n\n\n");
for (r=0; r<ROWS; r++) {
for (c=0; c<COLS; c++) {
x = Net->KohonenLayer->Weight;
y = Net->KohonenLayer->Weight;
z = Net->OutputLayer->Weight;
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 */
#define Mc 1 /* - mass of cart */
#define Mp 1 /* - mass of pole */
#define G 9.81 /* - acceleration due to gravity */
#define T 0.1 /* - time step */
#define STEPS 10 /* - simulation steps in one time step */
typedef struct { /* STATE VARIABLES OF A POLE: */
REAL x; /* - position of cart */
REAL xDot; /* - velocity of cart */
REAL w; /* - angle of pole [癩 */
REAL wDot; /* - angular velocity of pole [?s] */
REAL F; /* - force applied to cart */
} POLE; /* during current time step */
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)
{
INTs;
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 = (REAL*) calloc(N, sizeof(REAL));
}
for (i=0; i<M; i++) {
Net->OutputLayer->Weight = (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 = RandomEqualREAL(-30, 30);
}
}
for (i=0; i<Net->OutputLayer->Units; i++) {
for (j=0; j<Net->KohonenLayer->Units; j++) {
Net->OutputLayer->Weight = 0;
}
}
}
void SetInput(NET* Net, REAL* Input)
{
INT i;
for (i=0; i<Net->InputLayer->Units; i++) {
Net->InputLayer->Output = Input;
}
}
void GetOutput(NET* Net, REAL* Output)
{
INT i;
for (i=0; i<Net->OutputLayer->Units; i++) {
Output = Net->OutputLayer->Output;
}
}
/******************************************************************************
P R O P A G A T I N G S I G N A L S
******************************************************************************/
void PropagateToKohonen(NET* Net)
{
INTi,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;
Weight = Net->KohonenLayer->Weight;
Sum += sqr(Out - Weight);
}
Net->KohonenLayer->Output = sqrt(Sum);
}
MinOut = MAX_REAL;
for (i=0; i<Net->KohonenLayer->Units; i++) {
if (Net->KohonenLayer->Output < MinOut)
MinOut = Net->KohonenLayer->Output;
}
}
void PropagateToOutput(NET* Net)
{
INT i;
for (i=0; i<Net->OutputLayer->Units; i++) {
Net->OutputLayer->Output = Net->OutputLayer->Weight;
}
}
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)
{
INTiRow, 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)
{
INTi,j;
REAL Out, Weight, Lambda, StepSize;
for (i=0; i<Net->KohonenLayer->Units; i++) {
for (j=0; j<Net->InputLayer->Units; j++) {
Out = Input;
Weight = Net->KohonenLayer->Weight;
Lambda = Neighborhood(Net, i);
Net->KohonenLayer->Weight += Net->Alpha * Lambda * (Out - Weight);
}
StepSize = Net->KohonenLayer->StepSize;
Net->KohonenLayer->StepSize += Net->Alpha__ * Lambda * -StepSize;
}
}
void TrainOutput(NET* Net, REAL* Output)
{
INTi,j;
REAL Out, Weight, Lambda;
for (i=0; i<Net->OutputLayer->Units; i++) {
for (j=0; j<Net->KohonenLayer->Units; j++) {
Out = Output;
Weight = Net->OutputLayer->Weight;
Lambda = Neighborhood(Net, j);
Net->OutputLayer->Weight += Net->Alpha_ * Lambda * (Out - Weight);
}
}
}
void TrainUnits(NET* Net, REAL* Input, REAL* Output)
{
TrainKohonen(Net, Input);
TrainOutput(Net, Output);
}
void TrainNet(NET* Net)
{
INTn,t;
POLE Pole;
REAL wOld, wNew, ScoreOld, ScoreNew, dScore, dScoreMean, StepSize;
REAL Input;
REAL Output;
REAL Target;
n = 0;
while (n<TRAIN_STEPS) {
t = 0;
InitializePole(&Pole);
fprintf(f, " Time Angle Force\n");
fprintf(f, "%4.1fs %5.1f? %5.1fN\n", 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 = wOld;
Input = wNew;
SetInput(Net, Input);
PropagateNet(Net);
GetOutput(Net, Output);
Pole.F = Output;
StepSize = Net->KohonenLayer->StepSize;
Pole.F += StepSize * RandomNormalREAL(0, 10);
fprintf(f, "%4.1fs %5.1f? %5.1fN\n", 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;
if (dScore > dScoreMean) {
Target = Pole.F;
TrainUnits(Net, Input, Target);
}
Net->KohonenLayer->dScoreMean += Net->Gamma * (dScore - dScoreMean);
}
if (PoleStillBalanced(&Pole))
fprintf(f, "Pole still balanced after %0.1fs ...\n\n", t * T);
else
fprintf(f, "Pole fallen after %0.1fs ...\n\n", (t+1) * T);
}
}
/******************************************************************************
M A I N
******************************************************************************/
void main()
{
NET Net;
InitializeRandoms();
GenerateNetwork(&Net);
RandomWeights(&Net);
InitializeApplication(&Net);
TrainNet(&Net);
WriteNet(&Net);
FinalizeApplication(&Net);
}
顶
:lol :lol :lol :lol :lol :lol :lol :lol :lol :lol还是要先理解SOM的机理后,使用这段程序才会得心应手!
还没有学过SOM,只是学过BP。
页:
[1]