UFLDL 教程学习笔记(三)
教程地址: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: images = loadMNISTImages('train-images.idx3-ubyte');%得到的images是一个784*60000的矩阵,意思是每一列是一幅28*28的图像展成了一列,
- 2: %一共有60000幅图像。
- 3: labels = loadMNISTLabels('train-labels.idx1-ubyte');
- 4: display_network(images(:,1:100)); % Show the first 100 images
- 5: disp(labels(1:10));
下面我们进行训练,首先我们定义一些softmax模型常量:
- 1: inputSize = 28 * 28; % Size of input vector (MNIST images are 28x28)
- 2: inputSize =inputSize +1;% softmx的输入还要加上一维(x0=1),也是θj向量的维度
- 3: numClasses = 10; % Number of classes (MNIST images fall into 10 classes)
- 4: lambda = 1e-4; % Weight decay parameter
- 导入训练样本数据
- 1: images = loadMNISTImages('train-images.idx3-ubyte');%得到的images是一个784*60000的矩阵,意思是每一列是一
- 2: %幅28*28的图像展成了一列,一共有60000幅图像。
- 3: labels = loadMNISTLabels('train-labels.idx1-ubyte');
- 4: labels(labels==0) = 10; % 因为这里类别是1,2..k,从0开始的,所以这里把labels中的0映射成10
- 5:
- 6: inputData = images;
- 7: inputData = [ones(1,60000); inputData];%每个样本都要增加一个x0=1
初始化模型参数:
- 1: theta = 0.005 * randn(inputSize*numClasses, 1);
接下来也是最重要的一步就是:给定模型参数的情况下,求训练样本的softmax的cost function和梯度,即
- 1: [cost, grad] = softmax_regression_vec(theta,inputData ,labels,lambda );
接下来我们就要写softmax_regression_vec函数:
- 1: function [f,g] = softmax_regression_vec(theta, X,y,lambda )
- 2: %下面的n和inputSize指数据有多少维(包括新加的x0=1这一维),也是θj向量的维度
- 3: %这里y是1,2....到k,从1开始的
- 4: m=size(X,2);%X每一列是一个样本,m是指有m个样本
- 5: n=size(X,1); %n指代的前面说了
- 6: theta=reshape(theta, n, []); %也就是把theta设置成这样矩阵:有inputSize行也就是n行,每一列是一个θj,有k列。这样的θ矩阵跟前面理论部分的θ矩阵不一样,存在
%转置关系,为什么这样呢?这样这样的话在后面的reshape和矩阵A(:)这样的操作,方便,都是按列进行的,还原也方便。所以只好程序中出现的θ矩阵都是这样的,k列,跟理论部分的相反。
- 7: % initialize objective value and gradient.
- 8: f = 0;
- 9: g = zeros(size(theta));
- 10: h = theta'*X;%h是k行m列的矩阵,见图1.(之前一直不理解h矩阵是什么样的,看下图就明白了)
- 1: a = exp(h);
- 2: p = bsxfun(@rdivide,a,sum(a)); % sum(a)是一个行向量,每个元素是a矩阵的每一列的和。然后运用bsxfun(@rdivide,,)
- 3: %是a矩阵的第i列的每个元素除以 sum(a)向量的第i个元素。得到的p矩阵大小和图1一样,每个元素如图2.
- 1: i = sub2ind(size(c), y',1:size(c,2)); %y',1:size(c,2)这两个向量必须同时是行向量或列向量
- 2: %因为我们接下来每一个样本xi对应的yi是几,就去找到p的每一列中,所对应的第几个元素就是要找的,如图4.首先使用sub2ind
- 3: %sub2ind: 在matlab中矩阵是按一列一列的存储的,比如A=[1 2 3;4 5 6]
- 4: %那么A(2)=4,A(3)=2...而这个函数作用就是比如 sub2ind(size(A),2,1)就是返回A的第2行第一列的元素存储的下标,因为
- 5: %A(2)=4,所以存储的下标是2,所以这里返回2.这里sub2ind(size(A),2,1)的2,1也可以换成向量[a1,a2..],[b1,b2..]但是注意
- 6: %这两个向量必须同时是行向量或列向量,而不能一个是行向量一个是列向量。所以返回的
- 7: %第一个元素是A的第a1行第b1列的元素存储的下标,返回的第,二个元素是A的第a2行第b2列的元素存储的下标...i是一个向量,c(i)得到的
- 8: %向量的每一个元素就是p中每一列你前面要找的的元素。
- 注:sub2ind(size(A),m,n)是得到A中m行n列这个元素的标号,具体参考:http://blog.csdn.net/djh512/article/details/6785975
在上面的代码中,得到的是y(i)=j的元素所对应的标号。
- 1: values = c(i);
- 2: f = -(1/m)*sum(values)+ lambda/2 * sum(theta(:) .^ 2); %这个就是cost function
- 最后求梯度:
- 1: d = full(sparse(1:m,y,1)); %d为一个稀疏矩阵,有m行k列(k是类别的个数),这个矩阵的(1,y(1))、(2,y(2))
- 2: %....(m,y(m))位置都是1。
- 3: g = (1/m)*X*(p'-d)+ lambda * theta; %这个g和theta矩阵的结构一样。
- 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是样本个数。
我们想用矢量编程来求g矩阵:
我们有样本X(代码中每一列是一个样本,也即X为n行m列),那么g = (1/m).*X*(p'-d)即是。比如,X的第 i 行乘以(p'-d)的第 j 列就是X(i,j)的值。(正是这种行向量乘以列向量是对应元素相乘再相加就 完成了公式里的Σ,这也是矢量编程的核心)
ok,现在我们这个函数写完了,我们想验证下,我们写的这个求导数或着说梯度的这个公式正确不正确,我们还是用之前博客提到的用求导公式来验证,因为你求softmax模型某个参数的导数跟你输入的数据是什么、多少都没有关系,所以我们这有用一些简单的随意写得数据和label,然后随意取一个参数进行验证是不是正确,这些程序在前面已经有了,就不进行讲解了。
这段程序没跑过,有空跑跑看。
- 1: % DEBUG = true; % Set DEBUG to true when debugging.
- 2: DEBUG = false;
- 3: if DEBUG
- 4: inputSize = 9;
- 5: inputData = randn(8, 100);
- 7: inputData = [ones(1,100);inputData];
- 8: labels = randi(10, 100, 1);%从[1,100]中随机生成一个100*1的列向量
- 10: end
- 12: % Randomly initialise theta
- 13: theta = 0.005 * randn(inputSize*numClasses, 1);
- 1: [cost, grad] = softmax_regression_vec(theta,inputData ,labels,lambda );
- 2:
- 3: if DEBUG
- 4: numGrad = computeNumericalGradient( @(theta) softmax_regression_vec(theta,inputData ,labels,lambda) ,theta);
- 5:
- 6: % Use this to visually compare the gradients side by side
- 7: disp([numGrad grad]);
- 8:
- 9: % Compare numerically computed gradients with those computed analytically
- 10: diff = norm(numGrad-grad)/norm(numGrad+grad);
- 11: disp(diff);
- 12: % The difference should be small.
- 13: % In our implementation, these values are usually less than 1e-7.
- 14:
- 15: % When your gradients are correct, congratulations!
- 16: end
UFLDL 教程学习笔记(三)的更多相关文章
- UFLDL 教程学习笔记(三)自编码与稀疏性
UFLDL(Unsupervised Feature Learning and Deep Learning)Tutorial 是由 Stanford 大学的 Andrew Ng 教授及其团队编写的一套 ...
- UFLDL 教程学习笔记(四)主成分分析
UFLDL(Unsupervised Feature Learning and Deep Learning)Tutorial 是由 Stanford 大学的 Andrew Ng 教授及其团队编写的一套 ...
- UFLDL 教程学习笔记(二)反向传导算法
UFLDL(Unsupervised Feature Learning and Deep Learning)Tutorial 是由 Stanford 大学的 Andrew Ng 教授及其团队编写的一套 ...
- UFLDL 教程学习笔记(一)神经网络
UFLDL(Unsupervised Feature Learning and Deep Learning)Tutorial 是由 Stanford 大学的 Andrew Ng 教授及其团队编写的一套 ...
- UFLDL 教程学习笔记(四)
课程地址:http://ufldl.stanford.edu/tutorial/supervised/FeatureExtractionUsingConvolution/ 在之前的练习中,图片比较小, ...
- UFLDL 教程学习笔记(六)主成分分析
教程:http://ufldl.stanford.edu/tutorial/supervised/MultiLayerNeuralNetworks/ 以及这篇博文,写的很清楚:http://blog. ...
- UFLDL 教程学习笔记(一)
ufdl的新教程,从基础学起.第一节讲的是线性回归.主要目的是熟悉目标函数,计算梯度和优化. 按着教程写完代码后,总是编译出错,一查是mex的原因,实在不想整了. 这位博主用的是向量,比较简洁:htt ...
- UFLDL 教程学习笔记(二)
课程链接:http://ufldl.stanford.edu/tutorial/supervised/LogisticRegression/ 这一节主要讲的是梯度的概念,在实验部分,比较之前的线性回归 ...
- 学习笔记(三)--->《Java 8编程官方参考教程(第9版).pdf》:第十章到十二章学习笔记
回到顶部 注:本文声明事项. 本博文整理者:刘军 本博文出自于: <Java8 编程官方参考教程>一书 声明:1:转载请标注出处.本文不得作为商业活动.若有违本之,则本人不负法律责任.违法 ...
随机推荐
- bzoj 1823: [JSOI2010]满汉全席 && bzoj 2199 : [Usaco2011 Jan]奶牛议会 2-sat
noip之前学的内容了,看到题竟然忘了怎么建图了,复习一下. 2-sat 大概是对于每个元素,它有0和1两种选择,必须选一个但不能同时选.这之间又有一些二元关系,比如x&y=1等等... 先把 ...
- 丁酉年六月十一ACM模拟赛
似乎该写题解了.今天模拟ACM,10道题(本来还有2道被删了),9道都来自BZOJ,中间我做过2道.那么说,今天Solv.便大大增多了(但还是不如强大的Amphetamine). 题单及一句话题解如下 ...
- kernel-init-bash
https://www.kernel.org/doc/Documentation/kernel-parameters.txthttp://unix.stackexchange.com/question ...
- 四、Linux学习之文件处理命令
1.建立目录:mkdir 格式:mkdir –p [目录名] -p 递归创建目录 注意事项: 如果是创建单个目录直接mkdir [目录名就可以] 如果是创建一个目录下的目录也就是递归创建目录请 ...
- Nlog写日志到数据库
https://github.com/nlog/NLog/wiki/Database-Target
- [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[ ...
- 2017 清北济南考前刷题Day 2 morning
期望得分:100+30+60=190 实际得分:100+30+30=160 T1 最优方案跳的高度一定是单调的 所以先按高度排序 dp[i][j] 跳了i次跳到j 枚举从哪儿跳到j转移即可 #incl ...
- SpringBoot 线程池配置 实现AsyncConfigurer接口方法
目的是: 通过实现AsyncConfigurer自定义线程池,包含异常处理 实现AsyncConfigurer接口对异常线程池更加细粒度的控制 *a) 创建线程自己的线程池 b) 对void ...
- 简单理解 NP, P, NP-complete和NP-Hard
P是一类可以通过确定性图灵机(以下简称 图灵机)在多项式时间(Polynomial time)内解决的问题集合. NP是一类可以通过非确定性图灵机( Non-deterministic Turing ...
- 20145226夏艺华 《Java程序设计》第5周学习总结
教材学习内容总结 第八章 异常处理 语法与继承架构 使用 try.catch Java中所有信息都会被打包为对象,如果愿意,可以尝试(try)捕捉(catch)代表错误的对象后做一些处理 try{ . ...