DeepLearning (四) 基于自编码算法与softmax回归的手写数字识别

【原创】Liu_LongPo 转载请注明出处

【CSDN】http://blog.csdn.net/llp1992

softmax 回归模型,是logistic 回归模型在多分类问题上的推广。关于logistic回归算法的介绍,前面博客已经讲得很清楚,详情可以参考博客

机器学习实战ByMatlab(五)Logistic Regression

在logistic回归模型中,我们的激励函数sigmoid的输入为:

z=θ0x0+θ1x1+θ2x2+...+θnxn

则可以得到假设函数为:

hθ(x)=g(z)=11+e?θTx

其中 g 为 sigmoid 函数。

因此,我们得到判断,当 z 的值大于0, h 的值大于0.5,此时我们判断 x 属于正类(举个例子),当 z 的值小于0.5 ,此时 h 的值小于0.5,我们判断 x 属于反类。

此时得到的代价函数为:

J(θ)=?1m[∑i=1my(i)loghθx(i)+(1?y(i))log(1?hθx(i))]

只要最小化代价函数 J 就能够得到最优的模型参数 θ 。

对于二分类来说,我们只需要一组模型参数 θ 就可以对数据进行分类。

在多分类问题中,我们的 y(i) 值就不在只是0或者1,它可以是2,3,4等等,此时我们就得为每个模型都分配一组模型参数 θ1,θ2,...,θn ,假设现在依旧是2个分类,我们对假设函数改造一下:

hθ(x)=1eθT1x+eθT2x[eθT1xeθT2x]=[p1p2]

其中,θ1 代表分类1的模型参数, θ2 代表分类2的模型参数, 那么此时我们的假设函数 h 得到的是 p1,p2,这是两个大于0,小于1的值,分别代表当前输入数据 x 属于两个分类的概率。依照最大似然算法,我们选取概率最大的那个作为我们的分类结果。

这就是softmax回归的最简单模式。

K个模型的softmax回归算法

对于输入训练集 {(x(1),y(1)),...(x(m),y(m))} , 我们有类标签 y(i)∈{1,2,...,k} , 对于每个输入数据 x ,我们都可以得到它属于每个类别的概率 p(y=j|x) ,此时得到假设函数如下:

hθ(x(i))=??????p(y(i)=1|x(i);θ)p(y(i)=2|x(i);θ)...p(y(i)=k|x(i);θ)??????=1∑kj=1eθTjx(i)???????eθT1x(i)eθT2x(i)...eθTkx(i))???????

此时的代价函数为:

J(θ)=?1m[1{y(i)=j}logeθTjx(i)∑kl=1eθTlx(i)]+λ2∑i=1k∑j=0nθ2ij

代价函数的导数为:

ΔθjJ(θ)=?1m∑i=1m[x(i)(1{y(i)=j?p(y(i)=j|x(i);θ)})]

该到一般用于我们对参数进行迭代求解。

自我学习

我们平常进行算法训练所需要的标注数据比较少,而未标注数据比价多。自学习算法就是一种能从大量的为标注数据中学习得到数据的特征,并与以标注数据结合进行算法训练,从而得到更加准确的分类效果。

在一些拥有大量未标注数据和少量的已标注数据的场景中,上述思想可能是最有效的。即使在只有已标注数据的情况下(这时我们通常忽略训练数据的类标号进行特征学习),以上想法也能得到很好的结果。

自我学习步骤

1.利用无标签数据进行非监督特征学习,训练稀疏编码器,得到参数 W 和 b

2.将有标签数据通过学习到的稀疏编码器,得到更加能够代表数据的激活量 a

3.用激活量替代{(x(i),y(i))}→{a(i),y(i)}或者级联 {(x(i),y(i))}→{((x(i),a(i)),y(i))} 生成分类器的训练数据训练分类器

4.测试数据 xtest 经过稀疏编码器得到激活值 atest ,并将 atest 或者 (atest,xtest) 送到分类器中进行预测

如下:输入数据为6维,运用自编码算法学习到3维特征,也就是激活值,再下面的网络后面再加上softmax回归模型,便组成了基于自学习网络的softmax回归。

手写数字识别

前面的博客

DeepLearning(二) 自编码算法与稀疏性理解与实战

