模式识别课上老师对神经网络做了详细的数学推导,回来自己又推了两遍,不难,也就是链式法则和求偏导,觉得没什么问题。但是总感觉缺了点什么。根据以前学习数字图像处理的经验:有些算法原理看着简单,实则只有自己造个轮子,才能真正掌握。于是决定手写一个简单的两层神经网络,实现二分类。
%author:harry
%date:2017.03.21
%将数据用矩阵的形式进行运算
% 使用多层感知器进行二分类
clear all
clc
X = zeros(200,2);
randn('seed',0);
t1 = linspace(1*4,(1+1)*4,100) + rand(1,100)*0.2 ;
for i = 1:100
X(i,:) = [i*sin(t1(i))/20,i*cos(t1(i))/20];
end
t2 = linspace(2*4,(2+1)*4,100) + rand(1,100)*0.2 ;
for j = 1:100
X(100+j,:) = [j*sin(t2(j))/20,j*cos(t2(j))/20];
end
D = [ones(100,1);zeros(100,1)];%标签
data = X ;
% 构建神经网络
% 初始化权重参数及各层偏导
w1 = 2*rand(2,90);
w2 = 2*rand(90,1);
%w1 = 0.5*ones(2,90);
%w2 = 0.5*ones(90,1);
delta_w1 = zeros(90,2);
delta_w2 = zeros(90,1);
ecoh = 0 ; % 迭代次数
while(1)
ecoh = ecoh + 1 ;
fprintf('第%d次迭代\n',ecoh);
%前向传播
l0 = data ;
l1 = sigmoid(l0*w1) ;
l2 = sigmoid(l1*w2) ;
l2_error = l2 - D ;
if(rem(ecoh,100))
disp(mean(abs(l2_error)));
end
l2_delta = l2_error .* desigmoid(l2) ;
l1_error = l2_delta * w2' ;
l1_delta = l1_error .* desigmoid(l1) ;
w2 = w2 - l1'*l2_delta ;
w1 = w1 - l0'*l1_delta ;
if ecoh >= 10000
break ;
end
end
figure(1)
%plot(X1,Y1,'ro',X2,Y2,'bo');%画出两类样本点
plot(X(1:100,1),X(1:100,2),'ro',X(101:200,1),X(101:200,2),'bo');
hold on;grid;
x = (-10:0.01:10);
y = (-10:0.01:10);
[xx,yy] = meshgrid(x,y);
[row,col] = size(xx);
z = zeros(row,col);
for i = 1:row
for j = 1:col
l0 = [xx(i,j),yy(i,j)] ;
l1 = sigmoid(l0*w1) ;
l2 = sigmoid(l1*w2) ;
if l2>=0.5
z(i,j) = 1 ;
else
z(i,j) = 0 ;
end
end
end
contour(xx,yy,z);
% 以下为测试部分
for i=1:10
[x,y]=ginput(1);
plot(x,y,'m*');
sample=[x,y];
hold all
l0 = [x,y];
l1 = sigmoid(l0*w1) ;
l2 = sigmoid(l1*w2) ;
if(l2 > 0.5)
disp('此点属于第一类');
else
disp('此点属于第二类');
end
end
两类不同的颜色表示不同的样本。下图是神经网络经过1000次迭代后生成的分界线。
然后利用学到的模型(其实就是一堆参数),对任意输入的十个点做分类:
这里只是简单的介绍了神经网络的基本功能,还有很多深入的坑有待以后讲解。比如训练过程中是否出现梯度消失?网络是否过拟合?… …