(1)说说要解决的问题
这里只是运用BP感知器的一些知识,用delta法则方式解决一个简单的线性或者非线性可分问题,比如这里围绕的就是坐标系下的8个点,这8个点很明显的划分两类,现在要求解出一组权值来划分这两类点。8组点是自己假设的,为[1,0,1;2,1.5,1;-1,-1.5,1;-3,-5,1;0,2,0;1.5,2,0;-1,0,0],在坐标系下的可以看到为:
很显然也能看到可以有一条直线从中间穿过就能很好的把他们区分开来,为了简化随便编来的简化数据。
(2)关于梯度下降和delta法则的原理
这部分也看到了很多解释的很好的,也很容易理解,像该论坛许多都解释的很好,比如http://blog.youkuaiyun.com/acdreamers/article/details/27660519,自己也可以找找,好的。我想说重点是对于那个更新迭代的误差公式来源,也就是误差对权值w的求导最后等于一个乘式那块,理解这个好重要呀。
(3)算法的伪代码
下面这个图是我在《机器学习》这本书上截取下来的,在第四章人工神经网络(P68)那块,写到了伪代码,我就是照着这个伪代码写的:
(4)matlab代码:
%**********************函数说明***********************************
%****************BP网络下的梯度下降算法的实验原理***************************
%
%随便编的实验数据值:8组:x1,x2,t的值,为简单起见,让前四组为一个类型,后四组为一个类型
%[1,0,1;2,1.5,1;-1,-1.5,1;-3,-5,1;0,2,0;1.5,2,0;-1,0,0]
%
function ww = gradient_descent(training_example,eta)
[m,n] = size(training_example); %m--行,n--列
num_x = n-1; %输入量个数 ,最后一项是目标值,所以少一个
for i=1:num_x %初始化权值矩阵在(-1,1),这个相对较好
w(i) = 2*(rand()-0.5);
end
fault = 1;
while(fault>1e-5) %给定的判断条件
fault = 0;
delta_w(1:num_x) = 0; %初始化误差值
%----------------对于每一行数据----------------------------
for i=1:m
xx = training_example(i,1:num_x)'; %第i行的所有x值
output(i) = w*xx; %计算输出值
if output(i)>0 %如果输出大于0,让它等于1,这样误差为0,
output(i)=1;
else output(i)=0;
end
t = training_example(i,n); %第i行的目标值
for j=1:num_x
delta_w(j) = delta_w(j) + eta*(t-output(i))*training_example(i,j); %产生误差项
end
end
%---------------更新权值矩阵---------------------------
for j=1:num_x
w(j) = w(j) + delta_w(j);
end
%----------------根据新的权值矩阵计算一下目标函数的现在的输出out--------------------------
for i=1:m
out(i) = w*training_example(i,1:num_x)';
if out(i)>0 out(i)=1;
else out(i)=0;
end
end
%-------------------判断条件:所有的out值与所给的t一样------------------------------------
%------------------方法比较笨,就是一个一个比较,肯定有更好的结束条件,还没想好-------------
if ((out(1)==1)&&(out(2)==1)&&(out(3)==1)&&(out(4)==1)&&(out(5)==0)&&(out(6)==0)&&(out(7)==0)&&(out(8)==0))
fault=0; %条件符合了,结束
else fault=1; %没符合,继续运行
end
end
ww = w; %最后返回所得的权值矩阵
(5)实验结果
最后来看下实验的结果:在窗口中调用函数如下:
ww = gradient_descent(ss,0.1);plot(ss(1:4,1),ss(1:4,2),'*',ss(5:8,1),ss(5:8,2),'+')
hold on;k=[-5:0.1:5];p = -ww(1)/ww(2)*k;plot(k,p)
得到了如下的划分曲线(前提是你的相应的矩阵得正确输入进matlab工具箱中):
实验了几次,基本上都可以划分出来,虽然很简单,原理上是通用的,复杂的只是改一下判断规则、输入输出矩阵的格式等等即可。
好了,写的做的都比较简陋,随便看看吧!