📄 bp.h
字号:
b=(*lpSrc==255)?0:1;
tz[m]+=b;
}
}
//提取第9个特征-总象素值
for(i=0;i<lHeight;i++)
for(j=k*width;j<(k+1)*width;j++)
{ lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
b=(*lpSrc==255)?0:1;
tz[8]+=b;
}
//提取第10、11个特征-水平扫描切割
i=int(lHeight*1/3);
for(j=k*width;j<(k+1)*width;j++)
{ lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
b=(*lpSrc==255)?0:1;
tz[9]+=b;
}
//
i=int(lHeight*2/3);
for(j=k*width;j<(k+1)*width;j++)
{ lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
b=(*lpSrc==255)?0:1;
tz[10]+=b;
}
//提取第12、13个特征-垂直扫描切割
j=int(k*width+width*1/3);
for(i=0;i<lHeight;i++)
{ lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
b=(*lpSrc==255)?0:1;
tz[11]+=b;
}
j=int(k*width+width*2/3);
for(i=0;i<lHeight;i++)
{ lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
b=(*lpSrc==255)?0:1;
tz[12]+=b;
}
//存储特征
for(i=0;i<dim;i++)
tezheng[k][i]=tz[i];
}
::GlobalUnlock ((HGLOBAL)hDIB);
//返回特征向量矩阵的指针
return tezheng;
}
/**********************************
* 函数名称 code()
*
* 参量:
* BYTE* lpDIBBits -指向输入图像的象素其实位置的指针
* int num -图片中样本的个数
* LONG lLineByte -输入图片每行的字节数
* LONG lSwidth -预处理时归一化的宽度
* LONG lSheight -预处理时归一化的长度
*
* 函数功能 :
* 对于输入样本提取特征向量,在这里把归一化样本的
* 每一个象素都作为特征提取出来
**************************************/
double** code (BYTE* lpDIBBits,int num, LONG lLineByte,LONG lSwidth,LONG lSheight)
{
//循环变量
int i,j,k;
BYTE* lpSrc;
// 建立保存特征向量的二维数组
double **data;
// 为这个数组申请二维存储空间
data = alloc_2d_dbl(num,lSwidth*lSheight);
// 将归一化的样本的每个象素作为一个特征点提取出来
//逐个数据扫描
for(k=0;k<num;k++)
{
//对每个数据逐行扫描
for(i=0;i<lSheight;i++)
{
//对每个数据逐列扫描
for(j=k*lSwidth;j<(k+1)*lSwidth;j++)
{
// 指向图像第i行第j列个象素的指针
lpSrc = lpDIBBits + i*lLineByte + j;
//如果这个象素是黑色的
if(*(lpSrc)==0)
//将特征向量的相应位置填1
data[k][i*lSwidth+j-k*lSwidth]=1;
//如果这个象素是其他的
if(*(lpSrc)!=0)
//将特征向量的相应位置填0
data[k][i*lSwidth+j-k*lSwidth]=0;
}
}
}
return(data);
}
/****************************************************
* 函数名称 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 BpTrain(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<num;k++)
{
//将提取的样本的特征向量输送到输入层上
for(i=1;i<=n_in;i++)
input_unites[i] = data_in[k][i-1];
//将预定的理想输出输送到BP网络的理想输出单元
for(i=1;i<=n_out;i++)
target[i]=data_out[k][i-1];
//前向传输激活
//将数据由输入层传到隐层
bpnn_layerforward(input_unites,hidden_unites,
input_weights, n_in,n_hidden);
//将隐层的输出传到输出层
bpnn_layerforward(hidden_unites, output_unites,
hidden_weights,n_hidden,n_out);
//误差计算
//将输出层的输出与理想输出比较计算输出层每个结点上的误差
bpnn_output_error(output_deltas,target,output_unites,n_out);
//根据输出层结点上的误差计算隐层每个节点上的误差
bpnn_hidden_error(hidden_deltas,n_hidden, output_deltas, n_out,hidden_weights, hidden_unites);
//权值调整
//根据输出层每个节点上的误差来调整隐层与输出层之间的权值
bpnn_adjust_weights(output_deltas,n_out, hidden_unites,n_hidden,
hidden_weights, hidden_prev_weights, eta, momentum);
//根据隐层每个节点上的误差来调整隐层与输入层之间的权值
bpnn_adjust_weights(hidden_deltas, n_hidden, input_unites, n_in,
input_weights, input_prev_weights, eta, momentum);
//误差统计
for(i=1;i<=n_out;i++)
ex+=(output_unites[i]-data_out[k][i-1])*(output_unites[i]-data_out[k][i-1]);
}
//计算均方误差
ex=ex/double(num*n_out);
//如果均方误差已经足够的小,跳出循环,训练完毕
if(ex<min_ex)break;
}
//相关保存
//保存输入层与隐层之间的权值
w_weight(input_weights,n_in,n_hidden,"win.dat");
//保存隐层与输出层之间的权值
w_weight(hidden_weights,n_hidden,n_out,"whi.dat");
//保存各层结点的个数
w_num(n_in,n_hidden,n_out,"num");
//显示训练结果
CString str;
if(ex<=min_ex)
{
str.Format ("迭代%d次,\n平均误差%.4f",l,ex);
::MessageBox(NULL,str,"训练结果",NULL);
}
if(ex>min_ex)
{
str.Format("迭代%d次,平均误差%.4f\n我已经尽了最大努力了还是达不到您的要求\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
****************************************/
void 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));
//指向输入层数据的指针
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);
//读取权值
if( r_weight(input_weights,n_in,n_hidden,"win.dat")==false)
return;
if(r_weight(hidden_weights,n_hidden,n_out,"whi.dat")==false)
return;
//逐个样本扫描
for(k=0;k<num;k++)
{
//将提取的样本的特征向量输送到输入层上
for(i=1;i<=n_in;i++)
input_unites[i]=data_in[k][i-1];
//前向输入激活
bpnn_layerforward(input_unites,hidden_unites,
input_weights, n_in,n_hidden);
bpnn_layerforward(hidden_unites, output_unites,
hidden_weights,n_hidden,n_out);
//根据输出结果进行识别
int result=0 ;
//考察每一位的输出
for(i=1;i<=n_out;i++)
{
//如果大于0.5判为1
if(output_unites[i]>0.5)
result+=(int)pow(2,double(4-i));
}
//如果判定的结果小于等于9,认为合理
if(result<=9)
recognize[k]=result;
//如果判定的结果大于9,认为不合理将结果定位为一个特殊值20
if(result>9)
recognize[k]=20;
}
//将识别结果写到文本中
FILE *fp;
fp=fopen("result.txt","w+");
for(i=0;i<num;i++)
{
if(recognize[i]==20)
fprintf(fp,"无法识别,");
else
fprintf(fp,"%d,",recognize[i]);
}
fclose(fp);
//将识别的结果显示出来
CString str,str1;
for(i=0;i<num;i++)
{
if(recognize[i]!=20)
str.Format("%d ",recognize[i]);
if(recognize[i]==20)
str.Format("无法识别 ");
str1+=str;
}
//通知用户训练完成
::MessageBox(NULL,str1,"识别结果",NULL);
//释放存储空间
free(input_unites);
free(hidden_unites);
free(output_unites);
free(input_weights);
free(hidden_weights);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -