C++实现单层感知器网络

49 篇文章 1 订阅
19 篇文章 2 订阅

练习题:

       双输入单输出系统:

                 x1(1)=1                   x2(1)=1                         d(1)=1

                 x1(2)=-0.5              x2(2)=-1                        d(2)=-1

                 x1(3)=3                  x2(3)=1                         d(3)=1

                 x1(4)=-2                 x2(4)=-1                        d(4)=-1  

        建立一个 感知器网络,实现上述样本的分类。

         计算出相应的网络权值矩阵w。

1、            题目:

双输入单输出系统:

                 x1(1)=1                   x2(1)=1                        d(1)=1

                 x1(2)=-0.5              x2(2)=-1                       d(2)=-1

                 x1(3)=3                  x2(3)=1                        d(3)=1

                 x1(4)=-2                 x2(4)=-1                       d(4)=-1  

       建立一个感知器网络,实现上述样本的分类。

        计算出相应的网络权值矩阵W

2、            运算结果:

图1 实现误差输出,得出所求权值矩阵,并对样本实现分类:

图2 用opencv2的画线及画点函数实现样本分类及画出误差变化曲线。

3、            实现步骤及对以上结果的说明:

算法部分:

①初始化:建立一个神经元的感知器,开关函数采用  函数

   W阵的初值随机为[6,0.5,0.5],即b=6;步长为0.1.

        

②对网络施加四组输入, 计算感知器的输出

③计算误差:允许误差为E=0

       当E<0,则退出,网络训练结束,当E>=0时:

④调节网络权值系数

⑤令:n=n+1,转步骤2。

画图部分:

主要采用opencv2画线函数line(),画点函数circle()。

4、核心代码及说明:

while(E[n]>0)  //E[n]存储每一次循环的总误差,当总误差大于零,进行循环

    {

        n++;

        for(int i=0;i<4;i++)

        {

            W[1]=W[1]+l*(d[i]-Y[i])*X[i][1];//调节网络权值系数

            W[2]=W[2]+l*(d[i]-Y[i])*X[i][2];

            Y[i]=W[0]*X[i][0]+W[1]*X[i][1]+W[2]*X[i][2];

            if(Y[i]>=0)

                Y[i]=1;

            else

                Y[i]=-1;

            e[i]=abs(d[i]-Y[i]); //e[i]存储单个样本误差

        }

        E[n]=e[0]+e[1]+e[2]+e[3];//每次循环计算一次总误差

cout<<"E["<<n<<"]="<<E[n]<<endl;

}

///进行分类

for(int i=0;i<4;i++)

{

     if(Y[i]==1)

         cout<<"第"<<i<<"组属于第一类"<<endl;

     if(Y[i]==-1)

         cout<<"第"<<i<<"组属于第二类"<<endl;

}

4、            总结

通过C++编程实现感知器学习,我对其的原理理解更深刻了,只有通过一次次修改代码和查阅资料才知道自己对算法的些地方存在错误的认识,再不断改进自己的算法。

说明:

用了opencv画图

感知器的原理,张老师的课件有错,还是自己上网查吧。我也不确定我的理解是不是完全正确。

