首先介绍简单的神经元模型 如下是感知器神经元模型以及I/O关系 单层感知器模型:顾名思义就是模仿人类的神经元学习,通过输入测试样本的数据,对建立的神经元模型不断修正,使得模型更加精确。单层感知器模型如图: 定义加权系数wij为第i个神经元到第j个神经元之间的连接值 图形解释: 对n=2的情况 分平面为两部分 当输入为n时以此类推 学习训练算法具体如下: 首先是对权值w和b值得修正,修正的方法如下: 训练步骤 1)对于所要解决的问题,确定输入向量 X,目标向量T,由此确定维数及网络结构参数,n,m;(m代表输出个数,n代表输入个数) 2) 参数w和b的初始化;(本程序采用产生-1—1之间的随机数进行w和b的初始化) 3)设定最大循环次数(T); 4)计算网络输出;oo[N][N] 5)检查输出矢量oo[N][N]与目标矢量T是否相同,如果相同或者误差满足要求,或以达最大循环次数,训练结束,否则转入6); 6)学习 并返回4)。 详细算法思路如下图:
我是用的输入向量和目标向量如下: 解释一下这两组数据的使用: 首先P是输入向量,(1,-1,2)代表第一组样本测试数据的三个输入,(0.5,1.1,3,-1)代表第一组样本的目标输出。(根据输出得出有四个神经元)本算法关键就是经过神经元的计算得出的的四个输出与目标输出进行对比记录误差,通过不断修正w,b使得误差越来越小。接下来P的一列与T的一列对应。总共四组样本。 这里写代码片
这里写代码片 #include<iostream> #include<stdio.h> #include <math.h> #include <stdlib.h> #include <float.h> #define N 100 using namespace std; int main() { int n,t,q,i,j,m,mm,nn,Q; double w[N][N]; double d,b[N]; t=0; //初置精度控制参数e,学习率a,精度控制为d=e+1; int T=1000;double e=0.1;//T为最大训练次数,e为控制参数 double a=0.01;/*学习速率a决定每一次循环训练中所产生的权值变化量。 大的学习速率可能导致系统的不稳定;但小的学习速率导致 较长的训练时间,可能收敛很慢,不过能保证网络的误差值不 跳出误差表面的低谷而最终趋于误差最小值。所以一般情况下 倾向于选取较小的学习速率以保证系统的稳定性。 学习速率的选取范围在0.01~0.8之间。*/ d=e+1; double o[N]={0}; double oo[N][N]={0};//计算网络输出 double ss[4][3]={1,-1,2,1.5,2,1,1.2,3,-1.6,-0.3,-0.5,0.9};//样本测试数据即输入向量 X double yy[4][4]={0.5,1.1,3,-1,3,-1.2,0.2,0.1,-2.2,1.7,-1.8,-1.0,1.4,-0.4,-0.4,0.6};//目标向量T cout<<"请键入输入个数:"<<endl; cin>>n; cout<<"请键入输出个数:"<<endl; cin>>m; cout<<"请键入样本个数:"<<endl; cin>>Q; //初始化权矩阵w,阈值向量b(产生-1—1之间的随机数进行w和b的初始化) for(mm=0;mm<m;mm++) { for(nn=0;nn<n;nn++) { w[mm][nn] = (double)((rand() % 101) * 0.01f*2-1); } b[mm]=(double)((rand() % 101) * 0.01f*2-1); } for(mm=0;mm<m;mm++) { cout<<"训练前的的权值为:"<<endl; for(nn=0;nn<n;nn++) { printf("%0.2f\t",w[mm][nn]); } cout<<endl; cout<<"训练前的阈值为:"<<endl; printf("%0.2f\n",b[mm]); } //单层感知器多输出,Q组样本,本测试数据中每个样本n=3个输入 while(d >= e && t<T ) { d=0; for(q=0;q<Q;q++)//第q组样本 { // d=0; for(i=0;i<m;i++)//第i个神经元进行计算:根据各个输入计算出这个神经元对应的一个输出总共是4个输出 { // d=0; oo[q][i]=0; for(j=0;j<n;j++)//对每个输入进行加权计算 { oo[q][i]+=w[i][j]*ss[q][j]; } oo[q][i]+=b[i];//默认为线性函数,计算输出oo[q][i]值:即第q组样本的第i个输出值 // oo[q][i]=f(oo[q][i]);非线性函数的映射 b[i]=b[i]+a*(yy[q][i]-oo[q][i]);//修改权矩阵w,阈值向量b for(j=0;j<n;j++) w[i][j]=w[i][j]+a*(yy[q][i]-oo[q][i])*ss[q][j]; d=d+(yy[q][i]-oo[q][i])*(yy[q][i]-oo[q][i]); /*进行调试的时候发现误差d越来越小,越接近规定的误差精度 说明程序思路正确。如果总是精度达不到要求,可以适当调整 学习率,并不一定学习率越小精度就越小*/ } } t++; } for(mm=0;mm<m;mm++) { cout<<"训练后的权值为:"<<endl; for(nn=0;nn<n;nn++) { printf("%0.2f\t",w[mm][nn]); } cout<<endl; cout<<"训练后的阈值为:"<<endl; printf("%0.2f\n",b[mm]); } if(t<T) cout<<"训练了:"<<t<<"次达到精度"<<endl; else cout<<"次数到达限制!"<<endl; return 0; }经过不断地循环测试修正w与b,最终本程序因为精度达到要求跳出循环。使得神经元模型的建立更加准确。因为本程序默认是线性响应函数:Y=WX+B;忽然想到数学中的线性回归方程,有神似之处啊~自己瞎想的,吼吼吼 最终,单层感知器将人工智能的想法完美的演绎了一下。通过数据不断测试,修正数学模型,已达到结果的准确。如果想明白他的应用之处,详情请等我把BP神经网络整理出来。里面有一个如何判断蚊子种类的例题,很贴近生活!