教程地址:http://ufldl.stanford.edu/tutorial/supervised/SoftmaxRegression/

logstic regression是二分类的问题,如果想要多分类,就得用softmax regression。

这节比较难理解的是cost function,实际上,cost function就是最大似然估计加上了个负号。

理论部分参考这位博主的博文:http://www.cnblogs.com/tornadomeet/archive/2013/03/22/2975978.html

要注意logistic regression和softmax regression之间的不同,在不同场合用不同的方法。

实验部分看了好久,一直不明白,一是因为matlab不熟悉,还有一方面是变量的维数一直没搞明白。

这位博主给出了代码的详细解释,还是懵懵懂懂:http://www.cnblogs.com/happylion/p/4225830.html

他的字体不容易看,我重新整理下,并加些注释。

我们首先展示下我们训练样本部分的图片和label:

  1. 1: images = loadMNISTImages('train-images.idx3-ubyte');%得到的images是一个784*60000的矩阵,意思是每一列是一幅28*28的图像展成了一列,
  1. 2: %一共有60000幅图像。
  1. 3: labels = loadMNISTLabels('train-labels.idx1-ubyte');
  1. 4: display_network(images(:,1:100)); % Show the first 100 images
  1. 5: disp(labels(1:10));

下面我们进行训练,首先我们定义一些softmax模型常量:

  1. 1: inputSize = 28 * 28; % Size of input vector (MNIST images are 28x28)
  1. 2: inputSize =inputSize +1;% softmx的输入还要加上一维(x0=1),也是θj向量的维度
  1. 3: numClasses = 10;     % Number of classes (MNIST images fall into 10 classes)
  1. 4: lambda = 1e-4; % Weight decay parameter
  2.  
  3. 导入训练样本数据
  1. 1: images = loadMNISTImages('train-images.idx3-ubyte');%得到的images是一个784*60000的矩阵,意思是每一列是一
  1. 2: %幅28*28的图像展成了一列,一共有60000幅图像。
  1. 3: labels = loadMNISTLabels('train-labels.idx1-ubyte');
  1. 4: labels(labels==0) = 10; % 因为这里类别是1,2..k,从0开始的,所以这里把labels中的0映射成10
  1. 5: 
  1. 6: inputData = images;
  1. 7: inputData = [ones(1,60000); inputData];%每个样本都要增加一个x0=1

初始化模型参数:

  1. 1: theta = 0.005 * randn(inputSize*numClasses, 1);

接下来也是最重要的一步就是:给定模型参数的情况下,求训练样本的softmax的cost function和梯度,即

  1. 1: [cost, grad] = softmax_regression_vec(theta,inputData ,labels,lambda );