中已经介绍了如何实现自编码算法从未标注数据中学习数据的内在特征。假如,我们现在有一个无标注的训练数据集,这里使用的是手写识别库 MNIST ,我们使用的5-9作为无标注的数据进行特征学习,训练我们的自动编码器,得到网络的模型参数 W(1),b(1),W(2),b(2) , 这部分属于无监督学习,目的就是学习得到网络模型参数,从而得到自编码学习网络。

上面说到,我们已经用无标签数据训练得到一个可以使用的自编码学习网络,接着我们将从有便签数据 0-4 (其中0作为10)中选取一部分作为softmax模型的训练数据,另外的部分作为模型测试数据。

这里我们选取一般的有标签数据作为训练数据,首先将训练数据输入到上面学习到的自编码算法网络进行前向传输,得到输入数据的特征,也就是我们自编码学习网络隐藏层的激活值 a ,然后我们将学习得到的特征替换原来的输入数据,即 {(x(i),y(i))}→{a(i),y(i)} , 然后将得到的新输入数据输入到softmax回归模型进行训练。

测试模型时,同样将测试数据输入到自编码算法网络进行前向传输得到激活值,然后再将激活值输入到softmax回归模型,判断模型输输出值与标签值的差异即可判断模型误差。

Matlab 代码

自编码网络学习

首先,我们先要训练自编码网络,详细训练代码可以参考博客

DeepLearning(二) 自编码算法与稀疏性理解与实战

中的 sparseAutoencoderCost.m 这里调用这个代码进行训练,优化方法使用 lbfgs 算法。如下:

addpath minFunc/
options.Method = ‘lbfgs‘;
options.maxIter = 400;
options.display = ‘on‘;
visibleSize = inputSize;
[opttheta, cost] = minFunc( @(p) sparseAutoencoderCost(p, ...
                                   visibleSize, hiddenSize, ...
                                   lambda, sparsityParam, ...
                                   beta, unlabeledData), ...
                              theta, options);

前向传输

自编码网络学习完成之后,我们先进行前向传输,获得训练数据以及测试数据的学习特征:

trainFeatures = feedForwardAutoencoder(opttheta, hiddenSize, inputSize, ...
                                       trainData);

testFeatures = feedForwardAutoencoder(opttheta, hiddenSize, inputSize, ...
                                       testData);

前向传输 feedForwardAutoencoder 的核心代码如下:

activation = sigmoid(bsxfun(@plus,W1 * data,b1)) ;

这里的隐藏层神经元个数为200个。

softmax 回归模型训练

softmaxModel = struct;
options.maxIter = 100;
lambda = 1e-4;
numClasses = 5;
inputData = trainFeatures;
labels = trainLabels ;
inputSize = hiddenSize;
softmaxModel = softmaxTrain(inputSize, numClasses, lambda, inputData, labels, options);

softmax 回归模型训练函数 softmaxTrain.m 需要实现 softmax 回归的代价函数 softmaxCost.m ,其核心代码如下:

M = theta * data;
M = exp(bsxfun(@minus,M,max(M,[],1)));
H = bsxfun(@rdivide,M,sum(M));
cost = - sum(sum((groundTruth .* log(H)))) / size(data,2) + lambda * sum(sum(theta.^2)) / 2 ;
thetagrad = - ((groundTruth - H)) * data‘ /size(data,2) +lambda * theta;

这里解释下这段代码:

M = exp(bsxfun(@minus,M,max(M,[],1)));

softmax 回归模型中的假设函数为:

hθ(x(i))=??????p(y(i)=1|x(i);θ)p(y(i)=2|x(i);θ)...p(y(i)=k|x(i);θ)??????=1∑kj=1eθTjx(i)???????eθT1x(i)eθT2x(i)...eθTkx(i))???????

其中,我们将输入数据 x 与模型参数 θ 相乘之后,还将其进行指数计算 eθT2x(i) , 此时很容易由于 θT2x(i) 较大从而导致 eθT2x(i) 过大而出现 overflows 的情况。由于softmax回归模型的特点:参数冗余。

也就是说 eθT2x(i)?a ,其中 a 为常数,并不会由什么影响,所以将每一列的 θT2x(i) 都减去该列的最大值,既不会产生什么影响,又可以防止 overflows 情况的出现。

模型测试

模型训练完之后,我们运用有标签数据进行测试,代码如下:

[Val , pred] = max(theta*data);

如果单纯使用输入数据训练softmax回归模型,模型需要训练100次,而且最终的测试准确度为 : 93.27%。

如果先使用无标签数据训练自编码网络,再进行softmax回归模型训练,softmax回归算法只需迭代 54 次就收敛,而且测试准确度为 98.33%,因此可见我们的自编码网络学习到的特征比原来的输入数据更具代表性,这也就是传统训练方法与深度学习训练方法的差异。

训练过程的代码如下:


clc
clear 

inputSize  = 28 * 28;
numLabels  = 5;
hiddenSize = 200;
sparsityParam = 0.1; % desired average activation of the hidden units.
                     % (This was denoted by the Greek alphabet rho, which looks like a lower-case "p",
                     %  in the lecture notes).
lambda = 3e-3;       % weight decay parameter
beta = 3;            % weight of sparsity penalty term
maxIter = 400;

% Load MNIST database files
mnistData   = loadMNISTImages(‘train-images.idx3-ubyte‘);
mnistLabels = loadMNISTLabels(‘train-labels.idx1-ubyte‘);

% Set Unlabeled Set (All Images)
% Simulate a Labeled and Unlabeled set
labeledSet   = find(mnistLabels >= 0 & mnistLabels <= 4);
unlabeledSet = find(mnistLabels >= 5);

numTrain = round(numel(labeledSet)/2);
trainSet = labeledSet(1:numTrain);
testSet  = labeledSet(numTrain+1:end);

unlabeledData = mnistData(:, unlabeledSet);

trainData   = mnistData(:, trainSet);
trainLabels = mnistLabels(trainSet)‘ + 1; % Shift Labels to the Range 1-5

testData   = mnistData(:, testSet);
testLabels = mnistLabels(testSet)‘ + 1;   % Shift Labels to the Range 1-5

