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

📄 dlgbp.cpp

📁 人工神经网络基本模型:BP、ART、Hopfield、SOM
💻 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 + -