?? nnview.cpp
字號:
// NNView.cpp : implementation of the CNNView class
//
#include "stdafx.h"
#include "NN.h"
#include "NNDoc.h"
#include "NNView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CNNView
IMPLEMENT_DYNCREATE(CNNView, CView)
BEGIN_MESSAGE_MAP(CNNView, CView)
//{{AFX_MSG_MAP(CNNView)
ON_COMMAND(ID_MODAL_BP, OnModalBp)
ON_COMMAND(ID_MODAL_REVERSE, OnModalReverse)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CNNView construction/destruction
CNNView::CNNView()
{
// TODO: add construction code here
}
CNNView::~CNNView()
{
}
BOOL CNNView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CNNView drawing
void CNNView::OnDraw(CDC* pDC)
{
CNNDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->TextOut (10,10,"詳細說明見word文檔.............");
}
/////////////////////////////////////////////////////////////////////////////
// CNNView diagnostics
#ifdef _DEBUG
void CNNView::AssertValid() const
{
CView::AssertValid();
}
void CNNView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CNNDoc* CNNView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CNNDoc)));
return (CNNDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CNNView message handlers
void CNNView::OnModalBp() ///////bp網絡辨識
{
RECT rect;
GetClientRect(&rect);
CClientDC dc(this);
dc.Rectangle(0,0,rect.right ,rect.bottom); /////清除客戶區
////////定義變量//////////
CPoint zero(20,300); ////原點坐標
const int ni=5,nh1=20,nh2=10; ////,no=1;///四層網絡,各層節點數
double w12[ni+1][nh1+1],w23[nh1+1][nh2+1],w34[nh2+1]; ////權值
double e2[nh1+1],e3[nh2+1],e4; ///誤差
double xin[ni+1],h1[nh1+1],h2[nh2+1],yout; ////網絡各層輸出
const int s_number=800; ////采樣點個數
double u[s_number+1]; ////輸入
double y[s_number+1]; //////實際輸出
int i,j,k,n ,m; ///循環變量
double alpha ; ///學習因子
///...........
const int train_times=10000; /////訓練次數
const int train_number=100; ////訓練點數
double e_all; ////誤差平方和
const double error_limit=0.0001; /////誤差限 mspe
double mspe=1;
CString str;
double amax=2.0,amin=0.1,A=10.0; /////自適應 計算alpha 用
int kx=200; /////放大倍數---畫曲線用
int yy; /////輸出坐標---畫曲線用
/////////////.........
dc.SelectStockObject (BLACK_PEN);
dc.TextOut (10,2,"訓練中......." );
dc.TextOut (10,60,"綠色的曲線是網絡輸出......");
dc.TextOut (10,40,"紅色的曲線是對象輸出....");
/////////////////////////////////////////////
//////////畫對象輸出///////////////////
////坐標線
dc.MoveTo (zero); /////x坐標
dc.LineTo (rect.right-50,zero.y);
dc.MoveTo (zero.x ,rect.bottom -50);
dc.LineTo (zero.x ,rect.top +100);
dc.MoveTo (zero.x ,rect.top +100); /////here
dc.LineTo (zero.x-5 ,rect.top +110);
dc.MoveTo (zero.x ,rect.top +100);
dc.LineTo (zero.x+5 ,rect.top +110);
dc.MoveTo (rect.right-50 ,zero.y ); ///y坐標
dc.LineTo (rect.right-60 ,zero.y-5 );
dc.MoveTo (rect.right-50 ,zero.y );
dc.LineTo (rect.right-60 ,zero.y+5 );
////參考線y +0.5 --- -0.5
dc.MoveTo (zero);
dc.MoveTo (zero.x ,zero.y -0.5*kx);
dc.LineTo (zero.x+10 ,zero.y -0.5*kx);
dc.TextOut (30,zero.y-0.5*kx-22,"0.5");
dc.MoveTo (zero.x ,zero.y +0.5*kx);
dc.LineTo (zero.x+10,zero.y +0.5*kx);
dc.TextOut (30,zero.y +0.5*kx-22,"-0.5");
////參考線x
dc.MoveTo (zero);
for(i=0;i<=s_number-140;i+=20)
{
dc.MoveTo (zero.x+i,zero.y);
dc.LineTo (zero.x+i,zero.y-10);
}
for(i=0;i<=s_number-100;i+=100)
{
str.Format ("%d",i);
dc.TextOut (zero.x+i-10,zero.y+2,str);
}
/////初始化輸入 u[k]
for (i=1;i<=s_number;i++)
u[i]=sin(2*3.1415926535*i/250);
/////計算實際輸出 y[k]
y[3]=y[1]=y[2]=0;
for(k=4;k<=s_number;k++)
y[k]=(y[k-1]*y[k-2]*u[k-1]*(y[k-3]-1)+u[k-2])/(1+y[k-1]*y[k-1]+y[k-2]*y[k-2]);
/////劃線
CPen apen; ////////a new pen
apen.CreatePen(PS_SOLID,1,RGB(255,0,0));
dc.SelectObject (apen);
dc.MoveTo (zero);
for (i=1;i<=s_number;i++) //s_number=800; //采樣點個數
{
yy=zero.y -y[i]*kx; // kx=200; //放大倍數---畫曲線用
dc.LineTo (zero.x+i,yy);
dc.MoveTo (zero.x+i,yy);
};
//////////////////////////////////////
/// srand((unsigned)time(NULL));
/////初始化訓練信號
// int mm[16]={1,1,1,1,0,0,0,1,0,0,1,1,0,1,0};
for (i=1;i<=s_number;i++)
u[i]=sin(2*3.1415926535*i/250);
//((double)rand()/(double)RAND_MAX)*2.0-1.0;
//mm[i-i/16]*0.01;
//(rand()/RAND_MAX)*0.2-0.1;
/////計算訓練輸入的對象輸出
y[3]=y[1]=y[2]=0;
for(k=4;k<=s_number;k++)
y[k]=(y[k-1]*y[k-2]*u[k-1]*(y[k-3]-1)+u[k-2])/(1+y[k-1]*y[k-1]+y[k-2]*y[k-2]);
////////////////////////////////////////
///////////////////訓練網絡/////////////
///隨機數 --- 權值賦初值
for(i=1;i<=ni;i++)
for(j=1;j<=nh1;j++)
{ //// random between -0.1--+0.1
w12[i][j]=rand();
w12[i][j]=w12[i][j]/RAND_MAX;
w12[i][j]=(2*w12[i][j]-1)*0.1;
};
for(i=0;i<=nh1;i++)
for(j=0;j<=nh2;j++)
{ //// random between -0.1--+0.1
w23[i][j]=rand();
w23[i][j]=w23[i][j]/RAND_MAX;
w23[i][j]=(2*w23[i][j]-1)*0.1;
};
for(i=0;i<=nh2;i++)
{ //// random between -0.1--+0.1
w34[i]=rand();
w34[i]=w34[i]/RAND_MAX;
w34[i]=(2*w34[i]-1)*0.1;
};
///////////////////////////////////////////////
//////開始訓練網絡/////////
// train_times=10000; /////訓練次數
// train_number=100; /////訓練點數
for (n=1;n<=train_times;n++)
{
e_all=0;
for(k=3+20;k<=train_number+20;k++) //// 只取了300個點
{ ///構成輸入向量
xin[1]=y[k-1];
xin[2]=y[k-2];
xin[3]=y[k-3];
xin[4]=u[k-1];
xin[5]=u[k-2];
////////////////////
h1[0]=0;h2[0]=0;
for(i=1;i<=nh1;i++) //// 隱層h1輸出求得
{ h1[i]=0.0;
for(j=1;j<=ni;j++)
h1[i]=h1[i]+xin[j]*w12[j][i];
}
for(i=1;i<=nh2;i++) //// 隱層h2輸出求得
{ h2[i]=0.0;
for(j=1;j<=nh1;j++)
h2[i]=h2[i]+h1[j]*w23[j][i];
}
yout=0.0; //// 輸出層yout求得
for(j=1;j<=nh2;j++)
yout=yout+h2[j]*w34[j];
///////////////////
e_all+=(yout-y[k])*(yout-y[k]); // 總誤差!!!
//////反向傳播修正權值
alpha=amax+(amin-amax)*exp(-A*mspe);
/////////輸出層權值 w34//////////////
e4= (y[k]-yout)*yout*(1-yout);
for(j=1;j<=nh2;j++)
w34[j]=w34[j]+alpha*e4*h2[j];
////////////隱層權值 w23///////////////
for(i=1;i<=nh2;i++) /////計算誤差e3
e3[i]=e4*w34[i]*h2[i]*(1-h2[i]);
for(j=1;j<=nh1;j++) ////w23
for(i=1;i<=nh2;i++)
w23[j][i]=w23[j][i]+alpha*e3[i]*h1[j];
//////////隱層權值 w12/////////////
for(i=1;i<=nh1;i++) ////計算誤差e2
{ e2[i]=0;
for(m=1;m<=nh2;m++)
e2[i]=e2[i]+e3[m]*w23[i][m];
e2[i]=e2[i]*h1[i]*(1-h1[i]);
}
for(j=1;j<=ni;j++) //////w12
for(i=1;i<=nh1;i++)
w12[j][i]=w12[j][i]+alpha*e2[i]*xin[j];
}; //////k個樣本訓練完畢 計算均方誤差
mspe=e_all/(train_number*2);
if (mspe<error_limit)
{ dc.TextOut (10,2,"達到誤差要求......" );
str.Format (" %d %s %s %d %s",train_number,"個樣本","訓練了",n,"次.....");
dc.TextOut (zero.y ,2,str );
break; /////exit for(n=1;n<=train_times;n++)
}
}
///////////////訓練結束////////////////
if(n>=train_times)
{ str.Format ("%s %d","達到訓練次數...",train_times);
dc.TextOut (10,20 ,str);
}
if (mspe>error_limit)
dc.TextOut (10,2,"誤差未達到要求......" );
str.Format ("%s%f","MSPE=",mspe);
dc.TextOut (zero.y,22,str);
/////////////////////////////////////////////
//////////////////////輸出結果///////////////
/////初始化輸入
for (i=1;i<=s_number;i++)
u[i]=sin(2*3.1415926535*i/250);
/////計算實際輸出
y[3]=y[1]=y[2]=0;
for(k=4;k<=s_number;k++)
y[k]=(y[k-1]*y[k-2]*u[k-1]*(y[k-3]-1)+u[k-2])/(1+y[k-1]*y[k-1]+y[k-2]*y[k-2]);
///////////////
CPen bpen;
bpen.CreatePen(PS_SOLID,1,RGB(0,255,0));
dc.SelectObject (bpen);
dc.MoveTo (zero);
/////計算并畫出網絡輸出///////////
for(k=4;k<=s_number;k++)
{ ///構成輸入向量
xin[1]=y[k-1];
xin[2]=y[k-2];
xin[3]=y[k-3];
xin[4]=u[k-1];
xin[5]=u[k-2];
///////////////////
for(i=1;i<=nh1;i++) //// 隱層h1輸出求得
{ h1[i]=0;
for(j=1;j<=ni;j++)
h1[i]=h1[i]+xin[j]*w12[j][i];
};
for(i=1;i<=nh2;i++) //// 隱層h2輸出求得
{ h2[i]=0;
for(j=1;j<=nh1;j++)
h2[i]=h2[i]+h1[j]*w23[j][i];
};
yout=0; //// 輸出層yout求得
for(j=1;j<=nh2;j++)
yout=yout+h2[j]*w34[j];
////draw
yy=zero.y -yout*kx;
dc.LineTo (zero.x+k,yy);
dc.MoveTo (zero.x+k,yy);
};
};
void CNNView::OnModalReverse() //////逆模型1 非線性對象 單層網絡
{
RECT rect;
GetClientRect(&rect);
CClientDC dc(this);
dc.Rectangle(0,0,rect.right ,rect.bottom);
const int ni=6; ///輸入層節點數
const int sample_points=170; ///采樣點
const int traintimes=10000;
double u[sample_points+1];
double y[sample_points+1]; ////對象輸入和輸出
double x[ni+1]; ///網絡輸入向量
double wi[ni+1]; ///輸入權值向量
double yout[sample_points+1]; ////網絡輸出
double e=0,lin=0;
double alpha=0.8; ///步長
int i,j,k;
int kx=4,ky=100; ////作圖的放大系數
CPoint zero(20,280); ////原點
double yy;
CString str;
dc.TextOut (10,10,"訓練中..............");
dc.TextOut (10,rect.bottom-60 ,"藍色的曲線是輸入......");
dc.TextOut (10,rect.bottom -40,"紅色的曲線是對象輸出....");
dc.TextOut (10,rect.bottom -20,"綠色的曲線是訓練后的網絡輸出......");
//////////////////畫坐標軸////////
//坐標軸x
dc.MoveTo (zero);
dc.LineTo (rect.right ,zero.y );
dc.MoveTo(rect.right-5 ,zero.y );
dc.LineTo(rect.right-15 ,zero.y-5);
dc.MoveTo(rect.right-5 ,zero.y );
dc.LineTo(rect.right-15 ,zero.y+5);
//坐標軸y
dc.MoveTo(zero.x ,rect.bottom-60);
dc.LineTo(zero.x ,rect.top + 50);
dc.MoveTo (zero.x,rect.top + 50);
dc.LineTo (zero.x-5,rect.top + 60);
dc.MoveTo (zero.x,rect.top + 50);
dc.LineTo (zero.x+5,rect.top + 60);
////參考線y
dc.MoveTo (zero);
for(i=-4;i<=2;i++)
{
dc.MoveTo (zero.x,zero.y+i*ky*0.5);
dc.LineTo (zero.x+10,zero.y+i*ky*0.5); ///小短線
str.Format ("%1.1f",-i*0.5);
dc.TextOut (zero.x+10,zero.y+i*ky*0.5-20,str); ///標記
}
/*
dc.MoveTo (zero.x ,zero.y -0.5*kx);
dc.LineTo (zero.x+10 ,zero.y -0.5*kx);
dc.TextOut (30,zero.y-0.5*kx-22,"0.5");
dc.MoveTo (zero.x ,zero.y +0.5*kx);
dc.LineTo (zero.x+10,zero.y +0.5*kx);
dc.TextOut (30,zero.y +0.5*kx-22,"-0.5");*/
////參考線x
dc.MoveTo (zero);
for(i=0;i<=sample_points*kx;i+=20)
{
dc.MoveTo (zero.x+i*kx,zero.y);
dc.LineTo (zero.x+i*kx,zero.y-10);
}
for(i=0;i<=sample_points;i+=10)
{
str.Format ("%d",i);
dc.TextOut (zero.x+i*kx-10,zero.y+2,str);
}
////////初始化網絡權值
for(i=1;i<=ni;i++) wi[i]=0.5;
////輸入
for(i=1;i<=sample_points;i++)
{
if (i<=20)
u[i]=1.0;
else if(i<=40)
u[i]=(double)i/20;///1.0+(i-20)/20;
else if(i<=60)
u[i]=4.0-(double)i/20;//2.0-(i-40)/20;
else
u[i]=1.0+sin(0.1*i-6.1);
}
/////輸入曲線
dc.MoveTo (zero);
CPen pen0;
pen0.CreatePen (PS_SOLID,1,RGB(0,0,255));
dc.SelectObject (pen0);
for(k=1;k<=sample_points;k++)
{
yy=zero.y-u[k]*ky;
dc.LineTo (k*kx+zero.x,yy);
dc.MoveTo (k*kx+zero.x,yy);
}
////對象輸出
///for(i=1;i<=sample_points;i++) u[i]=1.0;
y[1]=0;
for(i=2;i<=sample_points;i++)
y[i]=(y[i-1]*exp(-y[i-1])+u[i-1])/(1.0+u[i-1]*exp(-y[i-1]));
/////畫對象輸出曲線
dc.MoveTo (zero);
CPen pen1;
pen1.CreatePen (PS_SOLID,1,RGB(255,0,0)); ////red
dc.SelectObject (pen1);
for(k=1;k<=sample_points;k++)
{
yy=zero.y -y[k]*ky;
dc.LineTo (k*kx+zero.x,yy);
dc.MoveTo (k*kx+zero.x,yy);
}
///////訓練網絡
double e_all;
for(i=1;i<=traintimes;i++)
{
e_all=0.0;
for(k=7;k<=sample_points;k++)
{
x[1]=y[k-1];
x[2]=y[k-2];
x[3]=y[k-3];
x[4]=y[k-4];
x[5]=y[k-5];
x[6]=y[k-6]; ////構成輸入向量
yout[k]=0;
for(j=1;j<=ni;j++)
yout[k]+=wi[j]*x[j];
e=y[k]-yout[k];
e_all+=e*e;
lin=0.0;
for(j=1;j<=ni;j++) lin+=x[j]*x[j];
lin=alpha*e/lin;
for (j=1;j<=ni;j++) ////修正網絡權值
wi[j]+=lin*x[j];
}
}
dc.TextOut (10,10,"訓練結束........................");
//////////////訓練結束 畫網絡輸出
/* for(i=1;i<=sample_points;i++)
{
if (i<=20)
u[i]=1.0;
else if(i<=40)
u[i]=(double)i/20;///1.0+(i-20)/20;
else if(i<=60)
u[i]=4.0-(double)i/20;//2.0-(i-40)/20;
else
u[i]=1.0+sin(0.1*i-6.1);
}
////對象輸出
y[1]=0;
for(i=2;i<=sample_points;i++)
y[i]=(y[i-1]*exp(-y[i-1])+u[i-1])/(1.0+u[i-1]*exp(-y[i-1]));
*/
for(k=7;k<=sample_points;k++)
{
x[1]=y[k-1];
x[2]=y[k-2];
x[3]=y[k-3];
x[4]=y[k-4];
x[5]=y[k-5];
x[6]=y[k-6]; ////構成輸入向量
yout[k]=0;
for(i=1;i<=ni;i++)
yout[k]+=wi[i]*x[i];
}
dc.MoveTo (zero);
CPen pen2;
pen2.CreatePen (PS_SOLID,1,RGB(0,255,0));
dc.SelectObject (pen2);
for(k=7;k<=sample_points;k++)
{
yy=zero.y-yout[k]*ky;
dc.LineTo (k*kx+zero.x,yy);
dc.MoveTo (k*kx+zero.x,yy);
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -