@cleardusk
2015-12-18T20:40:14.000000Z
字数 6634
阅读 1804
GjzCV
这一周主要的工作是涉及 scikit-learn, Face Alignment at 3000 FPS via Regressing Local Binary Features 论文的算法细节,python,个人对学习方法的一些思考等等。
上周五放下这篇论文后,我准备关注 Machine Learning 的一些 models,我先从书籍下手,选择了 PRML 这本书,但很快觉得不适,这本书我之前扫过一遍目录,很多 term 都知道,但具体都不熟,但我认为这是本非常基础且有用的书。我开始从头看,一会儿就不对劲了,我现在只是想急切的了解有哪些 model,以及 model 是如何工作的,probability 固然对 model 的理解很重要,然非我此时想要了解的东西;我也不想过于草率的把书扫一遍,这本书偏基础偏理论些,我觉得偏理论的东西还是细细看比较好。我换了个方向,不如先看看这些 model 有什么效果,我想找个好点的库先玩并学习一下,我最后选了两个,一个是 OpenCV 的 ml 模块,一个是 python 的 scikit-learn。我选了 scikit-learn 的,我对比了下 OpenCV 不同版本的 ml 模块,发现 OpenCV 的 ml 模块 3.0.0 版本封装的比较好,已经实现的算法也多些,我编译了两次未成功(ffmpeg 的原因),便放弃了,现在还不是迫切需要,不想花多少时间在上面。我花了不少时间看 scikit-learn(在 Python 中是 sklearn)的 user guide 和 reference,偶尔看看源码,比如我 track 源码,发现最基础 linear regression 的实现是直接调用 scipy 的库进行计算的。
sklearn 是 Python 的一个机器学习库,我看了一些 linear models,以及 decision tree 和 random forest 部分,具体的细节我就不多说了,我的重点放在每个 model 能干什么事上。我跑了不少的 demo,有些简单,也有些我不清楚的,我举一个例子,这个face completion,我好奇的有两点:1. random forest, knn, linear regression, ridge 这四个回归模型都竟然可以有多个 output;2. 这四个 estimator 是如何做到 multiple input -> multiple output 的映射的。我只是把这几个问题写下来,还没有花时间去琢磨,因为之后我回到了那篇 face alignment 的论文上,不过我想了一下如何去琢磨:wiki&online tutorial + book(.i.e PRML) + source code(scikit-learn or others);进阶的话我可以在谷歌学术,springer 搜更专业的书和文献。
我后来想到了一个关于学习 ML 理论和实践的 trade-off,就是在用 scikit-learn 或者其它库进行数据分析和基础理论之间徘徊,比如看书看到某个 model 并理解后,就立马用 scikit-learn 等进行验证,拿实际数据进行分析,得到反馈;或是观察 scikie-learn 中 model 的表现,有疑问后在回过去看书。(绕来绕去还是绕回去了,这应该是大部分人的学习模式)
我之所以如此关注 ML,主要原因有这几个:1. ML 与模式识别是紧密相关的,要不然怎么会有 Pattern Recognition and Machine Learning 这样的书名。2. ML 是 DL 的基础,我之前看的 DL 的那本在线书 NN&DL 中很多概念,与我在看的 Deep Learning 这本书中的 Machine Learning 部分的概念重叠。3. 对 ML 中的那些 models 很好奇,它们为何如此有效?
我之所以选择一个良好的 ML 库,因为我觉得很多轮子没必要再造了;固然造轮子能够加强对某个 model 的理解,但这样进度的学习实在太慢了。暂时选择 Python 的原因是,Python 很灵活,学习效率很高;c/c++ 每次运行还需要编译,远不及 Python 等脚本语言反馈的效率高,matlab 不及 Python 灵活。这三个各有各的优势,选择的时候得针对的需求。
关于这篇论文我只谈几点。
shape regression 是这篇论文的框架,基于这个框架之前已有不少的论文;这篇论文的特点在于 shape-index feature 是局部的,范围与选取的 radius 有关,选取局部的 feature 能减少运算的复杂度。
要理解 random forest,先从 decision tree 下手,粗略地理解:前者只是多个后者的组合。关于 decision tree,我写了这三个原则:
- decision tree 的每一个 node,都是将 feed 的 samples 进行分类,因为是分为两类,最后形成一颗二叉树(除 leaf node 外)。
- 每个 node 分类(即 split 的过程)的 rule 是可以自定义的。
- tree 会一直 grow,在某个阶段必须停止,停止的 rule 也是可以自定义的。
在本论文中,random forest 是如何对 train 得到 local finary feature 的呢?
首先,这不是 LBP,用的是 pixel-deffreence,就是两个 pixel 的灰度差(浮点,[0, 1]),这样一定程度上能减少光照的影响。其次,一个 random forest 只针对一个 stage 的一个 landmark,就是一个点。
现考虑 forest 的一个 decision tree。train 的时候,以 radius 为半径,在一个实际的 landmark 周围,比如随机选取 500 个点,假设有 1000 张 iamges,可以得到一个 500 by 1000 的 feature(矩阵)。因为选取了 500 个点,就是 500 个位置,现在用一个循环遍历这 500 个位置,对于每一个位置,有 1000 张 iamges 的 feature,可以用一个 1000 维度的 vector 表示,这个 vector 就是 feed 给 decision tree 中的 feature。500 个位置,即 500 个循环,每一次循环,从 vector 中随机选取一个 value 作为 threshold,这个 threshold 将整个 vector 划分为两部分(即两个 child),然后计算 vector variance 的减少值,即 ,因为是 500 次循环,每次循环会得到一个 variance 的值,然后选择这 500 个值中的最大值,作为这颗 decision tree 的这个 node 分裂的 threshold。对这棵树的子节点采取相同的分裂方法,只是 vector 的长度减少而已,这是一个递归的过程。最后就形成了一棵树。这棵树的每个 leaf node 的 output,文中的意思是 的平均值,我猜测可能是这样,计算走到该 leaf node 的 images的 meanshape 与 ground shape 的 offset 的平均值,不过本文实际上将这个 offset 值给抛弃了,再用一个 linear regression 去替代它。
上面只是谈了一个 stage 的一个 landmark 的一个 random forest 的一个 decision tree,其它的 decision tree 是一样的,只是随机选择的 feature 不同,或者选择的 images 不同;其它的 landmark train 的过程同此 landmark;其它的 stage 同此 stage,只是局部区域的选择范围的 radius 不同。在 test/predict 的过程中,还是只对一颗 dicision tree 进行分析,train 过的 tree 中,记录下来的是一个位置和一个 threshold 值(对于这个 thresold 值预先任意确定还是随机选择我持不确定态度,上面一段的描述是随机选择出来的),那么,input 一张 image,计算 meanshape(landmark) 某个点的和树记录下来的位置的 pixel-difference,即灰度差,将这个灰度差与 threshold 值进行比较,决定此张 image 的走向。剩下的就不多说了。强调一点,decision tree 的每个 node 记录的是 位置& threshold。
以上是本论文的核心部分,我不保证自己的理解是完全正确的,因为其实可能本论文也没有完全说清楚。当然,我还没有提及 shape 会存在变形,需要变换,radius 的选择也是一个技巧;还有最后的 global regression。
关于 decision tree,我补充一些,这是我自己在笔记中记录的草稿:
关于信息论在 Random Forest,甚至在 ML 中的基本假设
1. ML 中的 learning 过程,从 Information Theory 的角度,是一个熵减的过程。(怎么计算熵,怎么使熵减的最大,这才是具体的问题)貌似就只能做这一个假设了,就是一句大白话,decision tree 中,feature 的选取的 rule,就是熵减;选取的 feature 构成了 decision tree 的记忆;不停地选取 feature,就是 learning(train)的过程。feature 可以抽象为数值,数值作为 threthold;每个 node 的 threthold + 判断,构成了一颗 tree 的完整的记忆与 decision。
以上的每个字都是我码的,但一部分理解来自部分中文博客,以及这个项目的源码。虽然,上面的描述可能绝大部分是合理的,但是,我并不理解为什么这样就可行,比如 decision tree 分类出来得到的 feature,为何就是一个好的 pattern?
之前是有想法把算法重写一遍的,但是发现这样一番独立探究(我还没有请教别人,只借助了搜索引擎)下来,我发现我的兴趣点转移了,我并不想呆在这一篇论文上,以论文驱动的形式进行研究,就拿 face alignment 来说,我如果继续研究下去,我会去思考:传统的方法有哪些,基于 ML 的 model 的算法有哪些,基于 DL 的 model 又有哪些,为什么这些算法可行?有哪些 feature,为什么这些 feature 能起作用?等等,我可以提一系列合理和不合理的问题,然后去想,去看文献。我目前并没有什么积累,很多基础的东西还没搞懂,所以我认为对于现阶段的自己,可能所要做的更多的,是积累。(还有一点是交流,但我目前所处的环境,不方便和老师师兄师姐同学交流,身边也没有类似专业的同学;不过,独立思考倒也有它的好处,能培养有个性的思维方式,但有风险走弯)
dlib 的那个算法的 paper 我还没开始看。
这个问题下的较长回答我今天又看了一遍,发现自己这些日子的感悟与某些挺类似,比如那个打怪升级的回答,比如形成 intuition 或 insight 是很重要的,3000fps 的这篇论文的 Introduction 中也提到,比如对数学的看法,这个我有时间再写,对现阶段的我影响比较大,比如提到写作能力的那个回答,我觉得回答的非常好,我摘一句话写作是一个对你的实验和研究的深度反思过程
,还有等等。
In this work, we propose a better learning based approach. It regularizes learning with a “locality” principle. This principle is based on two insights: for locating a certain landmark at a stage, 1) the most discriminative texture information lies in a local region around the estimated landmark from the previous stage; 2) the shape context (locations of other landmarks) and local texture of this landmark provide sufficient information.
前一段时间,关于专业和编程,我浏览的绝大部分是英文的 page(我使用搜索引擎的频率,百分之九十是 Google,百分之十是 Bing);但这周我也浏览了不少的中文博客。我发现,浏览中文页面(指专业相关的),信息密度更大,就是同等时间内获取的信息量比英文多,这一点我的一门专业课老师也说过;我开始反思,自己是不是有点"为了英文而英文"了,我找了一个热门的 csdn 博客翻了翻目录和内容,aha,博客的这种内容我不是天天在写么,不过我是记录在为知笔记里的,截止到现在(2015.3-2015.12),已经有 982 篇笔记,就算只有百分之 20 的转化率,我也能够凑个一两百篇博客的,当然,我开玩笑的,我要写博客肯定花的时间比写笔记更多,我的笔记只是草稿,至于我的博客,自从国庆节憋了两篇文章后,一直没更新。
我想强调的是,不管中文英文,重要的是能够准确的获取信息,准确的理解文本所表达的东西。这对我直接的刺激是,我现在在看英文的内容时,我会想,我自己有没有明白这段所要表达的意思,不能自欺欺人;我在看中文的内容时,也是同样的想法。
看 LBP 的时候,我准备用 Python 写一个的,用 OpenCV 库,然后我不小心扫了一下我 clone 的一个关于 face recognition 的 Python 源码,有 LBP 特征及其变种计算的代码,最基本的 LBP,它是这样写的
X = np.asarray(X)
X = (1<<7) * (X[0:-2,0:-2] >= X[1:-1,1:-1]) \
+ (1<<6) * (X[0:-2,1:-1] >= X[1:-1,1:-1]) \
+ (1<<5) * (X[0:-2,2:] >= X[1:-1,1:-1]) \
+ (1<<4) * (X[1:-1,2:] >= X[1:-1,1:-1]) \
+ (1<<3) * (X[2:,2:] >= X[1:-1,1:-1]) \
+ (1<<2) * (X[2:,1:-1] >= X[1:-1,1:-1]) \
+ (1<<1) * (X[2:,:-2] >= X[1:-1,1:-1]) \
+ (1<<0) * (X[1:-1,:-2] >= X[1:-1,1:-1])
return X
直接用矩阵运算就可以了!代码的抽象写的比较好,至少我目前是写不出这样的代码的,学习了一下。比如它 descriptor 进行了抽象,这样的好处就是可以很方便的使用不同的 descriptor 了。
某天我在 springer 上找到了这本书 Encyclopedia of Biometrics
,如其题名,是 Biometrics 领域的关键词索引。我想下下来,一个一个章节下太麻烦了,然后我用 Python 写了一段代码,爬了下来,虽然写代码的时间足够用鼠标一个一个下好几遍了。
我仍在维护自己的一个非常小的项目 CodeCount。
这个比赛的内容是学校图书馆发起的,内容是图书馆的数据库、规章等。参加这个比赛的初衷,是想稍微锻炼一下文献搜索能力,不过,没觉得有多大提高,倒是多知道了几个数据库。这是在线比赛,两人组队,初赛过了,但成绩不理想。排在前 20 的,一半是研究生博士生的组队。
这个学期剩下的时间不多了,下周一过,就得花不少时间着手两门课的期末考试和两门课的课程论文。
如果可能的话,我还是想积累一些基础知识,理论与实践同时搞,适当的看看论文。基础知识包括:数字图像处理,ML,DL,数学。
题外话,这次写的有点长,但确实是我这周所涉及的以及思考的东西,看来下次得写个精炼版的。
[1] ML 属于应用数学的范畴,计算机科学、信息论都属于应用数学的分支。文中的偏基础偏理论只是相对性的,因为纯数学的理论性可能强多了。
[2] 写记录的时候,我一般都会仔细回顾所写的内容,刚刚又去尝试编译 OpenCV 3.0.0 版本,发现编译成功了;我猜测可能是 linux 上 mplayer (播放器后端) 的问题,因为我昨天把 mplayer 的依赖装了一下,smplayer(射手影音,播放器前端)能正常播放视频了;也有可能是我前天桌面又崩掉一次后,我又装了一次 codec (视频编码解码器)。