📄 dlgbp.cpp
字号:
// DlgBP.cpp : implementation file
//
#include "stdafx.h"
#include "ANN.h"
#include "DlgBP.h"
#include "DlgBPRem.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
int tx1[4][4]={ {1,1,1,1},{1,0,0,1},{1,1,1,1},{1,0,0,1} }; //3个学习模式
int ty1[3]={1,0,0};
/*
int tx2[4][4]={ {1,1,1,1},{1,0,0,1},{1,1,1,1},{1,0,0,1} }; //3个学习模式
int ty2[3]={1,0,0};
int tx3[4][4]={ {1,1,1,1},{1,0,0,1},{1,1,1,1},{1,0,0,1} }; //3个学习模式
int ty3[3]={1,0,0};
*/
int tx2[4][4]={ {0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0} };
int ty2[3]={0,1,0};
int tx3[4][4]={ {1,1,1,1},{1,0,0,1},{1,0,0,1},{1,1,1,1} };
int ty3[3]={0,0,1};
double W[16][8]; //输入层到中间层的连接权
double V[8][3]; //中间层到输出层的连接权
double t1[8]; //中间层的阈值
double t2[3]; //输出层的阈值
/////////////////////////////////////////////////////////////////////////////
// CDlgBP dialog
CDlgBP::CDlgBP(CWnd* pParent /*=NULL*/)
: CDialog(CDlgBP::IDD, pParent)
{
//{{AFX_DATA_INIT(CDlgBP)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CDlgBP::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDlgBP)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDlgBP, CDialog)
//{{AFX_MSG_MAP(CDlgBP)
ON_BN_CLICKED(IDC_BUTTON_Goal, OnBUTTONGoal)
ON_BN_CLICKED(IDC_BUTTON_Study, OnBUTTONStudy)
ON_BN_CLICKED(IDC_BUTTON_quan, OnBUTTONquan)
ON_BN_CLICKED(IDC_BUTTON_remember, OnBUTTONremember)
ON_BN_CLICKED(IDC_BUTTON_about, OnBUTTONabout)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDlgBP message handlers
BOOL CDlgBP::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
CButton *pBtn;
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_quan);
pBtn->EnableWindow(FALSE);
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_remember);
pBtn->EnableWindow(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CDlgBP::OnBUTTONGoal()
{
// TODO: Add your control notification handler code here
CString sGoal="";
sGoal+="1、本BP网的拓扑结构\n";
sGoal+="\n";
sGoal+="网络层 神经元数目\n";
sGoal+="------------------------------\n";
sGoal+="输入层 16\n";
sGoal+="中间层 8\n";
sGoal+="输出层 3\n";
sGoal+="\n\n";
sGoal+="2、本BP网的3个学习模式\n";
sGoal+="------------------------------\n";
sGoal+="输入 输出\n";
sGoal+="1 1 1 1 1 0 0\n";
sGoal+="1 0 0 1\n";
sGoal+="1 1 1 1\n";
sGoal+="1 0 0 1\n";
sGoal+="------------------------------\n";
sGoal+="输入 输出\n";
sGoal+="0 1 0 0 0 1 0\n";
sGoal+="0 1 0 0\n";
sGoal+="0 1 0 0\n";
sGoal+="0 1 0 0\n";
sGoal+="------------------------------\n";
sGoal+="输入 输出\n";
sGoal+="1 1 1 1 0 0 1\n";
sGoal+="1 0 0 1\n";
sGoal+="1 0 0 1\n";
sGoal+="1 1 1 1\n";
sGoal+="------------------------------\n\n";
sGoal+="3、其它\n";
sGoal+="------------------------------\n";
sGoal+="最大允许误差emax=0.01\n";
sGoal+="最大学习次数=30000\n";
sGoal+="输出层学习率α=0.1\n";
sGoal+="中间层学习率β=0.1\n";
MessageBox(sGoal,"BP",MB_ICONINFORMATION);
}
void CDlgBP::OnBUTTONStudy()
{
this->SetDlgItemText(IDC_EDIT_Count,"请稍后,正在学习......");
CButton *pBtn;
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_Study);
pBtn->EnableWindow(FALSE);
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_quan);
pBtn->EnableWindow(FALSE);
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_remember);
pBtn->EnableWindow(FALSE);
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_Goal);
pBtn->EnableWindow(FALSE);
CListBox *pLst;
pLst=(CListBox*)GetDlgItem(IDC_LIST_CtErr);
int c=pLst->GetCount();
for(int iL=0; iL<c; iL++)
pLst->DeleteString(0);
/*********************************************************
//初始化连接权、阈值;
//选取一个模式对;
//计算中间层的激活值;
//计算中间层的输出值;
//计算输出层的激活值;
//计算输出层的输出值;
//计算网络输出与模式之间的总误差;
//计算输出层的校正误差;
//计算中间层的校正误差;
//调整到输出层的连接权和输出层的阈值;
//调整到中间层的连接权和中间层的阈值;
//如果还有模式对尚未学习,则选取一个模式对学习;
//如果所有模式对学完{
// 总误差<最大允许误差,则学习成功;
// 学习回数>最大允许学习回数,则学习失败;
// 否则进行下一回学习;
//}
*******************************************************/
int x0[4][4];
int y0[3];
double bj[8]; //中间层的输出
double ct[3]; //输出层的输出
double dt[3]; //输出层的校正误差
double ej[8]; //中间层的校正误差
double y[16]; //临时数组
double a1; //输出层的学习率
double b1; //中间层的学习率
double er; //网络输出与模式之间的总误差
double emax; //最大允许误差
int r1;
double xy/*,d1,d2*/;
int cnt,i,j,k,t,l,n,p,q,cp;
//int sbaa;
n=16; p=8; q=3;
a1=0.1; b1=0.1; emax=0.01; cnt=0;
cp=1; er=0;
CString sMsg;
CString sWeight="",s;
//初始化连接权、阈值;
srand( (signed)time(0) );
for(i=0; i<n; i++){
for(j=0; j<p; j++){
r1=rand();
W[i][j]=r1/(0x7FFF+0.0)*2-1;
}
}
for(j=0; j<p; j++){
for(t=0; t<q; t++){
r1=rand();
V[j][t]=r1/(0x7FFF+0.0)*2-1;
}
}
for(j=0; j<p; j++){
r1=rand();
t1[j]=r1/(0x7FFF+0.0)*2-1;
}
for(t=0; t<q; t++){
r1=rand();
t2[t]=r1/(0x7FFF+0.0)*2-1;
}
//选取一个模式对;
L20:
if(cp==1){
for(i=0; i<4; i++){
for(j=0; j<4; j++){
x0[i][j]=tx1[i][j];
}
}
for(t=0; t<q; t++){
y0[t]=ty1[t];
}
}
else if(cp==2){
for(i=0; i<4; i++){
for(j=0; j<4; j++){
x0[i][j]=tx2[i][j];
}
}
for(t=0; t<q; t++){
y0[t]=ty2[t];
}
}
else if(cp==3){
for(i=0; i<4; i++){
for(j=0; j<4; j++){
x0[i][j]=tx3[i][j];
}
}
for(t=0; t<q; t++){
y0[t]=ty3[t];
}
}
else
MessageBox("error","BP",MB_ICONINFORMATION);
//计算中间层的激活值;
for(j=0; j<p; j++){
y[j]=0;
}
for(k=0; k<p; k++){
for(i=0; i<4; i++){
for(j=0; j<4; j++){
l=4*i+j;
xy=W[l][k]*x0[i][j];
y[k]=y[k]+xy;
}
}
}
//计算中间层的输出值;
for(j=0; j<p; j++){
y[j]=y[j]-t1[j];
bj[j]=1/( 1+exp(-y[j]) );
/*
if (bj[j]>0.99)
bj[j]=0.99;
else if (bj[j]<0.01)
bj[j]=0.01;
*/
}
//计算输出层的激活值;
for(t=0; t<q; t++){
y[t]=0;
}
for(t=0; t<q; t++){
for(j=0; j<p; j++ ){
xy=V[j][t]*bj[j];
y[t]=y[t]+xy;
}
}
//计算输出层的输出值;
for(t=0; t<q; t++){
y[t]=y[t]-t2[t];
ct[t]=1/( 1+exp(-y[t]) );
/*
if (ct[t]>0.99)
ct[t]=0.99;
else if (ct[t]<0.01)
ct[t]=0.01;
*/
}
//计算网络输出与模式之间的总误差;
for(t=0; t<q; t++){
er=er+(y0[t]-ct[t])*(y0[t]-ct[t]);
}
if( (cnt%100)==0 || ((er<emax) && (cp==q)) ){
sMsg.Format("回数=%d-%d 误差=%f",cnt,cp,er);
pLst->AddString(sMsg);
sMsg="样本输出: ";
for(t=0; t<q; t++){
s.Format("%-8d ",y0[t]);
sMsg+=s;
}
pLst->AddString(sMsg);
sMsg="实际输出: ";
for(t=0; t<q; t++){
s.Format("%f ",ct[t]);
sMsg+=s;
}
pLst->AddString(sMsg);
pLst->AddString("");
if(cp==q){
pLst->AddString("--------------------------------------------");
pLst->AddString("");
}
}
//计算输出层的校正误差;
for(t=0; t<q; t++){
dt[t]=(y0[t]-ct[t])*ct[t]*(1-ct[t]);
}
//计算中间层的校正误差;
for(j=0; j<p; j++){
xy=0;
for(t=0; t<q; t++){
xy+=(dt[t]*V[j][t]);
}
ej[j]=xy*bj[j]*(1-bj[j]); //ej[j]=xy+bj[j]*(1-bj[j]);
}
//调整到输出层的连接权和输出层的阈值;
for(t=0; t<q; t++){
for(j=0; j<p; j++){
V[j][t]=V[j][t]+a1*dt[t]*bj[j];
}
t2[t]=t2[t]+a1*dt[t];
}
//调整到中间层的连接权和中间层的阈值;
for(j=0; j<p; j++){
for(k=0; k<4; k++){
for(l=0; l<4; l++){
i=k*4+l;
W[i][j]=W[i][j]+b1*ej[j]*x0[k][l]; //W[i][j]=W[i][j]+b1*ej[j]*x0[l][k];
}
}
t1[j]=t1[j]+b1*ej[j];
}
//如果还有模式对尚未学习,则选取一个模式对学习;
cp++;
if(cp<=q){
goto L20;
}
//如果所有模式对学完{
// 总误差<最大允许误差,则学习成功;
// 学习回数>最大允许学习回数,则学习失败;
// 否则进行下一回学习;
//}
cnt++;
if ( (er<=emax)||(cnt>30000) ){
goto Ende;
}
cp=1; er=0;
goto L20;
Ende:
sMsg.Format("总学习回数=%d,误差=%f",cnt,er);
this->SetDlgItemText(IDC_EDIT_Count,sMsg);
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_Study);
pBtn->EnableWindow(TRUE);
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_Goal);
pBtn->EnableWindow(TRUE);
if(er>emax){
AfxMessageBox("Fail to study!");
return;
}
CTime time=CTime::GetCurrentTime();
s=time.Format("记录时间 %Y-%m-%d %H:%M:%S\n\n" );
sWeight=s;
sWeight+="输入层至中间层的权值W[16][8]:\n";
for(i=0; i<n; i++){
for(j=0; j<p; j++){
s.Format("%f\t",W[i][j]);
sWeight+=s;
}
sWeight+="\n";
}
sWeight+="\n";
sWeight+="中间层至输出层的权值V[8][3]:\n";
for(j=0; j<p; j++){
for(t=0; t<q; t++){
s.Format("%f\t",V[j][t]);
sWeight+=s;
}
sWeight+="\n";
}
sWeight+="\n";
sWeight+="中间层的阈值t1[8]:\n";
for(j=0; j<p; j++){
s.Format("%f\t",t1[j]);
sWeight+=s;
}
sWeight+="\n\n";
sWeight+="输出层的阈值t2[3]:\n";
for(t=0; t<q; t++){
s.Format("%f\t",t2[t]);
sWeight+=s;
}
sWeight+="\n\n";
s.Format("总学习回数=%d,误差=%f",cnt,er);
sWeight+=s;
CStdioFile out;
out.Open("BPWeight.txt", CFile::modeCreate | CFile::modeWrite);
out.WriteString(sWeight);
out.Close();
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_quan);
pBtn->EnableWindow(TRUE);
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_remember);
pBtn->EnableWindow(TRUE);
}
void CDlgBP::OnBUTTONquan()
{
// TODO: Add your control notification handler code here
HWND h=::FindWindowEx(NULL,NULL,NULL,"Microsoft Internet Explorer");
::ShellExecute(h,"open","BPWeight.txt",NULL,NULL,SW_SHOWNORMAL);
}
void CDlgBP::OnBUTTONremember()
{
// TODO: Add your control notification handler code here
CDlgBPRem dlg;
dlg.DoModal();
}
void CDlgBP::OnBUTTONabout()
{
// TODO: Add your control notification handler code here
CString s="参考书目:\n";
s+="【1】王伟,《人工神经网络原理--入门与应用》,北京航空航天大学出版社,1995年10月,第一版 \n";
s+="【2】王旭,《人工神经元网络原理与应用》,东北大学出版社,2000年,第一版\n";
MessageBox(s,"BP",MB_ICONINFORMATION);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -