📄 nn.cpp
字号:
// NN.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "NN.h"
//#define pi 3.14159265;
//---------------------------------------------------------------------------
// 隐节点的激励函数
double Hide_Activate_Function(float x)
{
double y;
y = exp(0.0 - x * x / 2); // 采用 高斯函数
return y;
}
//---------------------------------------------------------------------------
// 隐节点的激励函数的微分
double Hide_Function_Diff(float x)
{
double y;
y=(0.0-x)*exp(0.0-x*x/2);
return y;
}
//---------------------------------------------------------------------------
// 输出层的激励函数
double Out_Activate_Function(float x)
{
double y;
y = 1.0 / (1.0 + exp(-x));
return y;
}
//---------------------------------------------------------------------------
// 输出层的激励函数的微分
double Out_Function_Diff(float x)
{
double y;
double temp;
temp = exp(-x);
y = temp / ( (1 + temp) * (1 + temp) );
return y;
}
//---------------------------------------------------------------------------
void Initial()
{
Samplenum = 300;
Dimension = 290;
InputNum = 288;
HideNum = 100;
OutputNum = 10;
right = 0;
//right1 = 0;
//right2 = 0;
//right3 = 0;
// 最大迭代次数
MaxIteration = 500;
yita1 = 0.3;
yita2 = 0.5;
//ratio = 0.995;
alpha = 0.5; //动量因子
MaxError = 0.001;
Error_Average=1.0;
Error = new float[MaxIteration]; //总误差
//权值矩阵
//隐含层(包含阈值)
w2 = new float *[HideNum];
w2Change = new float *[HideNum];
for( int i=0; i<HideNum; i++ )
{
w2[i] = new float [InputNum + 1];
w2Change[i] = new float [InputNum + 1];
}
//输出层(包含阈值)
w3 = new float *[OutputNum];
w3Change = new float *[OutputNum];
for(i=0; i<OutputNum; i++ )
{
w3[i] = new float [HideNum + 1];
w3Change[i] = new float [HideNum + 1];
}
//各层节点的总输入和总输出
Out_Input = new float[InputNum + 1]; //总输出
Net_Hide = new float[HideNum]; //总输入
Out_Hide = new float[HideNum + 1]; //总输出
Net_Output = new float[OutputNum]; //总输入
Out_Output = new float[OutputNum]; //总输出
Order = new int[Samplenum];
for(i=0; i<Samplenum; i++ )
{
Order[i] = i;
}
Data = new float*[Samplenum];
for(i=0; i<Samplenum; i++ )
{
Data[i] = new float[Dimension + OutputNum];
}
Out_delta = new float[OutputNum];
for (i=0; i<OutputNum; i++ )
Out_delta[i]=0;
Hide_delta = new float[HideNum];
for (i=0; i<HideNum; i++ )
Hide_delta[i]=0;
}
//---------------------------------------------------------------------------
// 权系数赋初值
void Initial_Weight()
{
//隐含层
srand( (unsigned)time( NULL ) );
for( int i=0; i<HideNum; i++ )
{
for(int j=0; j<InputNum + 1; j++ )
{
w2[i][j] = float( 300.0 - rand()%600 ) / (1000.0-0.5);
w2Change[i][j] = 0;
}
}
//输出层
for( i=0; i<OutputNum; i++ )
{
for(int j=0; j<HideNum + 1; j++ )
{
w3[i][j] = float( 300.0 - rand()%600 ) / (1000.0-0.5) ;
w3Change[i][j] = 0;
}
}
}
//---------------------------------------------------------------------------
// 读入数据
void LoadData()
{
FILE *stream;
char namebuf[30];
short SampleHeight,SampleWidth;
unsigned char Printpic[100][100];
//初始化Data
for( int i=0; i<Samplenum; i++ )
{
for(int j=0; j<Dimension + OutputNum; j++)
{
Data[i][j] = 0;
}
}
for(i=0;i<10;i++)
{
for(int j=0;j<30;j++)
{
sprintf((char *)namebuf,".\\trainning\\%d-%d.raw",i,j+1);
if( (stream = fopen((const char *)namebuf,"rb")) == NULL )
{
printf("Can not open the file %d_%d.raw",i,j+1);
}
fread(&SampleHeight,sizeof(short),1,stream);
fread(&SampleWidth,sizeof(short),1,stream);
for(int k=0; k<SampleHeight; k++)
{
fread(Printpic[k],sizeof(unsigned char),SampleWidth,stream);
}
fclose(stream);
for( k=0; k<SampleHeight; k++)
{
for(int l=0; l<SampleWidth; l++)
if(Printpic[k][l]>0)
Printpic[k][l]=1;
}
//图像规一化为24×12
int UpRightZhifang[100],HorizenZhifang[100];
int LetterLow,LetterHigh,LetterLeft,LetterRight;
int VerticalScale,HorizenScale;
int x,y,offsetx,offsety;
int tempx,tempy,temp;
int Height,Width;
char Letter[24][12];
for(k=0;k<100;k++)
{
UpRightZhifang[k]=0;
HorizenZhifang[k]=0;
}
//确定上下左右边界
for(k=0; k<SampleHeight; k++)
{
for(int l=0; l<SampleWidth; l++)
{
UpRightZhifang[k]+=Printpic[k][l];
}
}
for(int l=0; l<SampleWidth; l++)
{
for(k=0; k<SampleHeight; k++)
{
HorizenZhifang[l]+=Printpic[k][l];
}
}
for(k=0; k<SampleHeight; k++)
{
if( UpRightZhifang[k+1]>=1 && UpRightZhifang[k]>=1 )
{
LetterHigh=k;
break;
}
}
for(k=SampleHeight; k>=0; k--)
{
if( UpRightZhifang[k]>=1 && UpRightZhifang[k-1]>=1 )
{
LetterLow=k;
break;
}
}
for(k=0; k<SampleWidth; k++)
{
if( HorizenZhifang[k+1]>=1 && HorizenZhifang[k]>=1 )
{
LetterLeft=k;
break;
}
}
for(k=SampleWidth; k>=0; k--)
{
if( HorizenZhifang[k]>=1 && HorizenZhifang[k-1]>=1 )
{
LetterRight=k;
break;
}
}
Height=LetterLow-LetterHigh+1;
Width=LetterRight-LetterLeft+1;
//按比例归一化为24*12图象
VerticalScale=Height*100/24;
HorizenScale=Width*100/12;
for(int i1=0; i1<24; i1++)
{
temp=((i1+1)*VerticalScale+50)/100;
offsetx=(i1*VerticalScale+50)/100;
tempx=temp-offsetx;
if(tempx<1)
tempx=1;
for(int j1=0; j1<12; j1++)
{
temp=((j1+1)*HorizenScale+50)/100;
offsety=(j1*HorizenScale+50)/100;
tempy=temp-offsety;
if(tempy<1)
tempy=1;
Letter[i1][j1]=0;
for(k=0; k<tempx; k++)
{
for(l=0; l<tempy; l++)
{
//???有问题
x=offsetx+k+LetterHigh;
if(x>=100)
x=99;
y=offsety+l+LetterLeft;
if(y>=100)
y=99;
//???可能有问题,只要认为原图象的对应区域有一个1,ij点的值就是1
Letter[i1][j1]|=Printpic[x][y];
}
}
}
}
//
for(k=0;k<24;k++)
{
for(l=0;l<12;l++)
Data[i*30+j][k*12+l]=Letter[k][l];
}
// 阈值对应的输入
Data[i*30+j][Dimension-2]=-1.0;
// 将理想输出写到矩阵中
Data[i*30+j][Dimension+i]=1;
printf("%d-%d has been loaded\n",i,j+1);
}
}
}
//---------------------------------------------------------------------------
void Training()
{
// 开始训练
int count = 0;
//for (int k=0; k<MaxIteration; k++ )
// Error[k]=0;
Error[count]=0;
// randomize();
int n = 0;
while ( n<300 )
{
//阈值所对应的输入(即是前一层的输出)
Out_Input[InputNum] = -1.0; //总输出
Out_Hide[HideNum] = -1.0; //总输出
//计算实际输出
//(1)输入层
for( int i=0; i<InputNum; i++ )
{
Out_Input[i] = Data[Order[n]][i];
}
//(2)输入层到隐含层
for( i=0; i<HideNum; i++ )
{
Net_Hide[i] = 0.0;
for( int j=0; j<InputNum + 1; j++ )
{
Net_Hide[i] = Net_Hide[i] + w2[i][j] * Out_Input[j];
}
Out_Hide[i] = exp(-Net_Hide[i]*Net_Hide[i]*0.5); //改Hide_Activate_Function为Out_Activate_Function
}
//(3)隐含层到输出层
for( i=0; i<OutputNum; i++ )
{
Net_Output[i] = 0.0;
for( int j=0; j<HideNum + 1; j++ )
{
Net_Output[i] = Net_Output[i] + w3[i][j] * Out_Hide[j];
}
Out_Output[i] = 1.414/( 1.0+exp(-0.05*Net_Output[i]) );//1.414/( 1.0+exp(-0.3*Net_Output[i]) );
}
//根据误差调整权值矩阵
float delta;
//(1)输出层误差
for( i=0; i<OutputNum; i++ )
{
Out_delta[i]=1.414*0.05*Out_Output[i]*(1-Out_Output[i])*(Data[Order[n]][i + Dimension] - Out_Output[i]);//1.414*0.3*Out_Output[i]*(1-Out_Output[i])*(Data[Order[n]][i + Dimension] - Out_Output[i]);
}
//(2)隐层误差
for( int j=0; j<HideNum; j++ )
{
delta=0.0;
for ( int k=0; k<OutputNum; k++ )
delta=delta+Out_delta[k]*w3[k][j];
Hide_delta[j]=-Net_Hide[j]*Out_Hide[j]*delta;
}
//(3)调整输出层节点权值
for( i=0; i<OutputNum; i++ )
{
for( int j=0; j<HideNum; j++ )
{
delta=Out_delta[i] * Out_Hide[j];
w3[i][j] = w3[i][j] + yita1 * delta + alpha*w3Change[i][j];
w3Change[i][j]=delta;
}
}
//(4)调整隐含层节点权值
for( i=0; i<HideNum; i++ )
{
for( int j=0; j<InputNum; j++ )
{
delta = Hide_delta[i] * Out_Input[j];
w2[i][j] = w2[i][j] + yita2 * delta + alpha*w2Change[i][j];
w2Change[i][j]=delta;
}
}
//(5)调整阈值
for( i=0; i<OutputNum; i++ )
{
w3[i][HideNum]-=yita1*Out_delta[i];
Out_delta[i]=0;
}
for( i=1; i<HideNum; i++ )
{
w2[i][InputNum]-=yita2*Hide_delta[i];
Hide_delta[i]=0;
}
//(6)计算误差
for( i=0; i<10; i++ )
{
Error[count] = Error[count]
+ 0.5*(Out_Output[i] - Data[Order[n]][Dimension+i]) * (Out_Output[i] - Data[Order[n]][Dimension+i]);
}
n = n + 1;
if ( n==300 )
{
Error[count]=Error[count] / 300;
if ( Error[count]<=MaxError || count>=MaxIteration-1 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -