这个博客为何而存在

说说我为什么维护这个博客,顺便总结一下2016年。

之前就说过,我想记下自己的轨迹,相当于记笔记给自己看,顺便给网友看。为什么不用知乎微信等主流平台,逆潮流而进使用博客?主要理由如下:

  • 潮流是只能等不能追的,这和在火车站等候火车是一个道理,乖乖留在站上,总会有车来,至于刚开走的车,我们泛泛之辈是追不上的。—— 韩寒《头发》
  • 不知彼而知己,一胜一负。
  • 星星之火,可以燎原?
  • 我希望我的观众是从搜索引擎到达这里。如果观众点进这里发现是浪费生命,我的责任就会小一点。可以让搜索引擎负责。

2016年博客数据

访问量算是增长较大,可能是因为我已经转向目前热门的机器/深度学习,内容也转了。所以访问量也大了不少。但贡献较大的其实还是分析微信聊天记录那篇博客。

当然访客的大部分都是来自搜索引擎,很符合实际。微博爱可可老师转了2篇,虽然我很高兴,但其实我觉得来自搜索引擎的访客是最让我高兴的。至少说明我的内容不是垃圾。这当然也是不完全统计,有些搜索引擎没有被识别为搜索引擎。我也通过这些referrer了解到很多东西,比如有哪些google的镜像站点。

我也知道哪些内容比较受欢迎,其实这通过webmaster更直观,这里就不截图了。这也算是知彼知己吧,更多的是知己。知道自己应该多整理哪些内容,知道自己有哪些不足需要尽快学习。

通过这个博客我也认识了好几个小伙伴,深刻地知道了世界是如何之小。看到我博客的一位小伙伴竟然是我高中邻座的表姐!(加了微博发现的)还有很多留学国外的同学,以前我以为德国澳大利亚什么的访问都是翻墙的,没想到居然是肉身访问!

其他数据也很有意思,也就是另一些形式的知己,以后可以一胜一负了。

博客作为星星之火,实在是这互联网时代最伟大的产物之一(另一个是搜索引擎,一个生产内容,一个搜索内容),看看wordpress的流行情况就可见一斑。但在我开始写博客的时候,这股潮流在中国已经渐渐消逝了。取而代之的是微博——微小的博客,继而出现了微信、知乎,我都不喜欢或者说不适合写博客。所以我会一直在这个博客总结下去,管他好不好看。


 

感谢小伙伴们,让我在dota 12连胜中迎来2017年,花式躺赢!

 

Deep Learning从0到0.1

以下大部分是根据我自己的学习过程来的,可以算是一种人生经验,也有可能是只适合我的。有好多人问我怎么入门,我自己都没入,所以是不想公开,能不看就不要看了。(陈老师微博转了一下,班门弄斧羞愧难当。小小服务器微卡,请见谅。)

前期准备

  1. 个人认为Linux远远优于Windows(mac 不清楚,貌似也比Windows方便一点),大二之后我没有在Windows上写过跑过代码,不清楚常用的deep learning框架能否顺利在Windows上安装。但我知道在Linux上安装theano就一个命令,GPU cuda 设置也很方便。当然,这是一个安利,可以不吃。
  2. 可以上Google,会用英文搜索。最好少看中文资料,或者粗略看中文资料有个大概印象之后仔细看英文资料。
  3. 基本的优化知识,像梯度下降法,以及随机的梯度下降法(SGD)。另外还有一些加速方法,可以看这篇博文,形象科学。
  4. 基本的机器学习知识,最起码的logistic regression。这个非常重要,可以看作是最最基本的单层神经网络,相当于平房跟金茂的关系。理解里面的sigmoid也很重要,对以后理解为什么要用tanh,relu有帮助。这个最好能自己实现,matlab也行,了解原理就好了。可以使用libsvm的数据集测试分类效果。可以参考coursera上的机器学习不过他的作业貌似封装了优化算法,最好优化算法也自己写。这可能是最艰难无趣的一步,实在不行先跳过。
  5. 一点矩阵知识,感觉知道就行,离真正用到还很远。
  6. 概率知识,只要不搞生成模型啥的如VAE这种就可以先不管。像CNN基本用不到,只要知道softmax是个什么就行了。softmax(敲黑板!)就是多类logistic regression,简单讲就是模型判定输入是属于哪个类的概率。理解了logistic regression就不难了。
  7. 最好能看一本书,能够系统的学习,Ian Goodfellow and Yoshua Bengio and Aaron Courville写的deep learning就不错。

准备这些我觉得需要2周左右,推荐几个框架,边准备边试,看看喜欢哪一个框架。


初步了解

神经网络最初的是多层感知机(MLP),就是多层的Logistic regression,coursera上的机器学习那课里也有讲到。可以跑一下thenao的代码。为什么纯MLP很少用呢?主要因为参数冗余且不符合原理。还有很多其他原因,可以在接触CNN等其他结构的网络之后慢慢理解。当然这个MLP也是很重要的,虽然这里不多谈。

最重要的是尝试,否则就是夸夸其谈不明细节。当然得选择有趣简单的东西玩。deep learning中RBM这类可能有点晦涩而且现在并不流行。我就分别举CNN,RNN,GAN中简单可行的例子。可能现在不知道这些分别是什么,后面慢慢理解。

CNN

CNN的开山鼻祖LeNetAlexNet算是最初级的CNN可以一看,毕竟里面有很多东西都过时了。但它引入的relu,pooling这些精华还一直在,所以务必看一下AlexNet的论文。这篇博文还有一些比较。简单来说,CNN就是下面的架构,很好理解,相比MLP就多了卷积pooling操作。看MLP就出现了,在这里cnn就是在提取特征,而MLP就是在提取的特征上做判别。

simple cnn
From deeplearning.net

知道这些并不有趣,要玩点直观的。我觉得最有趣的肯定是neural style,最近流行的Prisma也基于差不多的原理,如果你都懂原理你就是high level。我们在有限的计算资源下训练一个大型CNN显得非常不划算,但是用别人训练好的CNN做一些有趣的事也算是另辟蹊径来理解什么是CNN。他的paper中介绍的还算清楚。工业界是要让代码跑起来,入门的第一件事就是能跑别人的代码,管他原理不原理。如果不清楚,先跑起来再说,生成一张自己照片的风格图也很值啊,然后再慢慢了解原理。


如果了解了原理,看了源码,可以尝试修改,比如合成两张图片啥的。能做到就算完全了解了neural style的原理了。这算是入门的第二步,修改别人的代码,同时可以学习一个。牛b之后还可以想想能否通过Autoencoder来加快速度。



好像有点跳,不虚慢慢来。当了解CNN工作模式还得靠其他的东西。

还可以看看deep dream,不过看着好像有点恶心。或者看看其他流行的项目。最重要的是阅读源代码,代码是绝对正确的。书本上paper里的都是大概,很少有细节。我没怎么训练过CNN,所以没法给出更多训练时的细节。

RNN

RNN就难多了,理解LSTM花了我很久。下面两个系列帮我了很大的忙。看完绝对能理解RNN,至少知道是RNN个什么,至少知道为什么要用LSTM,GRU这些变种。看不懂可以先看个大概,跑跑代码再说,然后再看,然后再研究代码。我就这么recurrent的入门的。

  1. Recurrent Neural Networks tutorials
  2. Understanding LSTM Networks

然后是搞点有意思的。我觉得对于初学者来说,自动生成Shakespeare风格的文章或者Linux代码算有意思了吧。可以参考这篇博文和这篇paper。Github上有很多代码,如char-rnnblocks-char-rnn。原理非常非常简单,就是根据前一个字符预测下一个字符。如输入一句话”我tm怎么这么diǎo”,输出就是“tm怎么这么diǎo。”,用RNN来拟合这样一个输入输出就行了。就是以下的结构。

from colah.github.io

这篇文章比较n-gram和RNN的结果,可以看出RNN是多么diǎo。简单来说,RNN能捕获前后之间的联系,比如c代码,RNN能生成匹配的括号,而n-gram是做不到的。

这是RNN能做到的最简单的,而且能在自己电脑上轻松跑起来的例子。还有简单的就是曲线拟合,时序分析。如下就是用RNN拟合的,可以自己尝试用RNN来拟合sin(x)



另外还有结合CNN和LSTM生成图片描述音乐合成,很多能玩的例子,而且玩着玩着就懂了。如果没有好奇心,那可能玩了之后还是不懂。反正我玩了之后,就会想:“tmd,怎么做到的?!”,然后就开始学习一个。

GAN

Generative Adversarial Networks算高级一点的内容,也是算简单的很有意思很有前途的一块,看字面意思就知道是生成模型。比其他生成模型VAE,RBM什么的简单多了,而且原理非常简单。总的来说就是一个生成网络,一个判别网络,目标是让生成网络生成判别网络无法区分是生成的还是真实的数据,这是个对抗(adversarial)的训练过程。应用于图片可能会有点问题,因此出了Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks(DCGAN),效果好很多,见github

GAN比较简单,网上没有满意的代码,随便写个mnist的GAN代码,稍微能看到数字。



要玩还是试试DCGAN比较好,毕竟GAN有点不完善。生成数字可能不那么有冲击力,生成人脸够diǎo了吧,详见github。更有冲击力的是结合VAE和GAN的生成网络VAE/GAN

其他

如reinforce learning, deep-Q 还没有接触。以后再谈。


略微高级

我只能说说我熟悉的deep learning的领域。

框架开发

在知道deep learning的基本知识之后就应该回馈社区。参与一些流行的年轻的框架的开发。如mxnetkerasblocks。首先可以锻炼自己阅读代码和写代码的能力,还可以了解实现细节,这对以后实现自己的奇思妙想很有帮助。个人推荐keras,文档完善,社区广泛,同时支持theano和tensorflow。这里的关系是,theano和tensorflow是两种不同类型的砖头,而keras用这两种砖头做成一些通用的部件如墙壁地板对应于deep learning中的如MLP,LSTM网络等。搞deep learning,熟悉一种框架是必须的,可以的话,需要了解其他框架,毕竟要看源码。或者更形象一点,CUDA相当于汇编语言,theano和tensorflow是c语言,keras和blocks这些框架就像Python。

研究方向

deep learning里还有很多可研究的东西。我们不关注性能,毕竟这超出能力范围。我们可以想想deep learning能干嘛。机器翻译diǎo不diǎo,我一头就栽进去了,毫不犹豫,因为这个太tm有意义太tm有意思了。哥以后不用学外语,也能精通八国语言,想想就exciting。不像CNN,机器翻译的性能还没有那么好,始终缺少一点东西,等待开发,可以看看acl的tutorial

生成模型也是非常热门的发展方向。最近出的Pixel Recurrent Neural NetworksDRAW都是很美妙的,可惜没有时间跟进。但了解一下还是可以的。

最后是大牛的最新研究进展,随时可以跟进。


总结

入门实在有点难以定义。我认为能自己写个网络就算入门了,所以要看教程、跑代码、看文档、看代码、改代码反复来。其中跑代码是稍微轻松一点,也能激发兴趣。要尝试简单的,慢慢就会复杂的了,想想现在看的英文文章也是从一个个单词积累的。
所以要尝试啊,别光看光点赞光收藏啊。

最后我们需要帮助:我们正在翻译deep learning这本书,直译版已全部翻完正在校正中,大概2周后公开。希望多多提提意见,帮忙修改修改,目前处于私密状态,在github上。

Generative Adversarial Networks

生成对抗网络(Generative Adversarial Networks)越来越火,最开始是用于MLP的生成对抗网络,就是Ian J. Goodfellow论文中提出的。后来出现了CNN架构的,效果确实提高了。现在还有SeqGAN,我不敢做评论。既然是Simplified DeepLearning系列的,自然尝试最简单的。


Generative Adversarial Networks原理

GAN的原理其实很简单。首先我们要学习的是生成器G关于数据x的分布p_g,问题从哪生成呢,这就需要我们定义一个噪声先验p_z(z),如一个均匀分布。那么生成的样本就是G(z)。然后我们需要一个判别器D(y),判断y是来自G还是x,也就是D要判断出输入是伪造的还是真实的。这就是一个对抗学习的过程:G尽量生成逼近真实的数据,使D不能分辨真伪。D要足够厉害,能够分辨真伪。形象的图如下:

gan
图自slideshare

形式的代价函数如下:

    \[\underset{G}{\min}~ \underset{D}{\max} ~V(D,G) = \mathbb{E}_{x \sim p_{data}(x)}[\log D(x)] +\mathbb{E}_{z \sim p_{z}(z)}[\log(1 - D(G(z)))]\]

理解这个很重要,可以看看这个。这里其实是将两个loss拼起来了,而且省去了一部分。有了目标函数,训练则是交替的训练,论文中有详细描述。简单的说,就是一步固定G,训练D,然后固定D,训练G。作者提到,为了防止”the Helvetica scenario”,要训练D多步,然后训练G一步。


一维高斯分布

看一个简单的例子,也是论文中的例子,我觉得很多人没理解论文中那个用均匀分布生成高斯分布的例子。为了深刻理解,保证自己没有理解错误,我必须再现一下。网络结构很简单,没几行如下。

然后就是训练,具体见github。怎么知道我是对的呢。可以看以下训练过程。

init

初始状态
m1

训练好的判别器
m2

交替训练几步之后
m2

最后结果

 

我还能说什么,完全符合理论D^*(y) = \frac{p_{data}(y)}{p_{data}(y) + p_{g}(y)}以及最后D(y) = \frac{1}{2}。在强调一下,这是一维的情况,也就是从真实数据给出一个数字和从G中生成一个数字如4,判别器无法判断4来自真实数据还是伪造的,因为这两个分布产生这个数字的概率是一样的,如最后一张图。如果真实数据产生4的概率大一点,判别器就能稍微判断一下,如最后第二张图。


MNIST测试

又得用到果蝇MNIST了,上面的例子太简单,可能不能令人信服。代码其实差不多,稍微加了个dropout,见github。训练中间结果如下,注意这是一张只循环一次的gif,你可能要刷新一下。

mnist gan
mnist gan (gif)

可能注意到怎么只生成两个数字,这就是所谓的”the Helvetica scenario”,我还不知道哪里出了问题。反正能生成数字了,够了。


实践出真知,show me the code!

国庆终于把坑填完了,DOTA还拿了暴走,完成了千年辅助的梦想!3天没出宿舍楼,欢度国庆,开心!


链接