• 关于模式识别作业——利用分类器实现手写数字识别


    数据库:MNIST  http://yann.lecun.com/exdb/mnist/
    编写分类器程序,要求:
    1)选用课上讲述过的分类器
    2)使用交叉验证法生成训练集及测试集,并以此为基础评价模型的泛化误差。
    3)总结影响分类器算法结果的因素。

    第一步:利用matlab对MNIST数据进行读取。

    -------------------------------------------------------------*****************************************************---------------------------------------------------------------------------

    插入:关于测试集和训练集

    训练集验证集测试集这三个名词在机器学习领域极其常见

    训练集

    作用:估计模型

    学习样本数据集,通过匹配一些参数来建立一个分类器。建立一种分类的方式,主要是用来训练模型的。

     测试集

    作用:检验最终选择最优的模型的性能如何

    主要是测试训练好的模型的分辨能力(识别率等)

    为何需要划分

    简而言之,为了防止过度拟合。如果我们把所有数据都用来训练模型的话,建立的模型自然是最契合这些数据的,测试表现也好。但换了其它数据集测试这个模型效果可能就没那么好了。总而言之训练集和测试集相同的话,模型评估结果可能比实际要好。 

    总结

    显然,training set是用来训练模型或确定模型参数的,如ANN中权值等; validation set是用来做模型选择(model selection),即做模型的最终优化及确定的,如ANN的结构;而 test set则纯粹是为了测试已经训练好的模型的推广能力。当然,test set这并不能保证模型的正确性,他只是说相似的数据用此模型会得出相似的结果。但实际应用中,一般只将数据集分成两类,即training set 和test set,大多数文章并不涉及validation set。

    一个典型的划分是训练集占总样本的50%,而其它各占25%,三部分都是从样本中随机抽取。

    ----------------------------------------------------------------------------------********************************************************--------------------------------------------------------------------- 

    mnist数据集原网站下载下来的格式无法直接打开,需要对mnist数据集下载之后解压,

    在 Windows 平台下解压这些文件时,操作系统会自动修改这些文件的文件名,比如会将倒数第二个短线-修改为.,也即 train-images-idx3-ubyte.gz 解压为train-images.idx3-ubyte(文件类型就自作主张地变成了idx3-ubyte)。.matlab要想对这些数据进行使用,就需要编写程序对数据进行读取。由网上查询matlab读取mnist数据集的程序如下:

    clear variables
    close all
    clc

    train_x_file=char('train-images.idx3-ubyte');%得到vector形式
    test_x_file=char('t10k-images.idx3-ubyte');%得到vector形式
    train_y_file=char('train-labels.idx1-ubyte');%得到vector形式
    test_y_file=char('t10k-labels.idx1-ubyte');%得到vector形式

    train_x=decodefile(train_x_file,'image');
    test_x=decodefile(test_x_file,'image');

    train_labels=decodefile(train_y_file,'label');
    test_labels=decodefile(test_y_file,'label');

    其中,decodefile.m函数为:

    %MNIST源文件下载地址http://yann.lecun.com/exdb/mnist/index.html
    %功能:将下载得到的二进制文件转换为10进制数据,提取像素数据和标签数据
    %适用:仅适用于MNIST数据集,修改后可适用于其他

    function output=decodefile(filename,type)
    %数据介绍如下,参考网址http://yann.lecun.com/exdb/mnist/index.html
    、fio=fopen(filename,'r');%原始文件中数据是以2进制存储的。
    a = fread(fio,'uint8');%以8进制方式读取源文件。虽然前几项是32bit的,但是图像像素数据是8bit的,所以此处用8bit处理。

    if strcmp(type,'image')
    output=a(17:end);%提取像素数据
    else if strcmp(type,'label')
    output=a(9:end);
    end
    end

    第二步:分类器分类

    按照北京理工大学高琪老师等讲授的《人工智能之模式识别》,一般分类器的实现分为三个步骤:分类器模型的建立、模型的训练、以及模板分类结果的预测。分别利用templateSVM、 fitcecoc、predict函数实现功能。

    补充:

    关于交叉验证法,此处采用折十交叉验证法,对训练集数据再次进行划分,分为十份,每次留一份作为验证集,其余九份为训练集,十次循环训练模型。最后用训练后的模型再次对测试集数据进行验证。

    完整程序如下所示:

    % svm.m
    clear variables
    close all
    clc

    train_x_file=char('train-images.idx3-ubyte');%得到vector形式
    test_x_file=char('t10k-images.idx3-ubyte');%得到vector形式
    train_y_file=char('train-labels.idx1-ubyte');%得到vector形式
    test_y_file=char('t10k-labels.idx1-ubyte');%得到vector形式

    train_x=decodefile(train_x_file,'image');
    test_x=decodefile(test_x_file,'image');

    train_labels=decodefile(train_y_file,'label');
    test_labels=decodefile(test_y_file,'label');

    % 如果想检验转化是否正确,可执行以下代码。
    train_images=reshape(train_x,28,28,60000);%reshape后的图像是放倒的
    train_images=permute(train_images,[2 1 3]);%对每张图像进行行列的转置处理

    test_images=reshape(test_x,28,28,10000);%reshape后的图像是放倒的
    test_images=permute(test_images,[2 1 3]);%对每张图像进行行列的转置处理

    train_labels=train_labels';
    test_labels=test_labels';

    %选取部分数据进行训练
    train_num = 500;
    test_num = 200;

    data_train = mat2vector(train_images(:,:,1:train_num),train_num);%图像转向量
    data_test = mat2vector(test_images(:,:,1:test_num),test_num);%mnist数据集图像为28*28
    train_labels=train_labels(:,1:train_num)';
    test_labels=test_labels(:,1:test_num)';

    %定义SVM分类器模板,采用线性核函数, 这里选用最简单的线性模型做演示;
    t = templateSVM('KernelFunction','linear');

    %交叉验证法
    [m,n] = size(data_train);
    indices = crossvalind('Kfold', m, 10);
    for i = 1 : 10
    % 获取第i份测试数据的索引逻辑值
    test = (indices == i);
    % 取反,获取第i份训练数据的索引逻辑值
    train = ~test;
    %1份测试,9份训练
    test_data = data_train(test,:);
    test_label = train_labels(test,:);

    train_data = data_train(train, :);
    train_label = train_labels(train, :);
    % 使用数据的代码
    svm_model = fitcecoc(train_data,train_label,'Learners',t);%训练模型,由于是多分类,不能直接调用fitcsvm
    end

    %不使用交叉验证法时训练模型
    % svm_model = fitcecoc(data_train,train_labels(1:train_num),'Learners',t);

    %利用测试集数据测试结果
    result = predict(svm_model,data_test);
    result = result.';
    fprintf('预测结果:');
    result(1:20)%取20个打印出来对比
    fprintf('真实分布:');
    test_labels(1:20)'
    acc = 0.;
    for i = 1:test_num
    if result(i)==test_labels(i)
    acc = acc+1;
    end
    end
    fprintf('精确度为:%5.2f%% ',(acc/test_num)*100);

    % mat2vector.m
    % 输入:图片数据(矩阵),样本个数
    % 函数作用:将图片组转化为行向量的组合,每个行向量作为一张图片的特征
    % 输出:样本数*图片像素数量大小的矩阵
    function [data_]= mat2vector(data,num)
    [row,col,~] = size(data);
    data_ = zeros(num,row*col);
    for page = 1:num
    for rows = 1:row
    for cols = 1:col
    data_(page,((rows-1)*col+cols)) = im2double(data(rows,cols,page));
    end
    end
    end
    end

    未使用交叉验证法时:

    使用交叉验证法时:

  • 相关阅读:
    敏捷软件开发之何为敏捷开发
    在DataGridView控件中实现冻结列分界线
    VS2010 Extension实践(2)
    如何使用MOQ进行单元测试
    把WPF Dialog转成WinForm Dialog需要注意的问题续
    浅析Web数据存储Cookie、UserData、SessionStorage、WebSqlDatabase
    VS2010 Extension实践(3)——实现自定义配置
    Url Rewrite 再说Url 重写
    团购网火了?
    从Component对象到CodeDom——舞动你的Code系列(1)
  • 原文地址:https://www.cnblogs.com/gujunjie-study-time/p/12781695.html
Copyright © 2020-2023  润新知