智能计算第二次作业2
1、题目:
建立一个单输入但输出的三层神经网络,模拟下列三角函数:
Y=sin(x)+cos(x); (- , )
验证区间:(-3/2 , 3/2 )
2、实现步骤:
①初始化:设定wji(0), wkj(0) ,设计一个“合理的网络结构”,隐层数为1
函数采用Sigmoid()函数, y=-1+2/(1+exp(-x)), 使y在(-1,1)之间
导数为y‘=(1-y)(1+y)
②对每个输入样本进行如下计算:
a 前向信号传播
b 反向误差传播
③n=n+1, 转入下一个计算周期。
3、核心代码及说明:
参数说明:
int const n=200; //采样数及检测数
int const hidenode=15;
double l=0.5; //步长为0.5
double x[n]; //输入
double d[n];//期望输出
double test[n];//检测样本数
///样本采集
for(int i=0;i<n;i++)
{
x[i]=(double(i)/n)*2*3.14-3.14;
test[i]=(double(i)/n)*3*3.14-1.5*3.14;
//目标输出函数
d[i]=(sin(x[i])+cos(x[i]))/sqrt(2); //是使之适应Sigmoid函数
}
训练部分:
int time=0;
while(E>0.001)
{
time++;
double e_=0;
for(int k=0;k<n;k++)
{
//正向传播
//输入层到隐层
y1=x[k];
for(inti=0;i<hidenode;i++)
{
v2[i]=-1*w1[0][i]+y1*w1[1][i];
y2[i]=S(v2[i]);
}
//隐层到输出层
v3=-1*w2[0];
for(inti=0;i<hidenode;i++)
v3+=y2[i]*w2[i+1];
y3[k]=S(v3);
//计算误差
e[k]=d[k]-y3[k];
e_=e_+(d[k]-y3[k])*(d[k]-y3[k])/2;
//反向传播
//输出层到隐层
double deltas_3;
deltas_3=0.5*(1+y3[k])*(1-y3[k])*e[k];
w2[0]+=-l*1*deltas_3;
for(inti=0;i<hidenode;i++)
{
w2[i+1]+=l*y2[i]*deltas_3;
}
//隐层到输入层
double deltas_2[hidenode];
for(inti=0;i<hidenode;i++)
{
deltas_2[i]=0.5*(1+y2[i])*(1-y2[i])*w2[i+1]*deltas_3;
}
for(int i=0;i<hidenode;i++)
{
w1[0][i]+=-l*1*deltas_2[i];
w1[1][i]+=l*y1*deltas_2[i];
}
}
E=e_/n; //计算平均误差
cout<<time<<" E "<<E<<endl;
}
验证部分:
for(int k=0;k<n;k++)
{
y1=test[k];
for(inti=0;i<hidenode;i++)
{
v2[i]=-1*w1[0][i]+y1*w1[1][i];
y2[i]=S(v2[i]);
}
v3=-1*w2[0];
for(inti=0;i<hidenode;i++)
v3+=y2[i]*w2[i+1];
y3[k]=S(v3);
cout<<test[k]<<"验证结果"<<y3[k]*sqrt(2)<<endl;
}
4、运算结果:
(1) 满足允许平均误差0.001的运行结果,得到了矩阵w和u,及迭代次数和误差,并经行验证。
绘图结果:
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include<fstream>
#include <opencv2/core/core.hpp>
//#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
double S(double a)
{
return -1.0+2.0/(1+exp(-a));
}
void main ()
{
///cout<<S(773)<<endl;
//system("pause");
int const n=200; //采样数及检测数
int const hidenode=15;
double l=0.5; //步长为0.5
double x[n]; //输入
double d[n];//期望输出
double test[n];//检测样本数
///样本采集
for(int i=0;i<n;i++)
{
x[i]=(double(i)/n)*2*3.14-3.14;
test[i]=(double(i)/n)*3*3.14-1.5*3.14;
//目标输出函数
d[i]=(sin(x[i])+cos(x[i]))/sqrt(2); //是使之适应Sigmoid函数
}
//前向信号传播
//double v1;
double y1;
double v2[hidenode];
double y2[hidenode];
double v3;
double y3[n];
double w1[2][hidenode];
double w2[hidenode+1];
for(int i=0;i<hidenode;i++)
{
w1[0][i]=(rand()%10)*0.1-0.5;
w1[1][i]=(rand()%10)*0.1-0.5;
}
for(int i=0;i<hidenode+1;i++)
w2[i]=(rand()%10)*0.1-0.5;
double e[n];
double E=100;
int time=0;
while(E>0.001)
{
time++;
double e_=0;
for(int k=0;k<n;k++)
{
//正向传播
//输入层到隐层
y1=x[k];
for(int i=0;i<hidenode;i++)
{
v2[i]=-1*w1[0][i]+y1*w1[1][i];
y2[i]=S(v2[i]);
}
//隐层到输出层
v3=-1*w2[0];
for(int i=0;i<hidenode;i++)
v3+=y2[i]*w2[i+1];
y3[k]=S(v3);
//计算误差
e[k]=d[k]-y3[k];
e_=e_+(d[k]-y3[k])*(d[k]-y3[k])/2;
//反向传播
//输出层到隐层
double deltas_3;
deltas_3=0.5*(1+y3[k])*(1-y3[k])*e[k];
w2[0]+=-l*1*deltas_3;
for(int i=0;i<hidenode;i++)
{
w2[i+1]+=l*y2[i]*deltas_3;
}
//隐层到输入层
double deltas_2[hidenode];
for(int i=0;i<hidenode;i++)
{
deltas_2[i]=0.5*(1+y2[i])*(1-y2[i])*w2[i+1]*deltas_3;
}
for(int i=0;i<hidenode;i++)
{
w1[0][i]+=-l*1*deltas_2[i];
w1[1][i]+=l*y1*deltas_2[i];
}
}
E=e_/n; //计算平均误差
cout<<time<<" E "<<E<<endl;
}
cout<<endl<<"w1[0]:"<<endl;
for(int i=0;i<hidenode;i++)
{
cout<<w1[0][i]<<endl;
}
cout<<endl<<"w1[1]:"<<endl;
for(int i=0;i<hidenode;i++)
{
cout<<w1[1][i]<<endl;
}
cout<<endl<<"w2:"<<endl;
for(int i=0;i<hidenode+1;i++)
cout<<w2[i]<<endl;
cout<<endl;
///检测验证
for(int k=0;k<n;k++)
{
y1=test[k];
for(int i=0;i<hidenode;i++)
{
v2[i]=-1*w1[0][i]+y1*w1[1][i];
y2[i]=S(v2[i]);
}
v3=-1*w2[0];
for(int i=0;i<hidenode;i++)
v3+=y2[i]*w2[i+1];
y3[k]=S(v3);
cout<<test[k]<<"验证结果"<<y3[k]*sqrt(2)<<endl;
}
fstream ofs("test_x.txt",ofstream::out);
for (int i = 0; i<n; i++)
{
ofs<<test[i];
ofs<<'\n';
}
ofs.close();
fstream ofs1("test_y.txt",ofstream::out);
for (int i = 0; i<n; i++)
{
ofs1<<y3[i]*sqrt(2);
ofs1<<'\n';
}
ofs1.close();
system("pause");
}