% Output Some Statistics
fprintf(‘# examples in unlabeled set: %d\n‘, size(unlabeledData, 2));
fprintf(‘# examples in supervised training set: %d\n\n‘, size(trainData, 2));
fprintf(‘# examples in supervised testing set: %d\n\n‘, size(testData, 2));

%  Randomly initialize the parameters
theta = initializeParameters(hiddenSize, inputSize);

addpath minFunc/
options.Method = ‘lbfgs‘;
options.maxIter = 400;
options.display = ‘on‘;
visibleSize = inputSize;
[opttheta, cost] = minFunc( @(p) sparseAutoencoderCost(p, ...
                                   visibleSize, hiddenSize, ...
                                   lambda, sparsityParam, ...
                                   beta, unlabeledData), ...
                              theta, options);
% Visualize weights
W1 = reshape(opttheta(1:hiddenSize * inputSize), hiddenSize, inputSize);
display_network(W1‘);

trainFeatures = feedForwardAutoencoder(opttheta, hiddenSize, inputSize, ...
                                       trainData);

testFeatures = feedForwardAutoencoder(opttheta, hiddenSize, inputSize, ...
                                       testData);

%% STEP 4: Train the softmax classifier

softmaxModel = struct;
options.maxIter = 100;
lambda = 1e-4;
numClasses = 5;
inputData = trainFeatures;
labels = trainLabels ;
inputSize = hiddenSize;
softmaxModel = softmaxTrain(inputSize, numClasses, lambda, inputData, labels, options);

%%======================================================================
%% STEP 5: Testing 

[pred] = softmaxPredict(softmaxModel, testFeatures);
% Classification Score
fprintf(‘Test Accuracy: %f%%\n‘, 100*mean(pred(:) == testLabels(:)));
时间: 2025-01-04 01:53:36

DeepLearning (四) 基于自编码算法与softmax回归的手写数字识别的相关文章

C#中调用Matlab人工神经网络算法实现手写数字识别

手写数字识别实现 设计技术参数:通过由数字构成的图像,自动实现几个不同数字的识别,设计识别方法,有较高的识别率 关键字:二值化  投影  矩阵  目标定位  Matlab 手写数字图像识别简介: 手写阿拉伯数字识别是图像内容识别中较为简单的一个应用领域,原因有被识别的模式数较少(只有0到9,10个阿拉伯数字).阿拉伯数字笔画少并且简单等.手写阿拉伯数字的识别采用的方法相对于人脸识别.汉字识别等应用领域来说可以采用更为灵活的方法,例如基于规则的方法.基于有限状态自动机的方法.基于统计的方法和基于神

使用AI算法进行手写数字识别

人工智能 ??人工智能(Artificial Intelligence,简称AI)一词最初是在1956年Dartmouth学会上提出的,从那以后,研究者们发展了众多理论和原理,人工智能的概念也随之扩展.由于人工智能的研究是高度技术性和专业的,各分支领域都是深入且各不相通的,因而涉及范围极广 . 人工智能的核心问题包括建构能够跟人类似甚至超越人类的推理.知识.学习.交流.感知.使用工具和操控机械的能力等,当前人工智能已经有了初步成果,甚至在一些影像识别.语言分析.棋类游戏等等单方面的能力达到了超越

Python 手写数字识别-knn算法应用

在上一篇博文中,我们对KNN算法思想及流程有了初步的了解,KNN是采用测量不同特征值之间的距离方法进行分类,也就是说对于每个样本数据,需要和训练集中的所有数据进行欧氏距离计算.这里简述KNN算法的特点: 优点:精度高,对异常值不敏感,无数据输入假定 缺点:计算复杂度高,空间复杂度高 适用数据范围:数值型和标称型(具有有穷多个不同值,值之间无序)    knn算法代码: #-*- coding: utf-8 -*- from numpy import * import operatorimport

基于Numpy的神经网络+手写数字识别

基于Numpy的神经网络+手写数字识别 本文代码来自Tariq Rashid所著<Python神经网络编程> 代码分为三个部分,框架如下所示: # neural network class definition class neuralNetwork: # initialise the neural network def __init__(): pass # train the neural network def train(): pass # query the neural netwo

【转】机器学习教程 十四-利用tensorflow做手写数字识别

模式识别领域应用机器学习的场景非常多,手写识别就是其中一种,最简单的数字识别是一个多类分类问题,我们借这个多类分类问题来介绍一下google最新开源的tensorflow框架,后面深度学习的内容都会基于tensorflow来介绍和演示 请尊重原创,转载请注明来源网站www.shareditor.com以及原始链接地址 什么是tensorflow tensor意思是张量,flow是流. 张量原本是力学里的术语,表示弹性介质中各点应力状态.在数学中,张量表示的是一种广义的"数量",0阶张量

KNN分类算法实现手写数字识别

需求: 利用一个手写数字"先验数据"集,使用knn算法来实现对手写数字的自动识别: 先验数据(训练数据)集: ?数据维度比较大,样本数比较多. ? 数据集包括数字0-9的手写体. ?每个数字大约有200个样本. ?每个样本保持在一个txt文件中. ?手写体图像本身的大小是32x32的二值图,转换到txt文件保存后,内容也是32x32个数字,0或者1,如下: 数据集压缩包解压后有两个目录:(将这两个目录文件夹拷贝的项目路径下E:/KNNCase/digits/) ?目录trainingD

NN:神经网络算法进阶优化法,进一步提高手写数字识别的准确率—Jason niu

上一篇文章,比较了三种算法实现对手写数字识别,其中,SVM和神经网络算法表现非常好准确率都在90%以上,本文章进一步探讨对神经网络算法优化,进一步提高准确率,通过测试发现,准确率提高了很多. 首先,改变之一: 先在初始化权重的部分,采取一种更为好的随机初始化方法,我们依旧保持正态分布的均值不变,只对标准差进行改动, 初始化权重改变前, def large_weight_initializer(self): self.biases = [np.random.randn(y, 1) for y in

【机器学习】k-近邻算法应用之手写数字识别

上篇文章简要介绍了k-近邻算法的算法原理以及一个简单的例子,今天再向大家介绍一个简单的应用,因为使用的原理大体差不多,就没有没有过多的解释. 为了具有说明性,把手写数字的图像转换为txt文件,如下图所示(三个图分别为5.6.8): 要使用k-近邻算法,需要有足够的样本数据和测试数据,我放到了两个文件夹里(trainingDigits和testDigits),可以在这里(http://pan.baidu.com/s/1i3osO7N)下载使用 这里,每个数字有32X32个0或1,可以认为是一个维度

简单的神经网络算法-手写数字识别

本文通过BP神经网络实现一个简单的手写识别系统. 一.基础知识 1环境 python2.7 需要numpy等库 可利用sudo apt-get install python-安装 2神经网络原理 http://www.hankcs.com/ml/back-propagation-neural-network.html 讲的特别清楚,本实验过程中涉及矩阵运算都用numpy库的函数 3.js的基础知识 http://www.w3school.com.cn/tags/html_ref_canvas.a