📄 somsucess.c
字号:
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
#include "math.h"
#include "engine.h"
#include <string.h>
#define INPUT_NEURON 2
#define OUTPUT_COL 5
#define OUTPUT_ROW 5
#define STUDY_RATE_START 0.2 //学习速率初值,一般选较大数,0.2为典型值
#define STUDY_RATE_LAST 0.005 //学习速率最终值,一般在0.001~0.01之间选取一般
#define STUDY_NUMBER 4000 //学习次数,一般在500~10000之间选取
#define NEIGHBOR_START 8 //临域半径初值,一般应将整个网络所含神经元全部包括其中
double WEIGHT[OUTPUT_ROW*OUTPUT_COL][INPUT_NEURON];//存储权值
double DISTANCE[OUTPUT_ROW*OUTPUT_COL]; //存储距离
double STUDY_RATE; //学习速率
double NEIGHBOR_RADIUS; //临域半径
/******************************************************************************************
产生随机数
******************************************************************************************/
void InitializeRandoms()
{
srand(2559);//设置种子
}
float RandomEqualREAL(float Low, float High)
{
return (((float) rand())* (High-Low) / RAND_MAX + Low);//产生Low到High之间的数
}
/******************************************************************************************
更新学习速率 k代表学习速率已更新次数
******************************************************************************************/
void updata_study_rate(int k)
{
STUDY_RATE=(STUDY_RATE_START-STUDY_RATE)*(1-(float) k/STUDY_NUMBER)+STUDY_RATE_LAST;
}
/******************************************************************************************
更新临域 k代表此次临域半径更新为第k次
由于按照教材中理想的公式临域范围最后无法缩小到1(1后有小数点若干位),
所以在计算临域半径时,做四舍五入处理
******************************************************************************************/
int updata_neighbor(int k)
{
NEIGHBOR_RADIUS=sqrt(2)*(OUTPUT_ROW-1)+(1-sqrt(2)*(OUTPUT_ROW-1))*k/STUDY_NUMBER;
if(NEIGHBOR_RADIUS-floor(NEIGHBOR_RADIUS)>=0.5)
NEIGHBOR_RADIUS=ceil(NEIGHBOR_RADIUS);
else
NEIGHBOR_RADIUS=floor(NEIGHBOR_RADIUS);
return (NEIGHBOR_RADIUS);
}
/******************************************************************************************
初始化权值 根据教材,为了保证SOM有好的收敛性,一般将WEIGHT赋予同一数值
******************************************************************************************/
void init_weight()
{
int counter1,counter2;
for(counter1=0;counter1<INPUT_NEURON;counter1++)
for(counter2=0;counter2<OUTPUT_ROW*OUTPUT_COL;counter2++)
{
WEIGHT[counter2][counter1]=0.01;
}
}
/******************************************************************************************
计算权值与输入之间距离
******************************************************************************************/
void compute_distance(float *p_in)
{
int counter,counter1;
for(counter=0;counter<OUTPUT_ROW*OUTPUT_COL;counter++)
{
DISTANCE[counter]=0;
for(counter1=0;counter1<INPUT_NEURON;counter1++)
{
DISTANCE[counter]=DISTANCE[counter]+(*(p_in+counter1)-WEIGHT[counter][counter1]) * (*(p_in+counter1)-WEIGHT[counter][counter1]);
}
}
}
/************************************************************************************************
计算获胜者
************************************************************************************************/
int compute_winner()
{
int position;
int counter;
double temp;
position=0;
temp=DISTANCE[0];
for(counter=0;counter<OUTPUT_ROW*OUTPUT_COL;counter++)
{
if(temp>DISTANCE[counter])
{
temp=DISTANCE[counter];
position=counter;
}
}
return (position);
}
main()
{
int counter,counter1,counter2,counter3;//一般用计数器
FILE *p_data; //指向数据文件
float input_vector[INPUT_NEURON]; //输入向量
int winner; //获胜者编号
double temp_weight_x[OUTPUT_COL*OUTPUT_ROW];//暂存weight的x坐标
double temp_weight_y[OUTPUT_COL*OUTPUT_ROW];//暂存weight的y坐标
Engine *ep; //调用MATLAT引擎
mxArray *weight_x=NULL,*weight_y=NULL;//所需变量
init_weight(); //初始化网络
STUDY_RATE=STUDY_RATE_START; //
NEIGHBOR_RADIUS=NEIGHBOR_START; //
p_data=fopen("input space.dat","rb"); //从已建立好的文件中获取输入向量
fseek(p_data,0,SEEK_SET); //
for(counter=0;counter<STUDY_NUMBER;counter++)
{
fread(input_vector,1,sizeof(float),p_data);
fread(input_vector+1,1,sizeof(float),p_data);//从输入空间中去一输入向量
compute_distance(input_vector);
winner=compute_winner();
updata_neighbor(counter);
updata_study_rate(counter);
for(counter1=0;counter1<OUTPUT_COL;counter1++)
for (counter2=0;counter2<OUTPUT_ROW;counter2++)
{
if( ( (counter2-winner/OUTPUT_COL) * (counter2-winner/OUTPUT_COL) + (counter1-winner%OUTPUT_COL) * (counter1-winner%OUTPUT_COL) )<NEIGHBOR_RADIUS*NEIGHBOR_RADIUS )
for(counter3=0;counter3<INPUT_NEURON;counter3++)
WEIGHT[OUTPUT_ROW*counter2+counter1][counter3]=WEIGHT[OUTPUT_ROW*counter2+counter1][counter3]+STUDY_RATE*(input_vector[counter3]-WEIGHT[OUTPUT_ROW*counter2+counter1][counter3]);
}
}
fclose(p_data);
/***************************************************************************************
调用matlab引擎作图
******************************************************************************************/
ep = engOpen(NULL); //启动matlab engine
weight_x = mxCreateDoubleMatrix(1, OUTPUT_ROW*OUTPUT_COL, mxREAL);
weight_y = mxCreateDoubleMatrix(1, OUTPUT_ROW*OUTPUT_COL, mxREAL);
for(counter=0;counter<OUTPUT_ROW*OUTPUT_COL;counter++)
for(counter1=0;counter1<INPUT_NEURON;counter1++)
{
if(counter1==0)
temp_weight_x[counter]=WEIGHT[counter][counter1];
else
temp_weight_y[counter]=WEIGHT[counter][counter1];
}
memcpy((double *) mxGetPr(weight_x),temp_weight_x,OUTPUT_ROW*OUTPUT_COL*sizeof(double));
memcpy((double *) mxGetPr(weight_y),temp_weight_y,OUTPUT_ROW*OUTPUT_COL*sizeof(double));
engPutVariable(ep, "weight_x", weight_x);
engPutVariable(ep, "weight_y", weight_y);
engEvalString(ep, "plot(weight_x,weight_y,'+r');");
printf("done!\n");
mxDestroyArray(weight_x);
mxDestroyArray(weight_y);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -