📄 chooseview.cpp
字号:
// ChooseView.cpp : 实现文件
//
#include "stdafx.h"
#include "Apple.h"
#include "ChooseView.h"
#include ".\chooseview.h"
#include "AppleDoc.h"
#include "AppleView.h"
#include "MainFrm.h"
#include <time.h>
#include <math.h>
// CChooseView
#define INPUT_NUMBER 3 /*input*/
#define HIDE_NUMBER 3 /*hidden*/
#define OUT_NUMBER 1 /*output*/
#define U0 1
#define YINO 1
#define BETA 0.1 //步长
#define AFA 0.6 //a的值
#define SpNUM 3
#define MINERR 0
double dblWeight_IN_HD[HIDE_NUMBER][INPUT_NUMBER]; //初始的三个不同的输入和不同的Weight
double dblWeight_HD_OT[OUT_NUMBER][HIDE_NUMBER]; //隐含层输出的不同的三个初始Weight
double dblOut_IN[INPUT_NUMBER]; /*output of input layer*/ //输入层的输出
double dblOut_HD[HIDE_NUMBER]; /*output of hidden layer*/ //隐含层的输出
double dblOut_OT[OUT_NUMBER]; /*output of output layer*/ //最后的输出
double delta_HD[HIDE_NUMBER];
double delta_OT[OUT_NUMBER];
double CW_HD[HIDE_NUMBER]; /*limit value of hidden layer*/ //隐含层的阀值 三个
double CW_OT[OUT_NUMBER]; /*limit value of output layer*/ //输出层的阀值 一个
//int X[SpNUM][INNUM];
//int T[SpNUM][ON];
double OT[SpNUM][OUT_NUMBER];
//GA_realated
//const int POPNUM=4;
double GAdblWeight_IN_HD[POPNUM][HIDE_NUMBER][INPUT_NUMBER]; //初始的三个不同的输入和不同的Weight
double GAdblWeight_HD_OT[POPNUM][OUT_NUMBER][HIDE_NUMBER]; //隐含层输出的不同的三个初始Weight
double GAerrorp[POPNUM];
//total
double T[SpNUM][OUT_NUMBER] ={1,0.5,0.25};
double X[SpNUM][INPUT_NUMBER] ={{0,0,1},{0,1,0},{1,0,0}};
IMPLEMENT_DYNCREATE(CChooseView, CFormView)
CChooseView::CChooseView()
: CFormView(CChooseView::IDD)
, m_check0(FALSE)
, m_check1(FALSE)
, m_check2(FALSE)
{
train_count=0;
//int *t = new int[POPNUM+1];
}
CChooseView::~CChooseView()
{
}
void CChooseView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
DDX_Check(pDX, IDC_CHK0, m_check0);
DDX_Check(pDX, IDC_CHK1, m_check1);
DDX_Check(pDX, IDC_CHK2, m_check2);
}
BEGIN_MESSAGE_MAP(CChooseView, CFormView)
ON_BN_CLICKED(IDC_BTNSTUDY, OnBnClickedBtnstudy)
ON_BN_CLICKED(IDC_BTNREC, OnBnClickedBtnrec)
ON_BN_CLICKED(IDC_BTNSTUDY2, OnBnClickedBtnstudy2)
END_MESSAGE_MAP()
// CChooseView 诊断
#ifdef _DEBUG
void CChooseView::AssertValid() const
{
CFormView::AssertValid();
}
void CChooseView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
CAppleDoc* CChooseView::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CAppleDoc)));
return (CAppleDoc*)m_pDocument;
}
#endif //_DEBUG
// CChooseView 消息处理程序
//void CChooseView::OnBnClickedCheck1()
//{
// // TODO: 在此添加控件通知处理程序代码
// CAppleDoc* pDoc =(CAppleDoc* )GetDocument();
// pDoc->m =1;
// pDoc->UpdateAllViews (this);
//}
void CChooseView::OnBnClickedBtnstudy()
{
// TODO: 在此添加控件通知处理程序代码
CAppleDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDoc->m_Sign=true;
pDoc->UpdateAllViews (this);
//this->GetDocument()->UpdateAllViews (this);
}
void CChooseView::init()
{
wgtinit((double*)dblWeight_IN_HD,INPUT_NUMBER*HIDE_NUMBER); //输入层的9个初始 weight
wgtinit((double*)dblWeight_HD_OT,HIDE_NUMBER*OUT_NUMBER); // 隐含层的3个 weight
//for (int i=0;i<3;i++)
// for (int j=0;j<3;j++)
// dblWeight_IN_HD[i][j]=(i+j)/2.0;
//for (int j=0;j<3;j++)
// dblWeight_HD_OT[j][0]=-1;
wgtinit(CW_HD,HIDE_NUMBER); //隐含层的三个随机的阀值
wgtinit(CW_OT,OUT_NUMBER); //最后的输出层的一个随机的阀值
}
void CChooseView::wgtinit(double w[],int sl)
{
int i;
double d;
srand((unsigned)time(NULL));
for(i=0;i<sl;i++)
{
d= rand()/32767.0;
*(w+i)=0.2*d;
}
}
void CChooseView::forwardcp(int ft,int bk,double w[],double in[],double out[],double cw[])
{
int i,j;
double sum;
for(j=0;j<bk;j++) //w[j][i],,,样本第i个属性上的在隐层第j个神经元上的权重
{
sum=0;
for(i=0;i<ft;i++)
{
sum=sum+w[j*ft+i]*in[i];
}
//净输入sum
sum-=cw[j]/10;
out[j]=sigmf(sum);
}
}
double CChooseView::sigmf(double u)
{
double su;
su=-u/U0;
su=1/(1.0+exp(su));
//if(su>0.9) su=1; else if (su<0.1) su=0;
return su;
}
void CChooseView::Bpcal(int p)
{
int i,j,k;
double ajtW,Bdelta_OT;
double MajtW,MBdelta_OT;
//调节隐含层的输出权重 dblWeight_HD_OT[3]共三个;
for(j=0;j<OUT_NUMBER;j++)
{
//用到的公式是: d=X(1-X)(X-Y)
delta_OT[j]=dblOut_OT[j]*(1-dblOut_OT[j])*(T[p][j]-dblOut_OT[j]);
Bdelta_OT=BETA*delta_OT[j];
for(i=0;i<HIDE_NUMBER;i++)
{
//ajtW=YINO*delta_OT[j]*dblOut_HD[i];
ajtW=Bdelta_OT*dblOut_HD[i];
dblWeight_HD_OT[j][i] +=ajtW;
//用到的公式是:对误差和权重都分别取比例的调节公式
//即W(t+1)=W(t)-n*d*x+a*W(t)
//dblWeight_HD_OT[j][i] =dblWeight_HD_OT[j][i]-ajtW+AFA*dblWeight_HD_OT[j][i];
}
//调整阈值
CW_OT[j]+=BETA*delta_OT[j];
}
//调节初始输入层的权重 dblWeight_IN_HD[3][3]],共九个;
for(j=0;j<HIDE_NUMBER;j++)
{
//用到的公式是: d(k)=x(k)(1-x(k))*(求和w(l_i)*d(k+1));
delta_HD[j]=delta_OT[0]*dblWeight_HD_OT[0][j]*dblOut_HD[j]*(1-dblOut_HD[j]); //隐层第j个神经元的输入误差;
MBdelta_OT=BETA*delta_HD[j];
//开始调节最初输入的9个权重
//w[j][i],,,样本第i个属性上的在隐层第j个神经元上的权重
for(k=0;k<INPUT_NUMBER;k++)
{
MajtW=MBdelta_OT*dblOut_IN[k];
dblWeight_IN_HD[j][k]+=MajtW; //当出现权重不变的时候,是因为有输入为0的情况,这时调节权重为0;所以权重不变。
//用到的公式是:对误差和权重都分别取比例的调节公式
//即W(t+1)=W(t)-n*d*x+a*W(t)
//dblWeight_IN_HD[j][k] =dblWeight_IN_HD[j][k]-MajtW+AFA*dblWeight_IN_HD[j][k];
}
//调整阈值
CW_HD[j]+=BETA*delta_HD[j];
}
}
void CChooseView::GetChkValue(double * chk) //得到界面上的属性的值
{
if(m_check0)
chk[0]=1;
else
chk[0]=0;
if(m_check1)
chk[1]=1;
else
chk[1]=0;
if(m_check2)
chk[2]=1;
else
chk[2]=0;
}
void CChooseView::go_one_step ()
{
int i,p;
double Err,Errp[3];
CString s;
int flag=0;
CAppleDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
//pDoc->UpdateAllViews (this);//在这里加上为什么到最后线条会消失.???
train_count=0;
//for(p=0;p<SpNUM;p++)
//{
// for(i=0;i<INPUT_NUMBER;i++)
// dblOut_IN[i]=X[p][i]; //将开始的三个输入的值给 dblOut_IN[3] 变量;
//
// //从输入层的一个前向
// /*forward computation*/ //输入层 权重 //输入层值 //输出值 //隐层阀值
// forwardcp(INPUT_NUMBER,HIDE_NUMBER,(double*)dblWeight_IN_HD,dblOut_IN,dblOut_HD,CW_HD);
//
// //从隐含层作为一个输入层的前向
// forwardcp(HIDE_NUMBER,OUT_NUMBER,(double*)dblWeight_HD_OT,dblOut_HD,dblOut_OT,CW_OT);
// /*adjust weight*/
// //Bpcal(p);
//}
init();
/*compute the error*/
Err=0;
//输出权重用到的变量
CString str,strweight,stri,strj;
CMainFrame* pMF=(CMainFrame*)AfxGetApp()->m_pMainWnd;
CChooseView* pLV=(CChooseView*)pMF->m_WndSplitter.GetPane(0,0);
CAppleView* pRV=(CAppleView*)pMF->m_WndSplitter.GetPane(0,1);
CClientDC dc(pRV);
double max1(0), max2(0), max3(0);
do
{
for(p=0;p<SpNUM;p++)
{
for(i=0;i<INPUT_NUMBER;i++)
dblOut_IN[i]=X[p][i]; //dblOut_IN[i]=x=[0][i]{0,0.1} 第i个样本的输入
train_count++;
pDoc->mycount=train_count;
//Sleep(1); //时间延迟
//PeekMessage( &msg, NULL, 0, 0, PM_REMOVE );
////if( msg.message == WM_QUIT )
//// break;
//TranslateMessage( &msg );
//DispatchMessage( &msg );
/*forward computation*/
forwardcp(INPUT_NUMBER,HIDE_NUMBER,(double*)dblWeight_IN_HD,dblOut_IN,dblOut_HD,CW_HD);
forwardcp(HIDE_NUMBER,OUT_NUMBER,(double*)dblWeight_HD_OT,dblOut_HD,dblOut_OT,CW_OT);
for(i=0;i<OUT_NUMBER;i++) //每一个初始样本输入的所对应的最后输出
OT[p][i]=dblOut_OT[i];
//pDoc->wout =dblOut_OT[0];
//这里是误差计算,但在Bpcal()中也有误差的计算.所以这里的代码没用.
//Errp=0;
//for(i=0;i<OUT_NUMBER;i++)
//{
// //和教师信号T[0,1,2]的比较在这里体现;
// Errp+=0.5*(T[p][i]-OT[p][i])*(T[p][i]-OT[p][i]);
//}
//Err+=Errp;
//我认为应该在这里加上权重的调节程序
/*adjust weight*/
Bpcal(p); //调节在输入第p个样本时候的权重;
Errp[p]=OT[p][0]-T[p][0];
////train_count在这里*******************************
//保存当次的输入权重
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
pDoc->inweight[i][j]=dblWeight_IN_HD[i][j];
//保存当次的隐层权重
for(int u=0;u<3;u++)
pDoc->hdweight[u]=dblWeight_HD_OT[0][u];
//输出权重
//当次的权重就输出,而不是和V1.5一样,保存在一个很大的数组中,在做完计算后才进行输出画线;
for(int i1=0;i1<3;i1++)
for(int j=0;j<3;j++)
{
strweight.Format ("%f",pDoc->inweight[i1][j]);
stri.Format ("%d",i1);
strj.Format ("%d",j);
dc.TextOut (185,60+20*(j+i1*3),strweight);
}
//隐层
for(int j=0;j<3;j++)
{
strweight.Format ("%f",pDoc->hdweight[j]);
strj.Format ("%d",j);
dc.TextOut (185,250+20*j,strweight);
}
s.Format ("%d",train_count);
dc.TextOut (100,0,s);
pDoc->lastout[p]=OT[p][0];
if(pDoc->lastout[0]>max1)
{
CBrush newbrush;
newbrush.CreateHatchBrush(6,RGB(255,0,0));
CBrush * pOldpen=(CBrush*)dc.SelectObject (&newbrush);
max1=pDoc->lastout[0];
dc.SetPixel((train_count+1)/50+300,280-max1*200,RGB(255,0,0));
//dc.Ellipse((train_count+1)/50+300,280-max1*200,(train_count+1)/50+302,280-max1*201);
}
if(pDoc->lastout[1]>max2)
{
CBrush newbrush1;
newbrush1.CreateHatchBrush(6,RGB(0,255,0));
CBrush * pOldpen=(CBrush*)dc.SelectObject (&newbrush1);
max2=pDoc->lastout[1];
dc.SetPixel((train_count+1)/50+300,340-max1*200,RGB(0,255,0));
//dc.Ellipse((train_count+1)/50+300,340-max2*200,(train_count+1)/50+302,340-max2*202);
}
if(pDoc->lastout[2]>max3)
{
CBrush newbrush2;
newbrush2.CreateHatchBrush(6,RGB(0,0,255));
CBrush * pOldpen=(CBrush*)dc.SelectObject (&newbrush2);
max3=pDoc->lastout[2];
dc.SetPixel((train_count+1)/50+300,380-max1*200,RGB(0,0,255));
//dc.Ellipse((train_count+1)/50+300,380-max2*200,(train_count+1)/50+302,380-max2*202);
}
//保存最后的输出
//pDoc->lastout[train_count][p]=OT[p][0];
//pDoc->UpdateAllViews (this);
//Invalidate(true);为什么不行???
}
}while((fabs(Errp[0])>0.1)||(fabs(Errp[1])>0.1)||(fabs(Errp[2])>0.1));
pDoc->Success=true;
GetDlgItem(IDC_BTNREC)->EnableWindow(true);
//s.Format ("%d",train_count);
//MessageBox("学习完成!"+s);
//pDoc->UpdateAllViews (this);
}
//BOOL CChooseView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
//{
// // TODO: 在此添加专用代码和/或调用基类
//
// return CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
//}
void CChooseView::OnBnClickedBtnrec()
{
// TODO: 在此添加控件通知处理程序代码
//CAppleDoc* pDoc = GetDocument();
//ASSERT_VALID(pDoc);
m_result = new char[10];
UpdateData();
double myfruit[3];
GetChkValue(myfruit);
double result;
result=recognize(myfruit);
switch ((int)(result*100))
{
case 100:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -