📄 childview.cpp
字号:
//初始的权值和偏置存放于init
void CChildView::OnPrewb()
{ mark_wb=1;//表示已经产生了随机初始权值和偏置
W1=MatrixRand(s1,r); B1=MatrixRand(s1,1);
W2=MatrixRand(s2,s1); B2=MatrixRand(s2,1);
int i,j;
for(i=0;i<s1;i++)
{ B1_init[i]=B1[i];
for(j=0;j<r;j++)
W1_init[i*r+j]=W1[i*r+j];
}
for(i=0;i<s2;i++)
{ B2_init[i]=B2[i];
for(j=0;j<s1;j++)
W2_init[i*s1+j]=W2[i*s1+j];
}
free(W1);
free(W2);
free(B1);
free(B2);
CClientDC dc(this);
CString str;
CFont font;
font.CreatePointFont (300,_TEXT("新宋体"));
dc.SelectObject (&font);
dc.Rectangle (rect);
dc.DrawText (_T("正在随机产生初始权值和偏置.....OK!"),-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
}
//显示标准的0到9样本数据(是未加噪声的标准样本数据)
void CChildView::OnDispSamples()
{
CClientDC dc(this);
dc.Rectangle (rect);
CPen pen(PS_SOLID,3,RGB(105,90,170));
dc.SelectObject(&pen);
CPoint pcenter(20,20);
int i;
CFont font1;
font1.CreatePointFont (250,_T("新宋体"));
dc.SelectObject (&font1);
dc.TextOut (30,80,"以下依次为数字0到9的标准不含噪声的样本数据:");
for(i=0;i<10;i++)
{ pcenter.x =30+i*90;
pcenter.y =150;
DrawNumber(P_samples[i],pcenter);
}
}
//对已经训练完毕的BP网络应用于:加噪声的未知数字的识别
void CChildView::OnBpnRun()
{ int targetindex,i=5,j,k,sbl=0,*np;
double* temp1[40]; double* temp2[40]; double* temp3[40];
double* temp4[40]; double* temp5[40]; double* temp6[40];
CClientDC dc(this);
dc.Rectangle (rect);
CString str;
CPoint pcenter(40,40);
CFont font;
font.CreatePointFont (120,_TEXT("新宋体"));
dc.SelectObject (&font);
dc.Rectangle (rect);
dc.TextOut(129,20,"--------------应用BP网络进行数字识别(识别对象为随机加噪的40组未知数据):-------------------");
for(i=0;i<40;i++)
for(j=0;j<N_P;j++)
P_withnoise[i][j]=P_samples[i%10][j];
for(i=0;i<10;i++)
for(k=0;k<=4;k++)
{ np=Rand2(N_P,k+2);
for(j=0;j<k+2;j++)
P_withnoise[i+k*10][np[j]]=(P_withnoise[i+k*10][np[j]]==1)?0:1;
}
for(i=0;i<40;i++)//测试40组数据
{ P=P_withnoise[i];
temp2[i]=N1=MatrixAdd((temp1[i]=MatrixMul(W1_final,P,s1,r,1)),B1_final,s1,1); //N1: s1×1
temp3[i]=A1=f1(N1,s1);
temp5[i]=N2=MatrixAdd((temp4[i]=MatrixMul(W2_final,A1,s2,s1,1)),B2_final,s2,1);//N2: s2×1
temp6[i]=A2=f2(N2,s2);
targetindex=TargetTest(A2);
pcenter.x =40+(i%(Ns/Nsext))*98;
pcenter.y =80+95*int(i/(Ns/Nsext));
DrawNumber(P,pcenter);
dc.TextOut(pcenter.x-15,pcenter.y+50,"识别结果:");
str.Format("%d ",targetindex);
dc.TextOut (pcenter.x+60,pcenter.y+50,str);
if(i%10==targetindex) sbl++;
//TRACE("It is number %d ! %s!",targetindex,(i==targetindex)?"Right":"Wrong");
//if(i==targetindex) {sbl++;TRACE("\n");}
//else TRACE(" 应该是 %d \n",i);
}
dc.TextOut (45,pcenter.y+160,"当前BP网络对未知数字(含3~15%的随机噪声)的识别率达到:");
str.Format ("%3.2f",100*(double)sbl/40);
dc.TextOut (490,pcenter.y+160,str);
dc.TextOut (537,pcenter.y+160,"%");
for(i=0;i<40;i++)
{ free(temp1[i]);free(temp2[i]);free(temp3[i]);free(temp4[i]);free(temp5[i]);free(temp6[i]);}
//TRACE("网络应用测试:识别率为: 百分之%2.2f\n ",Nsext*100*(double)sbl/(double)Ns);
}
//BP网络的校验:使用已知样本(包括不带噪、带噪)进行分类看是否正确
void CChildView::OnBPNVerify()
{ int targetindex,i,sbl=0,k;
double* temp1[Ns]; double* temp2[Ns]; double* temp3[Ns];
double* temp4[Ns]; double* temp5[Ns]; double* temp6[Ns];
CClientDC dc(this);
dc.Rectangle (rect);
CString str;
CPoint pcenter(40,40);
CFont font;
font.CreatePointFont (120,_TEXT("新宋体"));
dc.SelectObject (&font);
dc.Rectangle (rect);
dc.TextOut(30,20,"------------校验结果-----------------");
dc.TextOut(40,50,"第一行不含有噪声的数字,后五行分别加入了3~15%的随机噪声:");
for(i=0;i<Ns;i++)
{ k=i-10*int(i/10);
P=P_samples[i];
temp2[i]=N1=MatrixAdd((temp1[i]=MatrixMul(W1_final,P,s1,r,1)),B1_final,s1,1); //N1: s1×1
temp3[i]=A1=f1(N1,s1);
temp5[i]=N2=MatrixAdd((temp4[i]=MatrixMul(W2_final,A1,s2,s1,1)),B2_final,s2,1);//N2: s2×1
temp6[i]=A2=f2(N2,s2);
targetindex=TargetTest(A2);
TRACE("It is number %d ! %s!",targetindex,(k==targetindex)?"Right":"Wrong");
if(k==targetindex) {sbl++;TRACE("\n");}
else TRACE(" 应该是 %d \n",k);
pcenter.x =40+(i%10)*98;
pcenter.y =80+90*int(i/10);
DrawNumber(P,pcenter);
dc.TextOut(pcenter.x-15,pcenter.y+50,"识别结果:");
str.Format("%d ",k);
dc.TextOut (pcenter.x+60,pcenter.y+50,str);
}
TRACE("识别率为: 百分之%2.2f\n ",100*(double)sbl/(double)Ns);
dc.TextOut (60,pcenter.y+100,"当前网络对已知数据的识别率已达到:");
str.Format ("%3.2f",100*(double)sbl/(double)Ns);
dc.TextOut (360,pcenter.y+100,str);
dc.TextOut (400,pcenter.y+100," %");
for(i=0;i<Ns;i++)
{ free(temp1[i]);free(temp2[i]);free(temp3[i]);free(temp4[i]);free(temp5[i]);free(temp6[i]);}
}
//引入动量因子的训练过程
void CChildView::OnBPTRAINOptimal1()
{ dongliangmark=1;
errorfilemark++;
if(mark_wb==0) OnPrewb();//随机产生初始权值和偏置存放于init
int i,j,current,loops,trainok;
int mark[Ns];//训练成功标志
//numE=(double*)malloc(N_Err*sizeof(double));//存放最多N_Err点的均方误差
/////////////////////////////////////////////////////////////////////
current=loops=trainok=0;
for(i=0;i<N_Err;i++) numE[i]=0;
for(i=0;i<Ns;i++) mark[i]=0;
initwb();//初始化权值和偏置(将init赋值给final)
/////////////////////////////////////////////////////////////////////
CClientDC dc(this);
dc.Rectangle (rect);
CString str;
CFont font;
font.CreatePointFont (350,_TEXT("新宋体"));
dc.SelectObject (&font);
dc.DrawText (_T("正在训练网络...请稍等...."),-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
double* temp[23];
double* dw1=(double*)malloc(s1*r*sizeof(double));
double* dw2=(double*)malloc(s2*s1*sizeof(double));
double* db1=(double*)malloc(s1*1*sizeof(double));
double* db2=(double*)malloc(s2*1*sizeof(double));
for(i=0;i<s1;i++)
{ db1[i]=0.1;
for(j=0;j<r;j++)
dw1[i*r+j]=0.1;
}
for(i=0;i<s2;i++)
{ db2[i]=0.1;
for(j=0;j<s1;j++)
dw2[i*s1+j]=0.1;
}
CTime startTime = CTime::GetCurrentTime();
struct _timeb timebuffer;
int mills1,mills2;
_ftime(&timebuffer);
mills1=timebuffer.millitm;
step2:
loadwb();//将final赋值给新分配内存空间的W1,W2,B1,B2
current=loops%(Nsext*10);
P=P_samples[current];//current为0到9,以循环指向数字0~9的标准输入样本
T=T_output[current];
/******************************计算正向传播信息********************************/
N1=MatrixAdd((temp[0]=MatrixMul(W1,P,s1,r,1)),B1,s1,1); //N1: s1×1
A1=f1(N1,s1);//f1是自定义的函数,具备对矢量进行运算的功能
N2=MatrixAdd((temp[1]=MatrixMul(W2,A1,s2,s1,1)),B2,s2,1);//N2: s2×1
A2=f2(N2,s2);
/******************************反向传播误差的计算******************************/
E=MatrixSub(T,A2,s2,1);//T、A2、E为s2×1
numE[loops]=0; //注意,此时的误差不是一个数了!是个向量
for(i=0;i<s2;i++)
numE[loops]=numE[loops]+E[i]*E[i];
//-------计算S2、S1(注意顺序)
S2=MatrixMulNum((temp[3]=MatrixMul((temp[2]=F2(N2,s2)),E,s2,s2,1)),s2,1,-2.0);
S1=MatrixMul(temp[6]=(MatrixMul((temp[4]=F1(N1,s1)),(temp[5]=MatrixInver(W2,s2,s1)),s1,s1,s2)),S2,s1,s2,1);
//调整输出层神经元的权值和偏置
dW2=MatrixMul(S2,(temp[7]=MatrixInver(A1,s1,1)),s2,1,s1);//dW2: s2×s1
dW2=MatrixMulNum((temp[8]=dW2),s2,s1,(rmobp-1)*learnspeed);
temp[15]=MatrixMulNum(dw2,s2,s1,rmobp);
temp[16]=MatrixAdd(temp[15],dW2,s2,s1);
W2=MatrixAdd((temp[9]=W2),temp[16],s2,s1);
dB2=MatrixMulNum(S2,s2,1,(rmobp-1)*learnspeed);
temp[17]=MatrixMulNum(db2,s2,1,rmobp);
temp[18]=MatrixAdd(temp[17],dB2,s2,1);
B2=MatrixAdd((temp[10]=B2),temp[18],s2,1);
//调整隐层神经元权值和偏置
dW1=MatrixMul(S1,(temp[11]=MatrixInver(P,r,1)),s1,1,r);//dW1: s1×r
dW1=MatrixMulNum((temp[12]=dW1),s1,r,(rmobp-1)*learnspeed);
temp[19]=MatrixMulNum(dw1,s1,r,rmobp);
temp[20]=MatrixAdd(temp[19],dW1,s1,r);
W1=MatrixAdd((temp[13]=W1),temp[20],s1,r);
dB1=MatrixMulNum(S1,s1,1,(rmobp-1)*learnspeed);
temp[21]=MatrixMulNum(db1,s1,1,rmobp);
temp[22]=MatrixAdd(temp[21],dB1,s1,1);
B1=MatrixAdd((temp[14]=B1),temp[22],s1,1);
dc.DrawText (_T("正在训练网络...请稍等...."),-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
TRACE("%d loops, error is: %f \n",loops,numE[loops]);
savewb();//将临时空间W、B中的数据存于final
for(i=0;i<s1;i++)
{ db1[i]=dB1[i];
for(j=0;j<r;j++)
dw1[i*r+j]=dW1[i*r+j];
}
for(i=0;i<s2;i++)
{ db2[i]=dB2[i];
for(j=0;j<s1;j++)
dw2[i*s1+j]=dW2[i*s1+j];
}
//释放动态分配的内存区
free(W1);free(B1);free(N1);free(A1);free(dB1);free(S1);free(dW1);
free(W2);free(B2);free(N2);free(A2);free(dB2);free(S2);free(dW2);
for(i=0;i<23;i++) free(temp[i]);
if(loops>N_Err) goto step3;
if(numE[loops]>error_accept) //说明误差不能满足要求。继续调节
{ mark[current]=0; //验证有效位重新计数
++loops;
goto step2;
}
else mark[current]=1;//执行到此步说明在该次迭代中,误差符合要求,记功一次
trainok=0;
for(i=0;i<Ns;i++)
trainok+=mark[i];
if(trainok>=Ns)
{ //训练可以结束了;
goto step3;
}
else { ++loops; goto step2;}
step3:
learncount=loops-1;//计算总的学习次数并存放于全局变量
dc.Rectangle (rect);
dc.TextOut (300,150,_T("训练完成!"));
str.Format ("%d",learncount);
dc.TextOut (80,400,"总共训练了:");
dc.TextOut (360,400,str);
dc.TextOut (490,400,"次");
str.Format ("%f",numE[loops-1]);
dc.TextOut (80,500,"最终误差:");
dc.TextOut (340,500,str);
stre=str;
//计算训练所用时间
CTime endTime = CTime::GetCurrentTime();
CTimeSpan elapsedTime = endTime - startTime;
_ftime(&timebuffer);
mills2=timebuffer.millitm;
long int timeused;
timeused=elapsedTime.GetTotalSeconds();
if (mills1<=mills2)
timeused=timeused*1000+(mills2-mills1);//将计算训练所用时间换算成毫秒
else
timeused=(timeused-1)*1000+(mills1-mills2);
strt.Format ("加入动量因子后,训练网络所用时间为:%d 毫秒 (初始权值不变的情况下)",timeused);
::AfxMessageBox(strt);
}
void CChildView::OnSaveerror()
{
//写输出文件:训练过程中的误差
int i;
//errorfilemark++;
CString filename;
CString str;
filename.Format ("训练误差记录%d.txt",errorfilemark);
CFile file (filename, CFile::modeReadWrite|CFile::modeCreate);
CString str_file;
char buffer[2]={13,10};
if(dongliangmark==0) str_file.Format ("训练过程误差记录(没有加入动量因子):");
else str_file.Format ("训练过程误差记录(使用了动量因子):");
file.Write (str_file, str_file.GetLength());
file.Write (buffer,sizeof(buffer));
for(i=0;i<learncount;i++)
{
str_file.Format ("loos%5d,误差为: %4.4f",i+1,numE[i]);
//str_file.GetLength();
file.Write (str_file, str_file.GetLength());
file.Write (buffer,sizeof(buffer));
}
str_file.Format ("训练完毕!");
file.Write (str_file,str_file.GetLength());
file.Write (buffer,sizeof(buffer));
file.Write (strt,strt.GetLength ());
file.Write (buffer,sizeof(buffer));
str_file.Format ("最终误差: ");
file.Write (str_file,str_file.GetLength ());
file.Write (stre,stre.GetLength ());
file.Close ();
str.Format ("训练过程误差信息输出到: 训练误差记录%d.txt 中",errorfilemark);
::AfxMessageBox(str);
}
void CChildView::OnSaveweight()
{
int i,j;
//errorfilemark++;
CString filename;
CString str;
filename.Format ("网络最终权值%d.txt",errorfilemark);
CFile file (filename, CFile::modeReadWrite|CFile::modeCreate);
CString str_file;
char buffer[2]={13,10};
str_file.Format ("网络训练最终结果-隐层和输出层的权值与偏置:");
file.Write (str_file, str_file.GetLength());
file.Write (buffer,sizeof(buffer));
str_file.Format ("*************************隐层的:*****************************");
file.Write (str_file, str_file.GetLength());
file.Write (buffer,sizeof(buffer));
for(i=0;i<s1;i++)
for(j=0;j<r;j++)
{ str_file.Format ("W1(%2d,%2d): %3.4f",i,j,W1_final[i*r+j]);
file.Write (str_file, str_file.GetLength());
file.Write (buffer,sizeof(buffer));
}
for(i=0;i<s1;i++)
{ str_file.Format ("B1(%d): %3.4f",i,B1_final[i]);
file.Write (str_file, str_file.GetLength());
file.Write (buffer,sizeof(buffer));
}
file.Write (buffer,sizeof(buffer)); file.Write (buffer,sizeof(buffer));
str_file.Format ("*************************输出层的:*****************************");
file.Write (str_file, str_file.GetLength());
file.Write (buffer,sizeof(buffer));
for(i=0;i<s2;i++)
for(j=0;j<s1;j++)
{ str_file.Format ("W2(%2d,%2d): %3.4f",i,j,W2_final[i*s1+j]);
file.Write (str_file, str_file.GetLength());
file.Write (buffer,sizeof(buffer));
}
for(i=0;i<s2;i++)
{ str_file.Format ("B2(%d): %3.4f",i,B2_final[i]);
file.Write (str_file, str_file.GetLength());
file.Write (buffer,sizeof(buffer));
}
file.Write (buffer,sizeof(buffer));
str_file.Format ("欲求此程序源代码,请与作者联系:bugzhao@sohu.com ");
file.Write (str_file, str_file.GetLength());
file.Write (buffer,sizeof(buffer));
str.Format ("训练后的网络最终权值、偏置输出到: 网络最终权值%d.txt 中 ",errorfilemark);
::AfxMessageBox(str);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -