感知机算法笔记及其matlab实现

定义:

感知机是二类分类的线性模型,其输入为实例的特征向量,输出为实例的类别,取+1和-1二值。感知机对应于输入空间(特征空间)中将实例划分为正负两类的超平面,属于判别模型。感知机学习旨在求出将训练数据进行线性划分的分离超平面,为此,导入基于误分类的损失函数,利用梯度下降法对损失函数进行极小化,求得感知机模型。

感知机数学模型:

在这里,sign(x)是一个符号函数,w*x+b,实际上是超平面,我们将我们有的数据假设是三维,那就是(x1,x2,x3),代入此式,理所应当,w应该就是一个1*3的矩阵,而x应该是一个3*1的矩阵。他们经过矩阵运算得到的结果然后加上参数b,就可以得到一个数值。

我们将这个数值送入符号函数,如果这个样本在该超平面上方,那么w*x+b的值应该是大于零,于是符号函数的输出即为+1,相反,若是该样本在w*x+b下方,那么送入符号函数的值应该是小于零,这样感知机输出的模型就应该是-1.

于是我们借助符号函数的这一特性实际完成了二分类的功能。

而我们的目的,显而易见就是让计算机去学习得到这个w*x+b。

在w*x+b这个超平面中,实际上未知的就是参数w和参数b。

对于w,它实际上是一个矩阵,如果样本数据是n维,那么他就为一个1*n的矩阵。

损失函数:

我们将L作为损失函数。

由上面的理论我们可以知道,如果w*x+b>0,与之对应的输出y也将为+1,当w*x+b<0,与之对应的输出y也将为-1,所以在正常情况下,y*(w*x+b)永远为正值,只有当该超平面判断样本点发生错误时,y*(w*x+b)才会小于0,这时我们取取相反数,得到我们的损失函数当然是大于零的。所以将所有的判断错误的样本求和就是我们整体的损失函数,显而易见,当超平面可以完全分开两类样本点事,损失函数就将等于0.

所以我们将问题转化为,如何使损失函数等于0。

梯度下降法:

在损失函数中,影响最终取值的两个变量分别为w与b,所谓梯度,就是使值下降的最快的方向。所以我们分别求对w和对b的偏导数,得到我们梯度更新的策略。

感知机算法笔记及其matlab实现_第1张图片

对单次梯度更新而言,可以去掉前面的累加符号。

于是得到梯度更新策略:

感知机算法笔记及其matlab实现_第2张图片

在这里为学习速率。

通过不断地迭代,直到上述损失函数降为0.

达成最后的目标。

算法总结:

感知机算法笔记及其matlab实现_第3张图片

根据上述总结的算法,进行matlab代码实现。

由于没有数据集,所以我选择自己去生成数据集。为了保证我的数据集线性可分,我采用2*x1+5*x2-3=0,这条直线,得到线性可分的两个数据集。画图如图所示:

感知机算法笔记及其matlab实现_第4张图片

数据集生成代码具体如下:

 

x=zeros(3,100);%产生一个全是0的矩阵,维度为3*100
temp1=0;i=1;
while(temp1~=50)
   t1=rand(1);
   t2=rand(1);
   if((2*t1+5*t2-3)>0)
   temp1=temp1+1;
   x(1,i)=t1;
   x(2,i)=t2;
   x(3,i)=1;
   i=i+1;
   end   
end%产生50个标记为1的数据集
temp1=0;i=1;
while(temp1~=50)
   t1=rand(1);
   t2=rand(1);
   if((2*t1+5*t2-3)<0)
   temp1=temp1+1;
   x(1,i+50)=t1;
   x(2,i+50)=t2;
   x(3,i+50)=-1;
   i=i+1;
   end   
end%产生50个标记为-1的数据集

我设置了两个while循环,用随机函数rand生成一对随机数,判断是否在2*x+5*y-3=0一侧,如果是,就保留,如果不是,就舍弃。直到有了100组数据,就跳出循环。

之后进行perceptron算法编程:

rowrank = randperm(size(x,2));  % size获得b的列数,randperm打乱各列的顺序
x= x(:,rowrank);              % 按照rowrank重新排列各列,注意rowrank的位置

x_sample=x(1:2,:);%提取x矩阵前两行作为样本
w=zeros(1,2);
w(1,1)=0;
w(1,2)=0;
b=0;learn_speed=0.2;
judge=0;
while(judge~=1)
judge=1;
for i=1:1:100
t=sign(w*x_sample(:,i)+b);
if(t*x(3,i)<=0)
w=w+learn_speed*x(3,i)*(x_sample(:,i)).';
b=b+learn_speed*x(3,i);
judge=0;
break;
end%梯度更新

    
end
end

最后得到理想的权值:

w:

b:

为方便做图,本实验采取的是二维数据,所以最后的超平面即为一条直线。

实验最终效果如图所示:

感知机算法笔记及其matlab实现_第5张图片

计算机很好的学习到了两类数据的分类。

完整代码如下:

clc;clear all;
%%  生成数据集
x=zeros(3,100);%产生一个全是0的矩阵,维度为3*100
temp1=0;i=1;
while(temp1~=50)
   t1=rand(1);
   t2=rand(1);
   if((2*t1+5*t2-3)>0)
   temp1=temp1+1;
   x(1,i)=t1;
   x(2,i)=t2;
   x(3,i)=1;
   i=i+1;
   end   
end%产生50个标记为1的数据集
temp1=0;i=1;
while(temp1~=50)
   t1=rand(1);
   t2=rand(1);
   if((2*t1+5*t2-3)<0)
   temp1=temp1+1;
   x(1,i+50)=t1;
   x(2,i+50)=t2;
   x(3,i+50)=-1;
   i=i+1;
   end   
end%产生50个标记为-1的数据集
%% Plot the figure
for i=1:1:50
figure(1)
scatter(x(1,i),x(2,i),'o');
hold on;
scatter(x(1,i+50),x(2,i+50),'x');
hold on;
end%散点图如图1所示
%% Perceptron算法

rowrank = randperm(size(x,2));  % size获得b的列数,randperm打乱各列的顺序
x= x(:,rowrank);              % 按照rowrank重新排列各列,注意rowrank的位置

x_sample=x(1:2,:);%提取x矩阵前两行作为样本
w=zeros(1,2);
w(1,1)=0;
w(1,2)=0;
b=0;learn_speed=0.2;
judge=0;
while(judge~=1)
judge=1;
for i=1:1:100
t=sign(w*x_sample(:,i)+b);
if(t*x(3,i)<=0)
w=w+learn_speed*x(3,i)*(x_sample(:,i)).';
b=b+learn_speed*x(3,i);
judge=0;
break;
end%梯度更新

    
end
end
%% 画图
figure(1)
hold on;
%plot([0,0.5],[0.1,0.1]);
plot([0,-b/w(1,1)],[-b/w(1,2),0]);

你可能感兴趣的:(算法,matlab,机器学习)