接下来我们就要写softmax_regression_vec函数:

  1. 1: function [f,g] = softmax_regression_vec(theta, X,y,lambda ) 
  1. 2: %下面的ninputSize指数据有多少维(包括新加的x0=1这一维),也是θj向量的维度
  1. 3: %这里y1,2....到k,从1开始的
  1. 4:   m=size(X,2);%X每一列是一个样本,m是指有m个样本 
  1. 5:   n=size(X,1);  %n指代的前面说了
  1. 6:   theta=reshape(theta, n, []); %也就是把theta设置成这样矩阵:有inputSize行也就是n行,每一列是一个θj,有k列。这样的θ矩阵跟前面理论部分的θ矩阵不一样,存在
    %转置关系,为什么这样呢?这样这样的话在后面的reshape和矩阵A(:)这样的操作,方便,都是按列进行的,还原也方便。所以只好程序中出现的θ矩阵都是这样的,k列,跟理论部分的相反。
  1. 7:   % initialize objective value and gradient. 
  1. 8:   f = 0; 
  1. 9:   g = zeros(size(theta)); 
  1. 10:   h = theta'*X;%h是k行m列的矩阵,见图1.(之前一直不理解h矩阵是什么样的,看下图就明白了)
  1.  
  1. 1: a = exp(h); 
  1.  
  1. 2:  p = bsxfun(@rdivide,a,sum(a)); % sum(a)是一个行向量,每个元素是a矩阵的每一列的和。然后运用bsxfun(@rdivide,,)
  1.  
  1. 3:  %是a矩阵的第i列的每个元素除以 sum(a)向量的第i个元素。得到的p矩阵大小和图1一样,每个元素如图2.
  1.  
  1. 1: i = sub2ind(size(c), y',1:size(c,2)); %y',1:size(c,2)这两个向量必须同时是行向量或列向量
  1.  
  1. 2:   %因为我们接下来每一个样本xi对应的yi是几,就去找到p的每一列中,所对应的第几个元素就是要找的,如图4.首先使用sub2ind
  1.  
  1. 3:   %sub2ind: matlab中矩阵是按一列一列的存储的,比如A=[1 2 3;4 5 6]
  1.  
  1. 4: %那么A2)=4A(3)=2...而这个函数作用就是比如 sub2indsizeA),2,1)就是返回A的第2行第一列的元素存储的下标,因为
  1.  
  1. 5: %A2)=4,所以存储的下标是2,所以这里返回2.这里sub2indsizeA),2,1)的2,1也可以换成向量[a1,a2..],[b1,b2..]但是注意
  1.  
  1. 6: %这两个向量必须同时是行向量或列向量,而不能一个是行向量一个是列向量。所以返回的
  1.  
  1. 7: %第一个元素是A的第a1行第b1列的元素存储的下标,返回的第,二个元素是A的第a2行第b2列的元素存储的下标...i是一个向量,ci)得到的
  1.  
  1. 8: %向量的每一个元素就是p中每一列你前面要找的的元素。
  2.  
  3. 注:sub2ind(size(A),m,n)是得到Amn列这个元素的标号,具体参考:http://blog.csdn.net/djh512/article/details/6785975
    在上面的代码中,得到的是y(i)=j的元素所对应的标号。
  1.  
  1. 1: values = c(i); 
  1.  
  1. 2:  f = -(1/m)*sum(values)+ lambda/2 * sum(theta(:) .^ 2);  %这个就是cost function
  2.  
  3. 最后求梯度:
  1. 1: d = full(sparse(1:m,y,1)); %d为一个稀疏矩阵,有mk列(k是类别的个数),这个矩阵的(1y1))、(2y2))
  1. 2:   %....(m,y(m))位置都是1
  1. 3:   g = (1/m)*X*(p'-d)+ lambda * theta; %这个g和theta矩阵的结构一样。
  1. 4:   g=g(:); % 再还原成向量的形式,这里(:)和reshape都是按列进行的,所以里面位置并没有改变。
    注:sparse(i,j,s,m,n)构成一个稀疏矩阵,full则是把稀疏矩阵转为全矩阵。具体参考:http://blog.csdn.net/meng4411yu/article/details/8840612
    下面这段话我没看明白:

   我们想求梯度矩阵g,这里的g和θ=[θ1,θ2,…,θk]矩阵大小size一样(跟博客中的θ矩阵存在转置关系,之所有代码中这么做,是因为这样再把参数矩阵转成一个向量或转回去利用g(:)或reshape函数按列比较方面),

是n行k列的矩阵。n是θj或一个样本xi(包括截距1这一维)的维度大小,k是类别个数。m是样本个数。

  1.  

我们想用矢量编程来求g矩阵:

  1.  

我们有样本X(代码中每一列是一个样本,也即X为n行m列),那么g = (1/m).*X*(p'-d)即是。比如,X的第 i 行乘以(p'-d)的第 j 列就是X(i,j)的值。(正是这种行向量乘以列向量是对应元素相乘再相加就 完成了公式里的Σ,这也是矢量编程的核心)

ok,现在我们这个函数写完了,我们想验证下,我们写的这个求导数或着说梯度的这个公式正确不正确,我们还是用之前博客提到的用求导公式来验证,因为你求softmax模型某个参数的导数跟你输入的数据是什么、多少都没有关系,所以我们这有用一些简单的随意写得数据和label,然后随意取一个参数进行验证是不是正确,这些程序在前面已经有了,就不进行讲解了。

这段程序没跑过,有空跑跑看。

  1. 1: % DEBUG = true; % Set DEBUG to true when debugging.
  1. 2: DEBUG = false;
  1. 3: if DEBUG
  1. 4:     inputSize = 9;
  1. 5:     inputData = randn(8, 100);
  1. 7:     inputData = [ones(1,100);inputData];
  1. 8:     labels = randi(10, 100, 1);%从[1,100]中随机生成一个100*1的列向量
  1. 10: end
  1. 12: % Randomly initialise theta
  1. 13: theta = 0.005 * randn(inputSize*numClasses, 1);
  1. 1: [cost, grad] = softmax_regression_vec(theta,inputData ,labels,lambda );
  1. 2:                                     
  1. 3: if DEBUG
  1. 4:  numGrad = computeNumericalGradient( @(theta) softmax_regression_vec(theta,inputData ,labels,lambda) ,theta);
  1. 5: 
  1. 6:     % Use this to visually compare the gradients side by side
  1. 7:     disp([numGrad grad]);
  1. 8: 
  1. 9:     % Compare numerically computed gradients with those computed analytically
  1. 10:     diff = norm(numGrad-grad)/norm(numGrad+grad);
  1. 11:     disp(diff);
  1. 12:     % The difference should be small.
  1. 13:     % In our implementation, these values are usually less than 1e-7.
  1. 14: 
  1. 15:     % When your gradients are correct, congratulations!
  1. 16: end
  1.  
  1.  

UFLDL 教程学习笔记(三)的更多相关文章

  1. UFLDL 教程学习笔记(三)自编码与稀疏性

    UFLDL(Unsupervised Feature Learning and Deep Learning)Tutorial 是由 Stanford 大学的 Andrew Ng 教授及其团队编写的一套 ...

  2. UFLDL 教程学习笔记(四)主成分分析

    UFLDL(Unsupervised Feature Learning and Deep Learning)Tutorial 是由 Stanford 大学的 Andrew Ng 教授及其团队编写的一套 ...

  3. UFLDL 教程学习笔记(二)反向传导算法

    UFLDL(Unsupervised Feature Learning and Deep Learning)Tutorial 是由 Stanford 大学的 Andrew Ng 教授及其团队编写的一套 ...

  4. UFLDL 教程学习笔记(一)神经网络

    UFLDL(Unsupervised Feature Learning and Deep Learning)Tutorial 是由 Stanford 大学的 Andrew Ng 教授及其团队编写的一套 ...

  5. UFLDL 教程学习笔记(四)

    课程地址:http://ufldl.stanford.edu/tutorial/supervised/FeatureExtractionUsingConvolution/ 在之前的练习中,图片比较小, ...

  6. UFLDL 教程学习笔记(六)主成分分析

    教程:http://ufldl.stanford.edu/tutorial/supervised/MultiLayerNeuralNetworks/ 以及这篇博文,写的很清楚:http://blog. ...

  7. UFLDL 教程学习笔记(一)

    ufdl的新教程,从基础学起.第一节讲的是线性回归.主要目的是熟悉目标函数,计算梯度和优化. 按着教程写完代码后,总是编译出错,一查是mex的原因,实在不想整了. 这位博主用的是向量,比较简洁:htt ...

  8. UFLDL 教程学习笔记(二)

    课程链接:http://ufldl.stanford.edu/tutorial/supervised/LogisticRegression/ 这一节主要讲的是梯度的概念,在实验部分,比较之前的线性回归 ...

  9. 学习笔记(三)--->《Java 8编程官方参考教程(第9版).pdf》:第十章到十二章学习笔记

    回到顶部 注:本文声明事项. 本博文整理者:刘军 本博文出自于: <Java8 编程官方参考教程>一书 声明:1:转载请标注出处.本文不得作为商业活动.若有违本之,则本人不负法律责任.违法 ...

随机推荐

  1. bzoj 1823: [JSOI2010]满汉全席 && bzoj 2199 : [Usaco2011 Jan]奶牛议会 2-sat

    noip之前学的内容了,看到题竟然忘了怎么建图了,复习一下. 2-sat 大概是对于每个元素,它有0和1两种选择,必须选一个但不能同时选.这之间又有一些二元关系,比如x&y=1等等... 先把 ...

  2. 丁酉年六月十一ACM模拟赛

    似乎该写题解了.今天模拟ACM,10道题(本来还有2道被删了),9道都来自BZOJ,中间我做过2道.那么说,今天Solv.便大大增多了(但还是不如强大的Amphetamine). 题单及一句话题解如下 ...

  3. kernel-init-bash

    https://www.kernel.org/doc/Documentation/kernel-parameters.txthttp://unix.stackexchange.com/question ...

  4. 四、Linux学习之文件处理命令

    1.建立目录:mkdir 格式:mkdir –p [目录名] -p     递归创建目录 注意事项: 如果是创建单个目录直接mkdir [目录名就可以] 如果是创建一个目录下的目录也就是递归创建目录请 ...

  5. Nlog写日志到数据库

    https://github.com/nlog/NLog/wiki/Database-Target

  6. [USACO4.3]逢低吸纳Buy Low, Buy Lower

    https://daniu.luogu.org/problemnew/show/2687 求方案数: if(f[j]+1==f[i] && a[j]>a[i]) s[i]+=s[ ...

  7. 2017 清北济南考前刷题Day 2 morning

    期望得分:100+30+60=190 实际得分:100+30+30=160 T1 最优方案跳的高度一定是单调的 所以先按高度排序 dp[i][j] 跳了i次跳到j 枚举从哪儿跳到j转移即可 #incl ...

  8. SpringBoot 线程池配置 实现AsyncConfigurer接口方法

      目的是:  通过实现AsyncConfigurer自定义线程池,包含异常处理  实现AsyncConfigurer接口对异常线程池更加细粒度的控制 *a) 创建线程自己的线程池  b) 对void ...

  9. 简单理解 NP, P, NP-complete和NP-Hard

    P是一类可以通过确定性图灵机(以下简称 图灵机)在多项式时间(Polynomial time)内解决的问题集合. NP是一类可以通过非确定性图灵机( Non-deterministic Turing ...

  10. 20145226夏艺华 《Java程序设计》第5周学习总结

    教材学习内容总结 第八章 异常处理 语法与继承架构 使用 try.catch Java中所有信息都会被打包为对象,如果愿意,可以尝试(try)捕捉(catch)代表错误的对象后做一些处理 try{ . ...