【ufldl tutorial】Softmax Regression
今天太长姿势了,什么叫懂了也写不出代码说的不就是我吗,就那么几行代码居然叽叽歪歪写了一个小时。
首先exercise要实现的是softmax的cost function和gradient,如下图:
(1)
(2)
(3)
下面就来仔细分析怎么不借助for循环高效的实现上面三个函数。
首先P是一个关键,因为在J和梯度中都出现了,所以现在实现P。
可以看到theta和X的乘积是一个十分重要的量,因为在分子分母中都出现了,所以首先计算假设h=exp(θTX),那么h(k,i)就是exp(θ(k)T*x(i))的值了,实际就是计算样本i标签为k的概率,当然是没归一化的。这一句的代码十分简单(为何不支持matlab的代码?有种被歧视了的赶脚=。=):
h = exp(theta' * X);
此时要注意的一点是虽然有10个分类,但是通过ufldl的讲解我们知道有一个参数是多余的,更直观的理解就是如果得到了x(i)取前9类的概率,那么取第10类的概率直接用1减去前9类的概率和就得到了,所以theat矩阵是9行,而不是10行。我们得到的h也是9行,和公式里面K=10不一样,所以我们给h加上1行1,至于为什么是1,接下来就知道了。
h = [h;ones(1,m)];
接下来就可以计算P了,我们计算一个矩阵P,使得P(k,i)表示上述公式2的值。可以看到公式2里面的分子就是上面计算过的h(k,i)的值,而分母就是h的第i列的值相加。这里就可以借助bsxfun函数实现:
p = bsxfun(@rdivide,h,sum(h));
logp = log2(p);
bsxfun函数是一个十分高效的函数,上述第一个参数@rdivide表示对h中的每个值做“右除”除法,sum(h)就是上面分析出来的P的分母值,是一个行向量1*m(m是总样本数),即(sum(h))(i)表示h的第i列相加的值,这样bsxfun函数就会自动对h的每一行的每一个元素,都除以sum(h)这一个行向量的对应位置的值。
接下来就可以计算cost function J了。借助sub2ind这个函数实现。ufldl上有对这个函数的解释,这里大概总结以下:对于矩阵A,I=sub2ind(size(A), 1:size(A,1), y);执行后I中存放所有index为(1,y(1)),(2,y(2)),(3,y(3)),...(size(A,1),y(size(A,1)))的元素的index,所以A(I)就是这些元素实际的值了。对于cost function J,我们需要把logp中所有(k,i)位置上的值都拿出来,其中k是x(i)的ground truth的标签,所以我们可以这么写sub2ind函数:
index = sub2ind(size(logp),y,[1:m]);
再把index里面元素在logp中对应的值加起来就是cost function J了:
f = -sum(logp(index));
最后解释一下为什么要给h最后一行补1,我们知道如果h(10,i)接近1,说明分类器认为x(i)取第10类的概率大;如果h(10,i)接近0,说明x(i)分类器不太可能取第10类,如果是其他值,说明分类器“自信度”不高,我们不用考虑。我们只要考虑h(10,i)为1的情况,因为我们只要保证从logp中取(k,i)位置上的元素时候,在h(k,i)位置上接近1的元素(k,i)在logp中被取出来,其他位置上的1并不会给最终的梯度带来影响,因为它们不会被取出来,所以在最初的h的最后一行,即使x(i)不属于第k类,我们把h(k,i)置为1,也不会对后面的运算造成影响。但如果x(i)确实属于第k类,我们把h(k,i)置为1,就保证了这部分误差会被计算到最终的误差J中。
以上计算了cost function J的值,接下来计算梯度g:
首先我们知道上面计算出来的P是一个k*m的矩阵(k是类的数目,m是样本的数量),P(k,i)表示样本x(i)属于第k类的概率,公式3中重要的是怎么求出一个k*m的矩阵yk,使得yk(k,i)表示x(i)是否属于第k类,如果属于,yk(k,i)=1;否则yk(k,i)=0;也就是公式3中减号前面的项,可以用如下代码实现:
yk = full(sparse(y,1:m,1));
full,sparse函数是非常神奇的。假设我们有一个矩阵A=[1,2,4],那么 full(sparse(A,1:3,1));就生成了如下的一个矩阵:
1 0 0
0 1 0
0 0 0
0 0 1
一般来说如果A是一个1*m的矩阵,那么full(sparse(A,1:m,1))就生成了一个(max(A),m)的矩阵,这个矩阵中(A(i),i)上的元素为1,其他元素都为0。这样我们用
yk = full(sparse(y,1:m,1));
就可以得到上面要求的yk。
不过呢,y里面是有10个类标的,所以yk其实是一个10*m的矩阵,前面说了,我们只要知道一个样本x为前9类的样本的概率就可以了,所以我们其实只需要yk的前9行,所以要对yk进行一个截短,同样对上面的p也做一个,因为其实p的最后一行是我们手动加上去的,并且在公式3中yk要和p相减,我们需要保证p和yk的维度match。
yk = yk(1:num_classes-1,:);
p = p(1:num_classes-1,:);
最后就可以根据公式3计算梯度了
g = -X * (yk-p)';
就这么三个公式,想用代码高效的实现就这么困难,有时候不光要关注idea,更要关注idea的实现。我实现的第一个版本准确率只有87%,这个版本有92%,有时候真的不知道是算法不好,还是实现不好,所以会码是非常重要的!
最后上下结果,总共迭代了232次:

完整的代码可以在我的github上看到。
参考:
【1】http://blog.csdn.net/lingerlanlan/article/details/38425929
【2】http://ufldl.stanford.edu/tutorial/supervised/SoftmaxRegression/
【ufldl tutorial】Softmax Regression的更多相关文章
- 【ufldl tutorial】Convolution and Pooling
卷积的实现: 对于每幅图像,每个filter,首先从W中取出对应的filter: filter = squeeze(W(:,:,filterNum)); 接下来startercode里面将filter ...
- emacs 新手笔记(一) —— 阅读【emacs tutorial】
ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287 [emacs tutorial]是熟悉 emacs 的入门资料.一共几十个命令,不需硬记,勤练即可. 翻页命 ...
- 【深度学习】softmax回归——原理、one-hot编码、结构和运算、交叉熵损失
1. softmax回归是分类问题 回归(Regression)是用于预测某个值为"多少"的问题,如房屋的价格.患者住院的天数等. 分类(Classification)不是问&qu ...
- 深度学习 Deep Learning UFLDL 最新Tutorial 学习笔记 5:Softmax Regression
Softmax Regression Tutorial地址:http://ufldl.stanford.edu/tutorial/supervised/SoftmaxRegression/ 从本节開始 ...
- 【DeepLearning】Exercise:Softmax Regression
Exercise:Softmax Regression 习题的链接:Exercise:Softmax Regression softmaxCost.m function [cost, grad] = ...
- 【TensorFlow-windows】(一)实现Softmax Regression进行手写数字识别(mnist)
博文主要内容有: 1.softmax regression的TensorFlow实现代码(教科书级的代码注释) 2.该实现中的函数总结 平台: 1.windows 10 64位 2.Anaconda3 ...
- 【UFLDL】Exercise: Convolutional Neural Network
这个exercise需要完成cnn中的forward pass,cost,error和gradient的计算.需要弄清楚每一层的以上四个步骤的原理,并且要充分利用matlab的矩阵运算.大概把过程总结 ...
- ufldl学习笔记和编程作业:Softmax Regression(softmax回报)
ufldl学习笔记与编程作业:Softmax Regression(softmax回归) ufldl出了新教程.感觉比之前的好,从基础讲起.系统清晰,又有编程实践. 在deep learning高质量 ...
- ufldl学习笔记与编程作业:Softmax Regression(vectorization加速)
ufldl学习笔记与编程作业:Softmax Regression(vectorization加速) ufldl出了新教程,感觉比之前的好.从基础讲起.系统清晰,又有编程实践. 在deep learn ...
随机推荐
- 山东理工大学第七届ACM校赛-经济节约 分类: 比赛 2015-06-26 10:34 19人阅读 评论(0) 收藏
经济节约 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 由于经济紧张,某国国王决定减少一部分多余的士兵,这些士兵在边界都有各自的 ...
- EditorWindow窗口大小锁死后没有边框的解决方法
var window = GetWindow(typeof(MyWindow), true); window.minSize = , ); window.maxSize = window.minSiz ...
- 从客户端中检测到有潜在危险的 Request.Form 值
今天在使用Kindeditor的时候,出现了如题的错误. 错误如图: 百度了下,艰难的找了原来是Framework的问题,原来用的2.0,后面变成了4.0,验证级别也更高了: 解决办法:在config ...
- Codeforces Round #373 (Div. 2) B
Description Anatoly lives in the university dorm as many other students do. As you know, cockroaches ...
- Mysql-学习笔记(==》存储过程 九)
1.存储过程概念在大型数据库系统中,一组为了完成特定功能的sql语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它. 2.建立存储过程delimit ...
- 关于MYSQL group by 分组按时间取最大值的实现方法!
类如 有一个帖子的回复表,posts( id , tid , subject , message , dateline ) , id 为 自动增长字段, tid为该回复的主题帖子的id(外键关联), ...
- Cpdetector编码识别
概述 浏览器在打开一个网页时,首要任务是判断网页的编码格式,然后采用合适的编码进行解析:我们常用的文本编辑器在打开文档时同样需要判断文档的编码进行相应的解析.这涉及到的技术就是编码甄别,下面我们介绍一 ...
- Eclipse搭建Android5.0应用开发环境 “ndk-build”:launchingfailed问题解决
Eclipse搭建Android5.0应用开发环境 "ndk-build":launchingfailed问题解决 详细参考http://blog.csdn.net/loongem ...
- 编写一个类A,该类创建的对象可以调用方法f输出小写的英文字母表。然 后再编写一个A类的子类B,要求子类B必须继承类A的方法f(不允许重写), 子类B创建的对象不仅可以调用方法f输出小写的英文字母表,而且可以调用子 类新增的方法g输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。
package zimu; public class A { public void f() { for (int i = 97; i <123; i++) { System.out.print ...
- Populate A List Item With Record Group In Oracle Forms Using Populate_List And Create_Group_From_Query Command
Example is given below to Populate a List Item in Oracle Forms using Create_Group_From_Query , Popul ...