📄 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 + -