C++实现BP算法实现正弦函数模拟

智能计算第二次作业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");

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值