代码

  1. #include<iostream>  
  2. #include"math.h"  
  3. #include <opencv2/core/core.hpp>  
  4. //#include <opencv2/imgproc/imgproc.hpp>  
  5. #include <opencv2/highgui/highgui.hpp>  
  6. //  
  7. //#include "linefinder.h"  
  8. //#include "edgedetector.h"  
  9.   
  10. using namespace cv;  
  11. using namespace std;  
  12. int main()  
  13. {  
  14.     double W[4][3];  
  15.       
  16.     for(int i=0;i<4;i++)  
  17.     {  
  18.         W[i][1]=0.5;  
  19.         W[i][2]=0.5;  
  20.     }  
  21.   
  22.     double X[4][3]={-1,1,1,  
  23.         -1,-0.5,-1,  
  24.         -1,3,1,  
  25.         -1,-2,-1};  
  26.     double d[4]={1,-1,1,-1};  
  27.     double e[4];  
  28.     double E[10]={0,0,0,0,0,0,0,0,0,0};  
  29.     double b=5;  
  30.     //W[][0]=b;  
  31.     for(int i=0;i<4;i++)  
  32.         W[i][0]=b;  
  33.     double l=0.1;  
  34.     /*W[0][1]=rand()%10*0.1; 
  35.     W[0][2]=rand()%10*0.1; 
  36.     W[1][1]=rand()%10*0.1; 
  37.     W[1][2]=rand()%10*0.1; 
  38.     W[2][1]=rand()%10*0.1; 
  39.     W[2][2]=rand()%10*0.1; 
  40.     W[3][1]=rand()%10*0.1; 
  41.     W[3][2]=rand()%10*0.1;*/  
  42.     cout<<W[0][1]<<endl<<W[0][2]<<endl;  
  43.     cout<<W[1][1]<<endl<<W[1][2]<<endl;  
  44.     cout<<W[2][1]<<endl<<W[2][2]<<endl;  
  45.     cout<<W[3][1]<<endl<<W[3][2]<<endl;  
  46.     double Y[4]={0};  
  47.     for(int i=0;i<4;i++)  
  48.     {  
  49.         Y[i]=W[i][0]*X[i][0]+W[i][1]*X[i][1]+W[i][2]*X[i][2];  
  50.         //cout<<"Y["<<i<<"]="<<Y[i]<<endl;  
  51.         if(Y[i]>=0)  
  52.             Y[i]=1;  
  53.         else  
  54.             Y[i]=-1;  
  55.   
  56.         e[i]=abs(d[i]-Y[i]);  
  57.     }  
  58.     E[0]=e[0]+e[1]+e[2]+e[3];  
  59.     cout<<"E{0]="<<E[0]<<endl;  
  60.     //cout<<"e1"<<e[i]<<endl;  
  61.     int n=0;  
  62.     while(E[n]>0)  
  63.     {  
  64.         n++;  
  65.         for(int i=0;i<4;i++)  
  66.         {  
  67.   
  68.             W[i][1]=W[i][1]+l*(d[i]-Y[i])*X[i][1];  
  69.             W[i][2]=W[i][2]+l*(d[i]-Y[i])*X[i][2];  
  70.             //cout<<W[i][1]<<endl<<W[i][2]<<endl;  
  71.             Y[i]=W[i][0]*X[i][0]+W[i][1]*X[i][1]+W[i][2]*X[i][2];  
  72.             if(Y[i]>=0)  
  73.                 Y[i]=1;  
  74.             else  
  75.                 Y[i]=-1;  
  76.   
  77.             e[i]=abs(d[i]-Y[i]);  
  78.             //cout<<"e"<<e[i]<<endl;  
  79.         }  
  80.   
  81.         E[n]=e[0]+e[1]+e[2]+e[3];  
  82.         /*cout<<"Yi"<<Y[i]<<endl; 
  83.         cout<<"e["<<i<<"]="<<e[i]<<endl;*/  
  84.         cout<<"E["<<n<<"]="<<E[n]<<endl;  
  85.   
  86.     }  
  87.     cout<<"W[]="<<endl;  
  88.     for(int i=0;i<4;i++)  
  89.     {  
  90.         for(int j=0;j<3;j++)  
  91.             cout<<W[i][j]<<" ";  
  92.     cout<<endl;  
  93.     }  
  94.     //E=e[0]+e[1]+e[2]+e[3];  
  95.     cout<<"ok"<<endl;  
  96.     /*IplImage *test=cvCreateImage(cvSize(400,400),IPL_DEPTH_16U,0); 
  97.     Mat mtx(test);*/  
  98.     Mat test(400,400,CV_8UC3,Scalar(130,240,205));//3通道图像  
  99.     line(test,Point(20,400-20),Point(20,0),Scalar(0));//因为mat型图像的原点在右上角,所以比较麻烦,要通过计算转换  
  100.     line(test,Point(20,400-20),Point(400,400-20),Scalar(0));  
  101.     for(int i=0;i<10;i++)  
  102.     {  
  103.         line(test,Point(20*(i+1),380-20*E[i]),Point(20*(i+2),380-20*E[i+1]),Scalar(220,0,150));  
  104.     }  
  105.   
  106.     /*for(int i=0;i<10;i++) 
  107.     { 
  108.     line(test,Point(20*(i+1),20*E[i]),Point(20*(i+2),20*E[i+1]),Scalar(255)); 
  109.     }*/  
  110.   
  111.     // Display the test image  
  112.     namedWindow("E Image");  
  113.     imshow("E Image",test);  
  114.     imwrite("test.bmp",test);  
  115.     waitKey();  
  116.     return 0;  
  117. }  
报告:

1、            题目:

双输入单输出系统:

                 x1(1)=1                   x2(1)=1                        d(1)=1

                 x1(2)=-0.5              x2(2)=-1                       d(2)=-1

                 x1(3)=3                  x2(3)=1                        d(3)=1

                 x1(4)=-2                 x2(4)=-1                       d(4)=-1  

       建立一个感知器网络,实现上述样本的分类。

        计算出相应的网络权值矩阵W

2、            运算结果:

图1 实现误差输出,得出所求权值矩阵,并对样本实现分类:

图2 用opencv2的画线及画点函数实现样本分类及画出误差变化曲线。

3、            实现步骤及对以上结果的说明:

算法部分:

①初始化:建立一个神经元的感知器,开关函数采用  函数

   W阵的初值随机为[6,0.5,0.5],即b=6;步长为0.1.

        

②对网络施加四组输入, 计算感知器的输出

③计算误差:允许误差为E=0

       当E<0,则退出,网络训练结束,当E>=0时:

④调节网络权值系数

⑤令:n=n+1,转步骤2。

画图部分:

主要采用opencv2画线函数line(),画点函数circle()。

4、核心代码及说明:

while(E[n]>0)  //E[n]存储每一次循环的总误差,当总误差大于零,进行循环

    {

        n++;

        for(int i=0;i<4;i++)

        {

            W[1]=W[1]+l*(d[i]-Y[i])*X[i][1];//调节网络权值系数

            W[2]=W[2]+l*(d[i]-Y[i])*X[i][2];

            Y[i]=W[0]*X[i][0]+W[1]*X[i][1]+W[2]*X[i][2];

            if(Y[i]>=0)

                Y[i]=1;

            else

                Y[i]=-1;

            e[i]=abs(d[i]-Y[i]); //e[i]存储单个样本误差

        }

        E[n]=e[0]+e[1]+e[2]+e[3];//每次循环计算一次总误差

cout<<"E["<<n<<"]="<<E[n]<<endl;

}

///进行分类

for(int i=0;i<4;i++)

{

     if(Y[i]==1)

         cout<<"第"<<i<<"组属于第一类"<<endl;

     if(Y[i]==-1)

         cout<<"第"<<i<<"组属于第二类"<<endl;

}

4、            总结

通过C++编程实现感知器学习,我对其的原理理解更深刻了,只有通过一次次修改代码和查阅资料才知道自己对算法的些地方存在错误的认识,再不断改进自己的算法。
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值