C++实现BP 神经网络两类图形分辨出来

#include<iostream>      
#include<cmath>    
#include<fstream>  
using namespace std;      
  
  
#define  innode 9  //输入结点数      
#define  hidenode 10//隐含结点数         
#define  sample 8//BP样本数   
double allow_e=0.001;//允许误差  
  
  
class BpNet      
{      
public:      
    void train(double p[sample][innode ],double t[sample]);//Bp训练      
    double p[sample][innode];     //输入的样本      
    double t[sample];    //样本要输出的      
  
  
    double test(double *p);//Bp识别      
  
  
    BpNet();      
    virtual ~BpNet();      
  
  
public:      
    void init();      
    double w1[innode][hidenode];//隐含结点权值      
    double w2[hidenode];//输出结点权值      
  
  
  
  
    double rate_w1; //权值学习率(输入层-隐含层)      
    double rate_w2;//权值学习率 (隐含层-输出层)      
  
  
  
  
    double e;//单个样本误差计算      
    double error;//误差均值   
    double result;// Bp输出  
      
};      
  
  
BpNet::BpNet()      
{      
    error=0.1;      
    e=0.0;      
      
    rate_w1=0.6;  //权值学习率(输入层--隐含层)      
    rate_w2=0.6; //权值学习率 (隐含层--输出层)      
  
  
}      
  
  
BpNet::~BpNet()      
{      
  
  
}      
  
  
void winit(double w[],int n) //权值初始化      
{      
    for(int i=0;i<n;i++)      
        w[i]= (rand()%10)*0.1-0.5;    
}      
  
  
void BpNet::init()      
{      
    winit((double*)w1,innode*hidenode);      
    winit((double*)w2,hidenode);      
  
  
}      
  
  
void BpNet::train(double p[sample][innode],double t[sample])      
{      
    double pp[hidenode];//隐含结点的校正误差      
    double qq;//希望输出值与实际输出值的偏差      
    double yd;//希望输出值      
  
  
    double x[innode]; //输入向量      
    double x1[hidenode];//隐含结点状态值      
    double x2;//输出结点状态值      
    double o1[hidenode];//隐含层激活值      
    double o2;//输出层激活值      
  
  
    for(int isamp=0;isamp<sample;isamp++)//循环训练一次样品      
    {      
        for(int i=0;i<innode;i++)      
            x[i]=p[isamp][i]; //输入的样本      
  
  
        yd=t[isamp]; //期望输出的样本      
  
  
        //构造每个样品的输入和输出标准      
        ///输入层到隐层    
        for(int j=0;j<hidenode;j++)      
        {      
            o1[j]=0.0;      
            for(int i=0;i<innode;i++)      
                o1[j]=o1[j]+w1[i][j]*x[i];//隐含层各单元输入激活值      
            x1[j]=1.0/(1+exp(-o1[j]));//隐含层各单元的输出      
                
        }      
        ///隐层到输出层    
  
  
        o2=0.0;      
        for(int j=0;j<hidenode;j++)      
            o2=o2+w2[j]*x1[j];      
        x2=1.0/(1.0+exp(-o2));  //输出层各单元输出    
        /计算偏差并调整权值  
        qq=(yd-x2)*x2*(1-x2); //希望输出与实际输出的偏差      
        for(int j=0;j<hidenode;j++)      
            w2[j]+=rate_w2*qq*x1[j];  //下一次的隐含层和输出层之间的新连接权      
  
  
        for(int j=0;j<hidenode;j++)      
        {      
            pp[j]=0.0;      
  
  
            pp[j]=pp[j]+qq*w2[j];      
            pp[j]=pp[j]*x1[j]*(1-x1[j]); //隐含层的校正误差      
  
  
            for(int i=0;i<innode;i++)      
                w1[i][j]+=rate_w1*pp[j]*x[i]; //下一次的输入层和隐含层之间的新连接权      
        }      
        e+=fabs(yd-x2)*fabs(yd-x2)/2;          
    }    
    error=double(e/double(sample));//计算误差均值  
}      
  
  
double BpNet::test(double *p)      
{      
    double x[innode]; //输入向量      
    double x1[hidenode]; //隐含结点状态值      
    double x2; //输出结点状态值      
    double o1[hidenode]; //隐含层激活值      
    double o2; //输出层激活值      
  
  
    for(int i=0;i<innode;i++)      
        x[i]=p[i];      
  
  
    for(int j=0;j<hidenode;j++)      
    {      
        o1[j]=0.0;      
        for(int i=0;i<innode;i++)      
            o1[j]=o1[j]+w1[i][j]*x[i]; //隐含层各单元激活值      
        x1[j]=1.0/(1+exp(-o1[j]));//x1[j]=1.0/(1.0+exp(-o1[j]-b1[j])); //隐含层各单元输出      
  
  
    }      
    o2=0.0;      
    for(int j=0;j<hidenode;j++)      
        o2=o2+w2[j]*x1[j];//输出层各单元激活值      
    x2=1.0/(1.0+exp(-o2)); //  x2[k]=1.0/(1.0+exp(-o2[k]-b2[k]));//输出层各单元输出      
    result=x2;      
    return result;      
}      
  
  
//输入样本  可改变,以实现不同函数的模拟    
double X[sample][innode]= {      
    {1,1,1,-1,1,-1,-1,1,-1},  
    {1,-1,-1,1,1,1,1,-1,-1},  
    {-1,1,-1,-1,1,-1,1,1,1},  
    {-1,-1,1,1,1,1,-1,-1,1},  
    {1,-1,-1,1,-1,-1,1,1,1},  
    {-1,-1,1,-1,-1,1,1,1,1},  
    {1,1,1,-1,-1,1,-1,-1,1},  
    {1,1,1,1,-1,-1,1,-1,-1}  
};      
//期望输出样本      
double Y[sample]={1,1,1,1,0,0,0,0};      
  
  
int main()      
{      
    BpNet bp;      
    bp.init();      
    int times=0;    
    ofstream out("error.txt");  
    ofstream Result("result.txt");  
    进行训练,直到误差小于等于allow_e  
    while(bp.error>allow_e)      
    {      
        bp.e=0.0;      
        times++;      
        bp.train(X,Y);      
        cout<<"Times="<<times<<" error="<<bp.error<<endl;  
       out << bp.error<< endl;  
    }    
    out.close( );  
    cout<<"trainning complete..."<<endl;  
    进行验证  
    for(int k=0;k<sample;k++)  
    {  
        double r=bp.test(X[k]);     
        for(int i=0;i<innode;++i)   
        {  
            if(X[k][i]==1)  
                cout<<"* ";  
            if(X[k][i]==-1)  
                cout<<"  ";  
            if((i+1)%3==0)  
                cout<<endl;        
        }  
        cout<<"的训练结果为";    
        cout<<bp.result<<" ";    
        Result<<bp.result<<endl;  
        double cha[sample];      
        double mi=100;      
        double index;      
        for(int i=0;i<sample;i++)      
        {      
            //找差值最小的那个样本      
            cha[i]=(double)(fabs(Y[i]-bp.result));      
            if(cha[i]<mi)      
            {      
                mi=cha[i];      
                index=Y[i];  //得到对应的期望输出    
            }      
        }      
        cout<<" 期望输出为 "<<index<<endl;      
        cout<<"-------------------------------------"<<endl;   
    }  
    return 0;      
}     
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值