www.pudn.com > Photodeal.rar > Bp.h
#include#include #include #include #define BIGRND 32767 double drnd(); double dpn1(); double squash(double x); double *alloc_1d_dbl(int n); double *alloc_1d_dbl(int n); double **alloc_2d_dbl(int m, int n); int ndigicount; //多次提取样本特征总个数 double ** all_data_in; // 多次提取特征矩阵 void bpnn_initialize(int seed); void bpnn_randomize_weights(double **w, int m, int n); void bpnn_zero_weights(double **w, int m, int n); void bpnn_layerforward(double *l1, double *l2, double **conn, int n1, int n2); void bpnn_output_error(double *delta, double *target, double *output, int nj); void bpnn_hidden_error(double* delta_h, int nh, double *delta_o, int no, double **who, double *hidden); void bpnn_adjust_weights(double *delta, int ndelta, double *ly, int nly, double** w, double **oldw, double eta, double momentum); void w_weight(double **w,int n1,int n2,char*name); bool r_weight(double **w,int n1,int n2,char *name); void w_num(int n1,int n2,int n3,char*name); bool r_num(int *n,char *name); double **TZTQ_24(BYTE*image ,int p,int w); //double **code(BYTE*image ,int *p,int w,int h,int dw); void BpTrain1(HDIB hDIB,int n_hidden,double min_ex,double momentum,double eta ,int width,int height); void BpTrain2(HDIB hDIB,int n_hidden,double min_ex,double momentum,double eta ,int width,int height); void BpTrain3(HDIB hDIB,int n_hidden,double min_ex,double momentum,double eta ,int width,int height); CString* CodeRecognize(HDIB hDIB,int width ,int height ,int n_in ,int n_hidden,int n_out); /*** 返回0-1的双精度随机数 ***/ double drnd() { return ((double) rand() / (double) BIGRND); } /*** 返回-1.0到1.0之间的双精度随机数 ***/ double dpn1() { return ((drnd() * 2.0) - 1.0); } double squash(double x) { return (1.0 / (1.0 + exp(-x))); } /*** 申请1维双精度实数数组 ***/ double *alloc_1d_dbl(int n) { double *new1; new1 = (double *) malloc ((unsigned) (n * sizeof (double))); if (new1 == NULL) { printf("ALLOC_1D_DBL: Couldn't allocate array of doubles\n"); return (NULL); } return (new1); } /*** 申请2维双精度实数数组 ***/ double **alloc_2d_dbl(int m, int n) { int i; double **new1; new1 = (double **) malloc ((unsigned) (m * sizeof (double *))); if (new1 == NULL) { // printf("ALLOC_2D_DBL: Couldn't allocate array of dbl ptrs\n"); return (NULL); } for (i = 0; i < m; i++) { new1[i] = alloc_1d_dbl(n); } return (new1); } /*** 设置随机数种子 ***/ void bpnn_initialize(int seed) { //printf("Random number generator seed: %d\n", seed); srand(seed); } /*** 随机初始化权值 ***/ void bpnn_randomize_weights(double **w, int m, int n) { int i, j; for (i = 0; i <= m; i++) { for (j = 0; j <= n; j++) { w[i][j] = dpn1(); } } } /*** 0初始化权值 ***/ void bpnn_zero_weights(double **w, int m, int n) { int i, j; for (i = 0; i <= m; i++) { for (j = 0; j <= n; j++) { w[i][j] = 0.0; } } } /*********前向传输*********/ void bpnn_layerforward(double *l1, double *l2, double **conn, int n1, int n2) { double sum; int j, k; /*** 设置阈值 ***/ l1[0] = 1.0; /*** 对于第二层的每个神经元 ***/ for (j = 1; j <= n2; j++) { /*** 计算输入的加权总和 ***/ sum = 0.0; for (k = 0; k <= n1; k++) { sum += conn[k][j] * l1[k]; } l2[j] = squash(sum); } } /* 输出误差 */ void bpnn_output_error(double *delta, double *target, double *output, int nj) { int j; double o, t, errsum; errsum = 0.0; for (j = 1; j <= nj; j++) { o = output[j]; t = target[j]; delta[j] = o * (1.0 - o) * (t - o); } } /* 隐含层误差 */ void bpnn_hidden_error(double* delta_h, int nh, double *delta_o, int no, double **who, double *hidden) { int j, k; double h, sum, errsum; errsum = 0.0; for (j = 1; j <= nh; j++) { h = hidden[j]; sum = 0.0; for (k = 1; k <= no; k++) { sum += delta_o[k] * who[j][k]; } delta_h[j] = h * (1.0 - h) * sum; } } /* 调整权值 */ void bpnn_adjust_weights(double *delta, int ndelta, double *ly, int nly, double** w, double **oldw, double eta, double momentum) { double new_dw; int k, j; ly[0] = 1.0; for (j = 1; j <= ndelta; j++) { for (k = 0; k <= nly; k++) { new_dw = ((eta * delta[j] * ly[k]) + (momentum * oldw[k][j])); w[k][j] += new_dw; oldw[k][j] = new_dw; } } } /*******保存权值**********/ void w_weight(double **w,int n1,int n2,char*name) { int i,j; double *buffer; FILE *fp; fp=fopen(name,"wb+"); buffer=(double*)malloc((n1+1)*(n2+1)*sizeof(double)); for(i=0;i<=n1;i++) { for(j=0;j<=n2;j++) buffer[i*(n2+1)+j]=w[i][j]; } fwrite((char*)buffer,sizeof(double),(n1+1)*(n2+1),fp); fclose(fp); free(buffer); } /************读取权值*************/ bool r_weight(double **w,int n1,int n2,char *name) { int i,j; double *buffer; FILE *fp; if((fp=fopen(name,"rb"))==NULL) { ::MessageBox(NULL,"无法读取权值信息",NULL,MB_ICONSTOP); return (false); } buffer=(double*)malloc((n1+1)*(n2+1)*sizeof(double)); fread((char*)buffer,sizeof(double),(n1+1)*(n2+1),fp); for(i=0;i<=n1;i++) { for(j=0;j<=n2;j++) w[i][j]=buffer[i*(n2+1)+j]; } fclose(fp); free(buffer); return(true); } /*****保存各层结点的数目******/ void w_num(int n1,int n2,int n3,char*name) { FILE *fp; fp=fopen(name,"wb+"); int *buffer; buffer=(int*)malloc(3*sizeof(int)); buffer[0]=n1; buffer[1]=n2; buffer[2]=n3; fwrite((char*)buffer,sizeof(int),3,fp); fclose(fp); free(buffer); } /********读取各层结点数目*********/ bool r_num(int *n,char *name) { int *buffer; FILE *fp; buffer=(int *)malloc(3*sizeof(int)); if((fp=fopen(name,"rb"))==NULL) { ::MessageBox(NULL,"结点参数",NULL,MB_ICONSTOP); return (false); } fread((char*)buffer,sizeof(int),3,fp); n[0]=buffer[0]; n[1]=buffer[1]; n[2]=buffer[2]; fclose(fp); free(buffer); return(true); } /******************************************************** * 函数名称 VerticalCode() * * 参量: * BYTE* lpDIBBits -指向输入图像的象素其实位置的指针 * int num -图片中样本的个数 * LONG lLineByte -输入图片每行的字节数 * LONG lSwidth -预处理时归一化的宽度 * LONG lSheight -预处理时归一化的长度 * * 返回值: * double** -特征向量矩阵 * * 函数功能 : * 对于输入样本提取特征向量,在这里把归一化样本的 * 水平和竖直方向的统计特征作为特征提取出来 ***************************************************************/ double** VerticalCode(BYTE* lpDIBBits,int num, LONG lLineByte,LONG lSwidth,LONG lSheight) { //循环变量 int i,j,k; BYTE* lpSrc; //统计变量 int sum; // 建立保存特征向量的二维数组 double **data; // 为这个数组申请二维存储空间 data = alloc_2d_dbl(num,lSwidth+lSheight); // 将归一化的样本的每个象素作为一个特征点提取出来 //逐个数据扫描 for(k=0;k c) c=f[i]; for(i=0;i<24;i++) f[i]=f[i]/c; //新增六个特征 for(i=0;i<6;i++) f[24+i]=0; int x=0; int y=0; for(m=1;m<=3;m++) { for(i=0;i<15;i++) { lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+8*m+lLineBytes*i; x=*lpSrc; lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+8*m+lLineBytes*(i+1); y=*lpSrc; if((x==0) && (y==255) ) f[23+m]+=1; x=y=0; } for(i=0;i<29;i++) { lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+4*m*lLineBytes+i; x=*lpSrc; lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+4*m*lLineBytes+(i+1); y=*lpSrc; if((x==0) && (y==255) ) f[26+m]+=1; x=y=0; } lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+8*m+lLineBytes*15; x=*lpSrc; lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+4*m*lLineBytes+29; y=*lpSrc; if(!x)f[23+m]+=1; if(!y) f[26+m]+=1; x=y=0; } c=f[24]; for(i=25;i<30;i++) if(f[i]>c) c=f[i]; for(i=24;i<30;i++) f[i]=f[i]/c; //再新增九个特征 for(m=0;m<9;m++) f[30+m]=tz[m]; c=f[30]; for(i=30;i<39;i++) if(f[i]>c) c=f[i]; for(i=30;i<39;i++) f[i]=f[i]/c; //存储特征 for(i=0;i<39;i++) tezheng[k][i]=f[i]; } // ::GlobalUnlock ((HGLOBAL)hDIB); //返回特征向量矩阵的指针 return tezheng; delete []f; delete []p; delete []tz; } /**************************************************** * 函数名称 BpTrain() * * 参数: * double **data_in -指向输入的特征向量数组的指针 * double **data_out -指向理想输出数组的指针 int n_in -输入层结点的个数 * int n_hidden -BP网络隐层结点的数目 * double min_ex -训练时允许的最大均方误差 * double momentum -BP网络的相关系数 * double eta -BP网络的训练步长 * int num -输入样本的个数 * * 函数功能: * 根据输入的特征向量和期望的理想输出对BP网络尽行训练 * 训练结束后将权值保存并将训练的结果显示出来 ********************************************************/ void BpTrain1(double ** data_in, double** data_out,int n_in,int n_hidden,double min_ex,double momentum,double eta ,int num) { //循环变量 int i,k,l; //输出层结点数目 int n_out=4; //指向输入层数据的指针 double* input_unites; //指向隐层数据的指针 double* hidden_unites; //指向输出层数据的指针 double* output_unites; //指向隐层误差数据的指针 double* hidden_deltas; //指向输出层误差数剧的指针 double* output_deltas; //指向理想目标输出的指针 double* target; //指向输入层于隐层之间权值的指针 double** input_weights; //指向隐层与输出层之间的权值的指针 double** hidden_weights; //指向上一此输入层于隐层之间权值的指针 double** input_prev_weights ; //指向上一此隐层与输出层之间的权值的指针 double** hidden_prev_weights; //每次循环后的均方误差误差值 double ex; //为各个数据结构申请内存空间 input_unites= alloc_1d_dbl(n_in + 1); hidden_unites=alloc_1d_dbl(n_hidden + 1); output_unites=alloc_1d_dbl(n_out + 1); hidden_deltas = alloc_1d_dbl(n_hidden + 1); output_deltas = alloc_1d_dbl(n_out + 1); target = alloc_1d_dbl(n_out + 1); input_weights=alloc_2d_dbl(n_in + 1, n_hidden + 1); input_prev_weights = alloc_2d_dbl(n_in + 1, n_hidden + 1); hidden_prev_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); //为产生随机序列撒种 time_t t; bpnn_initialize((unsigned)time(&t)); //对各种权值进行初始化初始化 bpnn_randomize_weights( input_weights,n_in,n_hidden); bpnn_randomize_weights( hidden_weights,n_hidden,n_out); bpnn_zero_weights(input_prev_weights, n_in,n_hidden ); bpnn_zero_weights(hidden_prev_weights,n_hidden,n_out ); //开始进行BP网络训练 //这里设定最大的迭代次数为15000次 for(l=0;l<15000;l++) { //对均方误差置零 ex=0; //对样本进行逐个的扫描 for(k=0;k min_ex) { str.Format("迭代%d次,平均误差%.4f\n请调整参数重新训练吧!",l,ex); ::MessageBox(NULL,str,"训练结果",NULL); } //释放内存空间 free(input_unites); free(hidden_unites); free(output_unites); free(hidden_deltas); free(output_deltas); free(target); free(input_weights); free(hidden_weights); free(input_prev_weights); free(hidden_prev_weights); } ///////////////////////////// void BpTrain2(double ** data_in, double** data_out,int n_in,int n_hidden,double min_ex,double momentum,double eta ,int num) { //循环变量 int i,k,l; //输出层结点数目 int n_out=4; //指向输入层数据的指针 double* input_unites; //指向隐层数据的指针 double* hidden_unites; //指向输出层数据的指针 double* output_unites; //指向隐层误差数据的指针 double* hidden_deltas; //指向输出层误差数剧的指针 double* output_deltas; //指向理想目标输出的指针 double* target; //指向输入层于隐层之间权值的指针 double** input_weights; //指向隐层与输出层之间的权值的指针 double** hidden_weights; //指向上一此输入层于隐层之间权值的指针 double** input_prev_weights ; //指向上一此隐层与输出层之间的权值的指针 double** hidden_prev_weights; //每次循环后的均方误差误差值 double ex; //为各个数据结构申请内存空间 input_unites= alloc_1d_dbl(n_in + 1); hidden_unites=alloc_1d_dbl(n_hidden + 1); output_unites=alloc_1d_dbl(n_out + 1); hidden_deltas = alloc_1d_dbl(n_hidden + 1); output_deltas = alloc_1d_dbl(n_out + 1); target = alloc_1d_dbl(n_out + 1); input_weights=alloc_2d_dbl(n_in + 1, n_hidden + 1); input_prev_weights = alloc_2d_dbl(n_in + 1, n_hidden + 1); hidden_prev_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); //为产生随机序列撒种 time_t t; bpnn_initialize((unsigned)time(&t)); //对各种权值进行初始化初始化 bpnn_randomize_weights( input_weights,n_in,n_hidden); bpnn_randomize_weights( hidden_weights,n_hidden,n_out); bpnn_zero_weights(input_prev_weights, n_in,n_hidden ); bpnn_zero_weights(hidden_prev_weights,n_hidden,n_out ); //开始进行BP网络训练 //这里设定最大的迭代次数为15000次 for(l=0;l<15000;l++) { //对均方误差置零 ex=0; //对样本进行逐个的扫描 for(k=0;k min_ex) { str.Format("迭代%d次,平均误差%.4f\n请调整参数重新训练吧!",l,ex); ::MessageBox(NULL,str,"训练结果",NULL); } //释放内存空间 free(input_unites); free(hidden_unites); free(output_unites); free(hidden_deltas); free(output_deltas); free(target); free(input_weights); free(hidden_weights); free(input_prev_weights); free(hidden_prev_weights); } //////////////////////////////////////// void BpTrain3(double ** data_in, double** data_out,int n_in,int n_hidden,double min_ex,double momentum,double eta ,int num) { //循环变量 int i,k,l; //输出层结点数目 int n_out=4; //指向输入层数据的指针 double* input_unites; //指向隐层数据的指针 double* hidden_unites; //指向输出层数据的指针 double* output_unites; //指向隐层误差数据的指针 double* hidden_deltas; //指向输出层误差数剧的指针 double* output_deltas; //指向理想目标输出的指针 double* target; //指向输入层于隐层之间权值的指针 double** input_weights; //指向隐层与输出层之间的权值的指针 double** hidden_weights; //指向上一此输入层于隐层之间权值的指针 double** input_prev_weights ; //指向上一此隐层与输出层之间的权值的指针 double** hidden_prev_weights; //每次循环后的均方误差误差值 double ex; //为各个数据结构申请内存空间 input_unites= alloc_1d_dbl(n_in + 1); hidden_unites=alloc_1d_dbl(n_hidden + 1); output_unites=alloc_1d_dbl(n_out + 1); hidden_deltas = alloc_1d_dbl(n_hidden + 1); output_deltas = alloc_1d_dbl(n_out + 1); target = alloc_1d_dbl(n_out + 1); input_weights=alloc_2d_dbl(n_in + 1, n_hidden + 1); input_prev_weights = alloc_2d_dbl(n_in + 1, n_hidden + 1); hidden_prev_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); //为产生随机序列撒种 time_t t; bpnn_initialize((unsigned)time(&t)); //对各种权值进行初始化初始化 bpnn_randomize_weights( input_weights,n_in,n_hidden); bpnn_randomize_weights( hidden_weights,n_hidden,n_out); bpnn_zero_weights(input_prev_weights, n_in,n_hidden ); bpnn_zero_weights(hidden_prev_weights,n_hidden,n_out ); //开始进行BP网络训练 //这里设定最大的迭代次数为15000次 for(l=0;l<15000;l++) { //对均方误差置零 ex=0; //对样本进行逐个的扫描 for(k=0;k min_ex) { str.Format("迭代%d次,平均误差%.4f\n请调整参数重新训练吧!",l,ex); ::MessageBox(NULL,str,"训练结果",NULL); } //释放内存空间 free(input_unites); free(hidden_unites); free(output_unites); free(hidden_deltas); free(output_deltas); free(target); free(input_weights); free(hidden_weights); free(input_prev_weights); free(hidden_prev_weights); } /******************************************* * 函数名称 * CodeRecognize() * 参量 * double **data_in -指向待识别样本特征向量的指针 * int num -待识别的样本的个数 * int n_in -Bp网络输入层结点的个数 * int n_hidden -Bp网络隐层结点的个数 * int n_out -Bp网络输出层结点的个数 * 函数功能: * 读入输入样本的特征相量并根据训练所得的权值 * 进行识别,将识别的结果写入result.txt ****************************************/ CString* CodeRecognize(double **data_in, int num ,int n_in,int n_hidden,int n_out) { //循环变量 int i,k; // 指向识别结果的指针 int *recognize; //为存放识别的结果申请存储空间 recognize=(int*)malloc(num*sizeof(int)); CString Charac[4]={"京","晋","粤",""}; CString Num[3]={"0","2","4"}; CString Letter[3]={"K","E","A"}; //指向输入层数据的指针 double* input_unites; //指向隐层数据的指针 double* hidden_unites; //指向输出层数据的指针 double* output_unites; //指向输入层于隐层之间权值的指针 double** input_weights; //指向隐层与输出层之间的权值的指针 double** hidden_weights; //为各个数据结构申请内存空间 input_unites= alloc_1d_dbl(n_in + 1); hidden_unites=alloc_1d_dbl(n_hidden + 1); output_unites=alloc_1d_dbl(n_out + 1); input_weights=alloc_2d_dbl(n_in + 1, n_hidden + 1); hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); //逐个样本扫描 for(k=0;k 0.55) result+=(int)pow(2,double(4-i)); } else if(k==1) { if(output_unites[i]>0.36) result+=(int)pow(2,double(4-i)); } else { if(output_unites[i]>0.4) result+=(int)pow(2,double(4-i)); } } //如果判定的结果小于等于9,认为合理 if(result<=9) recognize[k]=result; //如果判定的结果大于9,认为不合理将结果定位为一个特殊值20 if(result>9) recognize[k]=20; } //将识别的结果显示出来 CString str; CString* str1=new CString; for(i=0;i