⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nn.cpp

📁 神经网络用于牌照识别
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -