MATLAB实现感知器算法(MNIST数据集)

基于MOOC人工智能之模式识别的课程完成的第二次作业
MATLAB实现感知器算法(MNIST数据集)
MOOC地址:人工智能之模式识别

线性分类器之感知器模型,不能解决两两不可分问题。

感知器是一个通过输入加权和与阈值的比较来觉得是否激活输出的神经元模型,是一个线性分类器,输入的权构成了线性分类决策边界的权向量,激活输出的阈值θ就是分类决策边界的偏置量 w0。所以,经过数据规范化以后,得到了统一的求解目标,即
在这里插入图片描述
感知器的求解目标:MATLAB实现感知器算法(MNIST数据集)_第1张图片
感知器算法设定准则函数的依据很简单,就是最终分类器要能正确分类所有的样本,所以,感知器算法的准则函数 J 设定为所有错分样本的判别函数值之和,再乘以-1.因此,只要存在错分样本,准则函数值就是大于 0 的,只有当所有样本都正确地被分类了,准则函数才能取得极小值 0.如何求解呢?感知器算法采用了数值优化中经典的梯度下降法,即从一个任意的初始权向量 w0 出发,沿准则函数值下降最快的方向,也就是负梯度方向对权向量进行一步步修正,直到获得全局最优解为止。即第 k+1 步是在第 k 步获得的权向量基础上进行递推,得到第 k+1 步的权向量。其中ρ是每一次递推的调整步长。
我们把感知器算法的准则函数定义代入,就可以求得准则函数第 k 步时对w(k)的梯度,正好是所有错分样本的和乘以-1。因此感知器算法的权向量递推公式为
在这里插入图片描述
即每一步把当前被错分的样本加起来,在调整步长的控制下,去修正权向量。
要特别注意的是,修正的方向是“+”,这是因为负梯度和准则函数梯度中的负号相抵消的原因。
单样本修正的感知器算法,步骤为:
a、 设定初始权向量w0,k=0 ;
b、 从训练样本集中顺序抽取一个样本,将其规范化增广特征向量
代入到判别函数中计算;
c、 若分类正确返回到步骤 b,抽取下一个样本;
d、 若分类错误,修正权向量:
e、 返回到步骤 b,抽取下一个样本;直至训练样本集中所有样本均被正确分类。

数据集使用的是 matlab 版本,由四个文件组成,包含训练集 60000 个样本,测试集 10000 个样本;每个样本为 28*28 大小的矩阵,矩阵中元素为 double类型。标签为行向量,每个元素为相应数据的数字标签。
MATLAB实现感知器算法(MNIST数据集)_第2张图片

perceptionLearn.m文件,实现利用给定的训练数据和设定的学习参数,计算得到感知器的权向量 w。

%利用给定的训练数据和设定的学习参数,计算得到的感知机权向量w 
% 函数输入:数据(行向量),标签,学习率,终止轮次
% 输出:训练得到的权值向量
% 训练方法:单样本修正,学习率(步长)采用了固定值
  
function [w]=perceptionLearn(x,y,learningRate,maxEpoch)
    [rows,cols]=size(x);
    x=[x,ones(rows,1)];%行增广,返回一个row(行)*1的全1矩阵
    w=zeros(1,cols+1);%增广,返回一个1*cols(列)+1 的全0矩阵
    for epoch=1:maxEpoch%不可分情况下整体迭代轮次
        flag=true;%标志位真则训练完毕
        for sample=1:rows
            if sign(x(sample,:)*w')~=y(sample)%分类是否正确?错误则更新权值
                flag=false;
               %更新权值时使用标签来充当梯度方向的变量
                w=w+learningRate*y(sample)*x(sample,:);
            end
        end
        if flag==true
            break;
        end
    end
end

Properception.m 文件主要实现了数据集读入,感知器训练参数设置,获取训练及测试数据,标签转换,数据处理,感知器训练,测试及结果输出几个部分。

clear variables
clc
% 读取数据
load ('./test_images.mat');
load ('./test_labels.mat');
  
% 设定数据量
train_num = 1000;
test_num = 200;
% 临时变量以及各个感知器参数
j = 1;
lr = 0.01;%学习率
epoch =10;%设定训练多少轮
number = [4,8];%要取的数字组合,只能做二分类
% 提取数据中标签为任意组合的样本,共计200个
% 由于数据本身打乱过,因此可以直接取200个而不考虑样本不均衡问题
  
for i = 1:10000
    if test_labels1(i)==number(1)|| test_labels1(i)==number(2)
        data(:,:,j) = test_images(:,:,i);
        label(j) = test_labels1(i);%取相应标签
        j=j+1;
     if j>train_num+test_num
         break;
     end
    end
end
% A||B,或逻辑,如果A为真则A||B就为真,不会判断B的真假,但只能对标量操作, 
% 由于感知器输出结果仅为0、1,因此要将标签进行转换
% 本程序中,由于matlab计算不等式相对容易,因此没有对样本进行规范化
% 由于没有进行规范化,后面更新权值w需要借助标签,因此标签需要置-1和1
  
for k = 1:train_num+test_num
    if label(k)==number(1)
        label(k)=-1;
    end
    if label(k)==number(2)
        label(k)=1;
    end
end
data_ = mat2vector(data,train_num+test_num);%矩阵转向量
test_data = [data_(train_num+1:train_num+test_num,:),ones(test_num,1)];%这里对测试数据也进行增广变换
% test_data = data_(train_num+1:train_num+test_num,:);
% 训练权值
  
w=perceptionLearn(data_(1:train_num,:),label(1:train_num),lr,epoch);
% 测试(预测)
for k = 1:test_num
    if test_data(k,:)*w'>0
        result(k) = 1;
    else
        result(k) = -1;
    end
end
% 输出预测的准确率
acc = 0.;
for sample = 1:test_num
    if result(sample)==label(train_num+sample)
        acc = acc+1;
    end
end
fprintf('精确度为:%5.2f%%\n',(acc/test_num)*100);

设置训练样本1000,划分数字4和8,精确度能达到99.5%
MATLAB实现感知器算法(MNIST数据集)_第3张图片

你可能感兴趣的:(模式识别)