卷积神经网络(Convolutional Neural Networks)太棒了:它们能够从你的照片中识别出物体、位置以及人物;帮助自动驾驶汽车识别行人、路标以及灯光;识别遥感影像中的农田、森林和交通情况;辨认医学影像中的异常现象,还有各种各样的实用功能。但是这些强大的视觉识别模型时不时也可以作为娱乐的手段。
在这个有趣的试验中,我们用一个非常强大的、有着一亿四千万个链接的卷积神经网络模型来对从网上选出的二百万张自拍照片进行识别,然后训练它去区分好的自拍和差的自拍。 这个实验的理由很简单,因为这是卷积神经网络可以轻易完成的任务,而且我们也可以从试验过程中学习如何来完成一张更好的自拍。
卷积神经网络
话题深入之前,我认为有必要来科普下究竟何为卷积神经网络(缩写为ConvNets),以使我们的读者不要就此望而却步。 简单来说,卷积神经网络就是专门为电脑视觉问题这枚钉子打造的锤子。如果今年你读到或者看到任何关于计算机识别图片或视频中的事物的报道,几乎都能够和ConvNet 扯上关系。
[caption id="attachment_6356" align="aligncenter" width="1418"]
【图】从左上开始顺时针列举了ConvNets应用的实例:在街景图片中识别住宅门牌号,分辨医学影像中的异常情况,辨认汉字、交通标志以及人的面孔。[/caption]
来讲点历史吧。卷积神经网络的背景故事碰巧相当有趣。Yann LeCun等人在上世纪八十年代在Fukushima识别机的早期成果基础上开发了卷积神经网络。1993年时LeNet1(卷积神经网络ConvNet那时候的名字)可以用来识别数字。然而这些成绩却并没得到计算机视觉行业的重视,原因是大家认为LeNet对于现实世界中所拍的图片无计可施。到了2012年这个印象被打破,这要归功于计算机性能的提升(尤其是GPU加速,感谢NVIDIA)以及数据库的爆发增长(感谢ImageNet),因此我们终于有了足够的样本来训练我们的神经网络。2012年ImageNet挑战赛中(计算机视觉领域的世界杯级赛事),Alex Kirzhevsky,Ilya Sutskever 和 Geoff Hinton带领卷积神经网络第一次露脸,并以16.4%的错误率遥遥领先第二名26.2%的错误率取得了冠军。
我碰巧第一时间见证了这一关键时刻,因为ImageNet过去几年是由李飞飞实验室也就是我工作的实验室牵头搭建的。很多场景历历在目,我还记得我的搭档激动地说她简直不敢相信卷积神经网络出现在了参赛名单上,我也还记得我们在屋里来回地踱步想要弄清楚到底刚才是什么情况。在后来的几个月里,卷积神经网络由受到质疑的处境一跃成为计算机视觉领域的明星,几乎每一篇计算机视觉方面的论文都在讨论它。ImageNet挑战赛的情况反映了这一趋势——在2012年的比赛中,只有一个参赛队伍使用了卷积神经网络,但是到了2013年和2014年几乎所有参赛队伍都在用卷积神经网络。还有个有意思的现象,每年的获胜团队都会迅速地转型成一家企业。
在接下来的几年中我们完善、简化并提高了2012原始版「AlexNet」的架构(是的,我们还给它们起名字呢)。2013年又有了「ZFNet」,2014年的「GoogLeNet」(看到没?既有LeNet在其中又能体现出这是Google出品,哈哈)以及「VGG Net」。总而言之我们现在知道卷积神经网络是:
- 简单的: 一个从原始图像开始,对图片进行数十次反复处理的程序
- 迅速,图像处理速度达到几十毫秒。
- 工作能力出色(可参考这篇文章来看看我如何能在图片分类中战胜GoogLeNet)
- 另外,从某些角度来看,卷积神经网络的工作方式和我们的视觉皮层非常相似(参考这里)
藏在这之下的
那么卷积神经网络是如何工作的呢?纵观内部结构,你会发现一个非常简单的计算序列在一直不断地重复再重复。下面这幅动图演示了一个小型卷积神经网络的工作流程:
[caption id="attachment_6367" align="aligncenter" width="532"]
【图】相关流程展现[/caption]
在最左边我们将原始图片像素导入,呈现成三维数字网。举例来说,一张256×256的图片排成256×256×3阵列(最后的数字3代表着红、绿、蓝三色)。之后我们开始计算,说起来这方法有点复杂,我们用小的滤波器在图片上来回扫描,不同的滤波器会针对不同的特点发出信号:有些在感应到水平边缘时会发出强烈反应,有些会针对红色区域做出回应等等。假设我们有十个滤波器,用这种方式我们就可以将原始的(256,256,3)图片转化成(256,256,10)的「图片」,抛弃原始图片的信息,仅仅保留十个滤波器在图片各个位置所做出的回应信息。这就相当于图片中的三原色(红、绿、蓝)通道被十个滤波器回应通道所取代了。
(参见上图右侧的第一列) 现在,我阐述了图片被处理后的第一列,那么随着时间的流逝其他列显露出什么现象呢?它们重复进行了一次又一次完全相同的操作,每一次都得到新的一列。下一列相当于刚才应用于先前一列反馈结果的另一套滤波器,并逐渐发掘出越来越多的复杂视觉形态,直到最后一组滤波器运算出图像中完整的视觉类别(如图中所示狗/蟾蜍)的概率。显然,我略过了若干部分,但总的来说:这就是从始至终运行的卷积神经方式。
训练。我们已了解卷积神经网络是一大批在彼此之上相互作用的滤波器。但我们如何能知道应该寻找哪种滤波器呢?我们不这样做——我们全部随机初始化它们,然后假以时日的训练它们。例如,我们为一个携带随机滤波器的卷积神经网络提供一副图像,然后它可能会得出「有54%的可能性这是一条狗」的结论。然后我们可以告诉它,这事实上是一只蟾蜍,那么就会出现一次数学过程,对卷积神经网络中所有滤波器进行一次全面微调整,使得下次再进行同一副图像识别时更倾向于得出蟾蜍的结论。而后我们就为百万幅图像数以亿计的重复这一过程。自然而然地,在卷积神经网络中追踪计算路径的不同滤波器将会逐步地调整自身,从而对图像中重要的信息做出反馈,例如眼睛、然后是头部、更或是整个躯干等等。
[caption id="attachment_6357" align="aligncenter" width="800"]
如图所示的是在受训过的卷积神经网络中随机挑选的12个滤波器,转载自马修·蔡勒的《对卷积神经网络的观察和理解》。这里所显示的滤波器处于过程中的第三阶段,并且似乎为车轮/人体躯干/文本信息等反馈出蜂巢图案的结果。再次说明,我们不干涉这个结论;它由其自身呈现,但我们可以校验它。[/caption]
在Jason Yosinski等人的项目deepvis中可以看到另外一组关于完整受训过的卷积神经网络的视觉化效果。它包含一个关于卷积神经网络的有趣现场测试,测试是通过你的计算机摄像头实时进行的,这段视频中Jason很好的解释了它。
总而言之,完整的训练过程就像给一个孩子展示很多事物的图像,然后他/她需要逐渐理解在图像中需要通过寻找什么来分辨这些事物。如果你想要一个技术点的解释,那么卷积神经网络将会以滤波器作为参数,对图像像素到类别概率绘制一个函数,然后我们运用随机梯度调整优化一个分类损失函数。又或者,如果你从人工智能/大脑/奇点的层面看,这个功能就是个「深度神经网络」,滤波器是神经元,而完整的卷积神经网络是一块模拟视觉皮层组织的自适应器。
训练卷积神经网络
卷积神经网络的好处在于你可以提供任何你喜欢的图像(连同分类标签一起),它们即会学习如何识别这些标签。就这次的主题来讲,我们将会给卷积神经网络提供一些好的和不好的自拍照,然后它会在这些图像中自动找出分辨这两类图像的最佳途径。让我们来抓取一些自拍照:
- 我以#自拍照#为关键词写了一个快速脚本来收集照片。最终得到五百万张照片(对于卷积神经网络来说是越多越好)。
- 采用另一个卷积神经网络来将照片的范围缩小到两百万张,保证每张照片上至少都有一张脸。
- 现在到了决定这些自拍照中孰优孰劣的时候了。直观上来说,我们想通过一个代理服务器观察有多少人看过这些自拍照,依照点赞的数量来计算出观众数量级。我将全部的用户收集起来并按照粉丝数分类。对照片上的每个附加标签给予一点额外补贴,使得这些标签可以吸引更多的眼球。然后我将这份挑选后的名单再分为每百人一组,并依据它们的点赞数为这一百幅自拍照分类。我只选用了线上公布超过一个月的照片,以确保是准确稳定的点赞数量。再将点赞数最多的50幅照片指定为好的自拍照,将点赞数最少的50幅照片指定为不好的。最终通过二进制数将这些数据分成两组,并试图通过看过每一张照片的人数来进行标准化。在这个项目中我同样把那些过少粉丝或者过多粉丝的用户过滤掉,当然也包括那些在照片上使用了过多标签的。
- 将这一百万好的自拍照和一百万不好的自拍照作为结论数据集,并以此训练一个卷积神经网络。
看到这里你可能会反对我定义一张自拍是好是坏的标准——比如:如果有人发布了一张非常棒的自拍,但是由于是深夜发布的,可能看到的人不太多,它获得的赞也相应的少了,这又该怎么办?说得对——这几乎就压根不行,但是这也是它唯一能够实现的「对」的方式,也是卷积神经网络能够掌控的情况。它不会犯迷糊或者气馁,只是尽自己最大的力量去完成分配到的任务。想要知道在我们的数据资料集当中分辨两个种类有多困难,可以看看下面这几张训练图片。如果我给你这其中的任意一张图片,你可以说出它属于哪个类别么?
[caption id="attachment_6358" align="aligncenter" width="1105"]
【图】示例图片展示了在我们训练数据集中被认定好或者坏的自拍,它们将被作为教导样本输入到卷积神经网络之中。[/caption]
训练细节。正是为了突出一些技术性的细节,我利用Caffe(一种深度学习架构)进行卷积神经网络的训练,首先我用VGGNet网络在ImageNet进行预训练,同时在自拍照片数据集上进行微调。我的模型在一个NVIDIA K40的GPU上跑了一整晚,同时关闭了dropout功能因为在没有dropout的情况下我得到了更好的结果。我也用VGGNet在一个人脸数据集上进行了预训练但是没有获得一个比ImageNet上更好的结果。最终模型在我的验证数据子集上获得了60%的准确度(50%是随机猜测的)。
如何成就一张好的自拍照?
我们收集了二百万张左右的自拍照,根据他们收到的点赞数来决定哪一些可能是好的自拍或者差的自拍(点赞数目也受限于关注人数的制约),我们将整个数据集送入Caffe并训练卷积神经网络。ConvNet「注视」着这两百万自拍照中的每一张数十次,并且在一定程度上调整它自身的滤波器从而最大化地分辨出好的自拍和不好的自拍照。我们无法轻易地查看到它到底挖掘出了什么(因为大概有一亿四千万的参数量混合在一起定义调整滤波器)。然而我们可以设定它放过那些从来没见过的自拍照,通过分辩喜欢哪些照片,不喜欢哪些照片来尝试理解它正在怎样地运作着。
我从测试集中取了五万张自拍照(注:我们的卷积神经网络在这之前没有见过这些图片)。作为第一次视觉化,在下面的图片中我展示了一个连续的视觉化过程,最好的自拍照片放在顶行,最糟糕的自拍放在底行,而每行之间夹着一个可持续体结构:
[caption id="attachment_6359" align="aligncenter" width="1548"]
一个从最好(顶层)到最差(底层)的自拍照组成的持续体结构,这是由卷积神经网络判别出来的。[/caption]
这个现象十分有趣。现在我从5万张照片中抽出最好的100张,根据卷积神经网络的判定:
[caption id="attachment_6360" align="aligncenter" width="1290"]
这是由它自身判断出来的5万张中最好的100张自拍照片。[/caption]
如果你希望了解更多,这里有一个链接
_top 1000 selfies (3.5MB)。看过之后,你是否注意到了卷积神经网络可能学会通过寻找什么来判定好坏的模式了吗?我看到了其中的一小部分模式,如果除了以下我列举出的模式,你还在其中发现了其他的东西,请在评论里告诉我吧,如果能知道其他存在的模式,我将非常高兴。
为了得到一张好的自拍,大致模式有:
女性自拍。女士们的相片排名一直比男性要高,特别注意到的一点就是,前100的相片里没有一张单独的男性自拍相片。
脸部大小占整张相片的1/3。我们注意到位置和脸的角度在排名靠前的照片中都是比较一致的。脸部总是占整个图片的1/3左右,角度微微倾斜,位置偏中上方。这也给我带来启示:
- 裁掉前额部分。这是为什么呢?至少对女性来说,这似乎是一个不错的策略。
- 展示你的飘逸长发。我们注意到通常过肩的长发都会显示出比较大的优势。
- 增加脸部的过饱和度。我们注意到通常过饱和的光线能够使面部看上去更加平滑和融入画面,与此相关的:
- 放置一个滤镜。黑白相片就做的很好,而且大部分排名靠前的图片都包含某种程度上的滤镜使得图片有淡出效果,减少了色彩反差对比。
- 加一个相框。你会注意到经常有白色的水平/垂直的相框出现。
有趣的是,并不是所有规则都适用于男性,我自己浏览过排名靠前2000的自拍照片并且挑选出其中的男性最佳自拍,这是我得到的结果:
[caption id="attachment_6361" align="aligncenter" width="1091"]
从前2000张自拍中挑选出的最佳男性自拍。[/caption]
在这一组的自拍里,我们可以看到自拍者的前额部分都没有被截掉。相反,绝大多数自拍似乎都有着更广一点儿的取镜:照片中可以看见完整的脑袋,肩膀也能看见。同时,自拍里的许多男性似乎都留着一种精致的发型——稍长的刘海向上梳起。尽管如此,我们依旧可以清楚看到,过度饱和使脸部特征溶于画面这一效果在自拍中的显著应用。
让我们也来看一下那些在卷积神经网络看来绝不会收到多少赞的最差自拍吧。由于我的意图在于让大家能够学到提高自拍质量的普遍模式,而不是让那些不巧拍了张不佳自拍的人亮相,所以这些照片会以小得多、更难辨认的形式展示出来。如下图:
[caption id="attachment_6363" align="aligncenter" width="1470"]
根据卷积神经网络判断,50,000张自拍中最差的300张。[/caption]
即便在分辨率如此小的情况下,一些模式还是清晰地显现出来。切忌:
- 光线昏暗时自拍。光线更暗的照片(通常也伴随着更多的噪点)在卷积神经网络的评判下一律排名极低。
- 构图中头部过大。可能也没有谁想看到这样一个逼近的角度吧。
- 群体自拍。和你的朋友们一起自拍的确很有趣,但这并不能成就一张高质量的自拍。让画面保持简洁,画面中只有你自己。但是可不是让你占据整个画面。
- 最后一点,值得注意的是,图片的风格可以解释自拍质量好坏之间极大的浮动性,这与自拍者自身原本的吸引力形成了对比。此外,我们可以松一口气——最佳自拍似乎并非是最暴露的那些。我一度相当担心我那精巧的一亿四千万个卷积神经网络最终会变成一个简单的皮肤组织展示台。
名人们。最后一个有趣的实验,我试着在卷积神经网络上运行一些名流们的自拍,并将结果用连续视觉化进行了分类。最佳自拍位于顶端,卷积网络的评分向右递减直到底部:
[caption id="attachment_6368" align="aligncenter" width="2570"]
卷积神经网络评价下的名人自拍。最具吸引力自拍:顶部左起,接着往右自拍质量递减,然后向底部递减。[/caption]
我们注意到非常有趣的一点,我们之前观察到的一条「获赞法则」(切忌群体自拍)被艾伦·德詹尼斯和一群奥斯卡典礼上的明星们的著名自拍给打破了。卷积网络还是认为这的确是一张非常棒的自拍,将它放在了第二排!棒极了!:)
我们的另一条「获赞法则」(没有男性)则被克里斯·帕拉特的美好肉体(同样在第二排)完全挑战了。同时,荣誉还属于贾斯汀·比伯的挑眉自拍、史蒂芬·扣扣熊和吉米·肥伦的双人自拍(第三排)。詹姆斯·弗兰科的自拍比克里斯暴露的多得多,然而却并没能让卷积网络青眼有加(仅排在第四排)。对于这点,我也表示赞同。
最后,风格的重要性再次彰显出来。一些毫无疑义的高颜值明星由于构图不佳、光线太差等缘故却仍旧出现在结果的底部(比如詹妮弗·洛佩兹可能就是因为照片里头太大)。
探索#自拍#空间
另一个我们可以尝试的有趣的视觉化效果是运用t-SNE算法将这些自拍排列出来。t-SNE是一种绝妙的算法,以至于我都想把它运行到几乎所有我能做到的东西上去。它的妙处在于极其普适且非常有效——它提取出一些事物(在我们这个实验中就是图像),然后将它们排列出来,使得相邻的事物都是相似的。事实上,你可以用t-SNE排列出许多东西,例如Netflix的电影、单词、Twitter 上的文件、ImageNet上的图片,或者真的任何你手头上需要比较相似度的一些东西。在我们这个实验里,我们将根据卷积神经网络感知到的相似度来排列这些自拍。专业点来说,我们这样做依据的就是最后一个完全连接层面中fc7激活的L2规范。如图为视觉化效果:
[caption id="attachment_6366" align="aligncenter" width="800"]
自拍的t-SNE 视觉觉化效果图。高分辨率版本链接 (9MB)[/caption]
你能看到自拍以某种有趣的方式分组集中了起来:群体自拍分布在左上角,一组戴着墨镜/眼镜的自拍在中间偏左分布,特写分布在了底部偏左,一堆对镜全身自拍则位于右上角等等。嗯,我觉得这还是挺有趣的。
寻找自拍的最佳剪裁
另一个我们可以做的实验是用卷积神经网络来自动找出最佳的自拍剪裁。具体操作方法就是,我们拿出一张照片,随意尝试各种可能的剪裁效果,然后选择一个卷积神经网络认为最好的。以下是整个操作过程的四组对比案例——原图在左,经过卷积网络剪裁的在右:
[caption id="attachment_6365" align="aligncenter" width="900"]
四组照片对比展示了原图(左)和卷积神经网络选择出的最佳剪裁后的图片(右)。[/caption]
我们注意到卷积神经网络倾向于让头部占据整个照片1/3的比例,并且截取掉前额。有趣的是,在右下角的图片中,卷积网络决定丢弃自拍中的「自己」,完全失去了重点:)你可以在这些「简单粗暴」的剪裁中发现更多有趣的例子:
[caption id="attachment_6364" align="aligncenter" width="900"]
以上采用了同样的视觉化,原物在左边,最好的剪裁在右边,而我也喜欢右边的。[/caption]
在任何高级用户询问前:是的,我曾试图在图像后和卷积神经网络前嵌入一个空间转换层。然后维持6个参数定义一个随机的仿射剪裁。不幸的是,我没能很好完成工作——优化偶尔会停滞,或产生随机漂移。我也尝试限制向规模/翻译的转变,但毫无帮助。幸运的是,当你变换 3 个参数限值,我们就支持全平台搜索(如上图所示)。
你的自拍照怎么样呢?
想知道卷积神经网络如何评价你的自拍照吗?我将卷积神经网络打包进了推特机器人,这样你就能轻松知道答案。(这个机器人用Python写的,只用了150行代码,包括Caffe/Tweepy代码)。把你的照片发推特(或者链接),然后@deepselfie,这个机器人将扫描你的自拍,并对其进行评价。为了得到最好的结果,请使用正方形照片,否则机器人将不得不自行压缩成正方形,这会导致结果不乐观。机器人会在一分钟内给予回答,除非它出了什么问题(那就稍后再试)。
[caption id="attachment_6369" align="aligncenter" width="1162"]
推特机器人的交互示例[/caption]
在任何人开口问到这一点前,我也试图采用卷积神经网络的较小版本运行在iOS上,让你在自拍时能获取即时反馈,但这被证实是应用于一个快速投入的偏门项目。例如,我第一次在没有类似CUDA的支持下,尝试去写片段着色器,然后搜索一些仅有CPU版本的线程,但最终我无法使它有效实时的工作起来做。。我确实有些事得做。
总结
我希望我为你展示了了卷积神经网络有多么强大。你给它们输入带标签的示例照片,它们学习自动识别这些东西,工作运转高效且杰出(至少在实验时是这样,至少在旦经过训练完毕就表现得非常好就能高效完成工作)。当然,我们仅仅只只触及到了了表层,卷积神经网络被用于许多神经网络中的基本单元构件,它不仅给图片/视频分类,还剪切、识别及描述他们,并同时作用于云或机器上。
作为深度学习的初学者,如果你想了解更多,目前最好的学习课程应该是迈克尔·尼尔森的教程。从那里,我鼓励你首先学习吴恩达创建的Coursera的机器学习课程,然后下一步我建议了解一下为CS231n开设的笔记/作业,这是去年冬天我和飞飞在斯坦福开设的专注于卷积神经网络的课程。2016年1月,我们也将重新开设这堂课,你可以免费在线学习。为了更深入的学习,我将引进Hugo Larochelle的《神经网络》课或目前由Yoshua Bengio,Ian Goodfellow和Aaron Courville编写的《由Yoshua Bengio, Ian Goodfellow和Aaron Courville写的深度学习》书
当然,实践比阅读能让通过实践学的比阅读能够学到更多,因此我建议你玩101 Kaggle Challenges,或开发自己的项目,在这种情况下,我由衷推荐你不仅实践,还应该写下流程文档,然后发到网上供大家分享,例如reddit等机器学习成员集中的技术社区网站。以下是我推荐的3个工具:
- Caffe(C++,Python/Matlab封装),就是我文中提到过的那个。如果你正在做基本的图片分类,Caffe是最简单的,因为在许多情况下,你无需编写代码,只需调用已有的脚本。
- 基于Theano的深度学习库(Python)(Python),如 Keras或 Lasagne,灵活性较强。
- Torch(C++, Lua),我目前在我的研究项目中使用的语言。我把Torch推荐给最高级的用户,因为它提供了大量自由、 灵活、 迅速且简单的抽取方式。
- 还有一些稍新、不成熟但有前景的代码库包括 Nervana 的Neon、 CGT 或在Julia的Mocha。
最后,也有部分公司致力于向大众普及深度学习。其中一个是 MetaMind, 这家公司提供 web 界面使你可以随意放置图片,训练卷积神经网络(他们在云上处理所有的细节) 。 MetaMind和 Clarifai 也提供可调度卷积神经网络的REST应用程序接口。
机器之心编译出品,参与成员: 李小鱼、Chao、安隐、xuminjun1992、柒柒 、妞妞姐姐