http suo.im 3ktor/f9w2v打不开不存在

&figure&&img src=&https://pic2.zhimg.com/v2-5e0de8feebe34a3d1818ed_b.jpg& data-rawwidth=&1100& data-rawheight=&670& class=&origin_image zh-lightbox-thumb& width=&1100& data-original=&https://pic2.zhimg.com/v2-5e0de8feebe34a3d1818ed_r.jpg&&&/figure&&h2&基础概念&/h2&&p&上个月开始从原理层面了解机器学习,选了一本在线电子书《&a href=&https://link.zhihu.com/?target=http%3A//neuralnetworksanddeeplearning.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Neural Networks and Deep Learning&/a&》作为教材,事实证明该书实在不错,让一个毫无神经网络、机器学习背景知识的 PM 很快就读懂了其中的基本原理。&/p&&p&附上此书第一章我的&a href=&https://link.zhihu.com/?target=http%3A//www.mogeha.com/DL_notes.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&读书笔记&/a&,对于 PM 而言,读完第一章就够了,基本概念和方法论在这章里解释得十分清楚。读完之后有一种打开新世界大门的感觉。&/p&&h2&行动诱因&/h2&&p&上周末看到 Twitch 做的 ClipMine,基于游戏直播画面识别出守望先锋、炉石传说中玩家正在玩的英雄和段位,供观众在多个主播间筛选自己想看的英雄。顿时手痒,想着这样的需求在国内直播行业里其实也是存在的,比如将几千个正在直播的王者荣耀直播流识别出当前在玩的英雄,这样观众就可以选择自己想看的英雄专注的看了。&/p&&p&手痒,又碰上周末,看来不得不做点啥了。&/p&&h2&工程分析&/h2&&p&王者荣耀这款游戏,想要识别其中正在玩的英雄,有几个思路:&/p&&p&1. 游戏开始前选择英雄的界面&/p&&figure&&img src=&https://pic2.zhimg.com/v2-192f11cb3a_b.jpg& data-rawwidth=&1600& data-rawheight=&956& class=&origin_image zh-lightbox-thumb& width=&1600& data-original=&https://pic2.zhimg.com/v2-192f11cb3a_r.jpg&&&/figure&&p&2. 游戏开始后加载资源时的 Loading 界面&/p&&figure&&img src=&https://pic1.zhimg.com/v2-26beebc8149_b.jpg& data-rawwidth=&1598& data-rawheight=&898& class=&origin_image zh-lightbox-thumb& width=&1598& data-original=&https://pic1.zhimg.com/v2-26beebc8149_r.jpg&&&/figure&&p&3. 游戏进行中屏幕正中央的英雄本身&/p&&figure&&img src=&https://pic2.zhimg.com/v2-178eb5752d7ebb4f768d3_b.jpg& data-rawwidth=&1280& data-rawheight=&720& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&https://pic2.zhimg.com/v2-178eb5752d7ebb4f768d3_r.jpg&&&/figure&&p&4. 游戏进行中屏幕右下角的技能图标&/p&&figure&&img src=&https://pic4.zhimg.com/v2-156fa688b34f56fd69676_b.jpg& data-rawwidth=&383& data-rawheight=&361& class=&content_image& width=&383&&&/figure&&p&分析如下:&/p&&ul&&li&在整个直播时长中,1 和 2 的时间占比是很短的,而且如果玩家直接直播游戏进行中的画面,那就没法获取英雄信息了。&/li&&li&并且 1 和 2 的界面里,当前玩家所处的位置并不固定,如果还要加上玩家位置的判定,工程复杂度上升不止一点点。&/li&&li&因为英雄在游戏中永远处于正中央,所以 3 其实挺适合用来做训练素材。但考虑到英雄有不同的动作和朝向,最重要的是这个游戏单一英雄还有不同的皮肤。各种条件综合起来,一方面需要提供更多的训练素材,一方面也加大了机器学习的难度。&/li&&li&而 4 这个界面,英雄的技能在较长的时间段内是不会变的,而且位置稳定,在整个直播时长里出现的时间占比也很高,唯一变化较大的是技能发动间歇里的读秒倒计时。综合考虑,4 是最适合用来做训练素材的。&/li&&/ul&&p&确定了这点后,就能理清整个项目的运转流程了:&/p&&ol&&li&获取 60 几个英雄对应的游戏进行中图片,每个英雄不少于 1000 张(拍脑袋的,我也不知道多少张合适)&/li&&li&将 1 中图片的右下角截取出来,作为机器学习的训练资料&/li&&li&运行机器学习代码,训练出可以识别不同英雄技能的模型&/li&&li&从待识别的直播流中抽取画面,截取右下角的技能画面,用 3 中的模型去识别看是哪个英雄的技能,从而完成对直播流英雄的识别&/li&&/ol&&p&流程已然清晰,但后面的工作量才是最大的,先来看看如何获取训练资料吧。&/p&&h2&收集素材&/h2&&p&做机器学习的都知道,写代码不是最难的部分,收集优质的训练素材才是。如何能够快速获得 60 多个英雄分别对应的 1000 张图片呢?且不说找到 6 万多张图片的难度,找到后难道要我人肉来标记哪张图片是哪个英雄?如果真要这么做,估计一个人是很难完成了。&/p&&p&这一次想出的取巧方法是直接去优酷上搜索「王者荣耀」+「英雄名字」,就能搜到很多玩家录好的英雄视频。于是让团队里的同学帮忙,很快收集齐了所有英雄的对战视频各 1 个。然后用 Adapter 这样的软件将视频按一秒一帧转化为几千张图片。(不过一开始没有发现 Adapter 这个软件,当时是用 OpenCV 去一帧帧把视频里的画面读取出来的。)&/p&&p&唯一的坑是优酷上的视频往往并不只是对战过程本身,还会有一些制作者加入的视频特效、文字、转场动画啥的。一开始没留意,污染了一小批训练素材,后来重新找了几个干净的视频解决此问题。&/p&&p&于是就这样,轻松获得了含有英雄标记信息的近 10 万张图片。&/p&&p&后面的事情就简单了,用 OpenCV 统一对图片进行裁剪。一开始是裁到三个技能的区域,但因为这个区域覆盖的面积较大,会包含进来很多不必要的图像信息,导致训练出来的结果不理想。在后期调优时,想到每个英雄的技能其实是唯一的,没必要识别全部,于是将素材全都裁剪到第二个技能,果然大大提升了识别准确度。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-77e0c4dec3eaf7e_b.jpg& data-rawwidth=&808& data-rawheight=&488& class=&origin_image zh-lightbox-thumb& width=&808& data-original=&https://pic1.zhimg.com/v2-77e0c4dec3eaf7e_r.jpg&&&/figure&&h2&技术实施&/h2&&p&早有耳闻 Google 家 TensorFlow 上手容易且性能还不错,加上是 G 家产品,自然和 Python 配合度最好,适合常年写 Python 的我。于是果断开始读 TensorFlow 的&a href=&https://link.zhihu.com/?target=https%3A//www.tensorflow.org/get_started/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&文档&/a&。&/p&&p&不得不说周末那个晚上有很多时间花在了如何在 virtualenv 里安装 TensorFlow 和 OpenCV。网上的教程没有一个是可以完全顺利在 Mac 上跑完的,还好最后在 Google 和 Stack Overflow 的双重加持下,这俩个组件都在我 Mac 上编译成功了。&/p&&p&很快,在 TensorFlow 官方教程里找到一篇关于&a href=&https://link.zhihu.com/?target=https%3A//www.tensorflow.org/tutorials/image_recognition& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&图片识别&/a&的文章。跑了一下 demo,运行正常。于是开始研究如何&a href=&https://link.zhihu.com/?target=https%3A//www.tensorflow.org/tutorials/image_retraining& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&训练自己的模型&/a&。&/p&&p&既然都按照官方教程走了,所以直接用了 Inception V3 的网络结构。近 10 万张图片,在没有 GPU 加持的 Macbook Pro 上,差不多得跑 10 个小时才能跑完第一次训练。&/p&&p&不过其中最耗时是计算 Bottleneck 值,因为这个值在每次训练时其实都不会变。所以教程中会让在第一次计算每张图片的 Bottleneck 值后,将之保存下来,这样下次训练只需要计算新增图片素材的 Bottleneck 值即可,不需要每次都全量计算。这样优化之后,效率飞升。&/p&&p&到此时,已经是周日凌晨 3 点了,赶紧让模型跑起来,睡觉去。&/p&&h2&性能调优&/h2&&p&周日中午醒来,第一次训练已经跑完了,赶紧拿新模型去做各种测试,准确率超乎想象的高。但如「收集素材」那一段里提到,一开始是识别三个技能,所以在某些英雄的识别上不太理想。&/p&&p&将所有素材调整为单个技能截图后,又跑了一次,出结果时已经是周日晚上。这个时候的准确率靠我找到的测试图片已经没有失败的例子了。&/p&&p&截止这个时候,识别单张图片大概需要 5 秒,倒也不是不能接受,但还想更快。在没有 Nvidia 显卡的情况下,只能依赖于在本地编译 TensorFlow,从而让 TensorFlow 能用上本地 CPU 的 SSE、AVX 这类指令,加快运算速度。如何在 Mac 上编译 TensorFlow,可以&a href=&https://link.zhihu.com/?target=https%3A//www.tensorflow.org/install/install_sources& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&参考这里&/a&。&/p&&h2&附加功能&/h2&&p&在本地已经能完美识别英雄了,但总想着让更多的同事能体验这个功能。周二晚回家想起了之前用 itchat 写的微信机器人,于是立马将机器人和王者识别代码结合起来,实现了在微信里给机器人发游戏图片,机器人立即回复这个图片里的英雄是谁。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-5e0de8feebe34a3d1818ed_b.jpg& data-rawwidth=&1100& data-rawheight=&670& class=&origin_image zh-lightbox-thumb& width=&1100& data-original=&https://pic2.zhimg.com/v2-5e0de8feebe34a3d1818ed_r.jpg&&&/figure&&h2&结语&/h2&&p&实际的学习和开发时间就是周六晚 8 点到凌晨 3 点。这 8 个小时让我从原理及代码层面认识到了机器学习的魅力和实施细节,真真切切的看到了另一个世界的入口以及未来无穷的可能性。&/p&&p&最大的触动是开始思考未来产品经理在设计产品逻辑时,如果理解机器学习,那么很多以往被认为不可能的事情,都将成为产品逻辑的一部分。而能否建立这种新的认知,运用好新的工具,将在未来某些领域里区分出产品经理的高下。&/p&&p&学习,是一个 PM 永远不该停下的生存技巧。&/p&
基础概念上个月开始从原理层面了解机器学习,选了一本在线电子书《》作为教材,事实证明该书实在不错,让一个毫无神经网络、机器学习背景知识的 PM 很快就读懂了其中的基本原理。附上此书第一章我的,对于 PM 而…
&p&转载请注明:&a href=&https://zhuanlan.zhihu.com/easyml& class=&internal&&炼丹实验室&/a&&br&&/p&&p&之前曾经写过一篇文章,讲了一些深度学习训练的技巧,其中包含了部分调参心得:&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&深度学习训练心得&/a&。不过由于一般深度学习实验,相比普通机器学习任务,时间较长,因此调参技巧就显得尤为重要。同时个人实践中,又有一些新的调参心得,因此这里单独写一篇文章,谈一下自己对深度学习调参的理解,大家如果有其他技巧,也欢迎多多交流。&/p&&h1&好的实验环境是成功的一半&/h1&&p&由于深度学习实验超参众多,代码风格良好的实验环境,可以让你的人工或者自动调参更加省力,有以下几点可能需要注意:&/p&&ul&&li&将各个参数的设置部分集中在一起。如果参数的设置分布在代码的各个地方,那么修改的过程想必会非常痛苦。&/li&&li&可以输出模型的损失函数值以及训练集和验证集上的准确率。&/li&&li&可以考虑设计一个子程序,可以根据给定的参数,启动训练并监控和周期性保存评估结果。再由一个主程序,分配参数以及并行启动一系列子程序。&/li&&/ul&&h1&画图&/h1&&p&画图是一个很好的习惯,一般是训练数据遍历一轮以后,就输出一下训练集和验证集准确率。同时画到一张图上。这样训练一段时间以后,如果模型一直没有收敛,那么就可以停止训练,尝试其他参数了,以节省时间。 &br&如果训练到最后,训练集,测试集准确率都很低,那么说明模型有可能欠拟合。那么后续调节参数方向,就是增强模型的拟合能力。例如增加网络层数,增加节点数,减少dropout值,减少L2正则值等等。 &br&如果训练集准确率较高,测试集准确率比较低,那么模型有可能过拟合,这个时候就需要向提高模型泛化能力的方向,调节参数。&/p&&h1&从粗到细分阶段调参&/h1&&p&实践中,一般先进行初步范围搜索,然后根据好结果出现的地方,再缩小范围进行更精细的搜索。&/p&&ol&&li&建议先参考相关论文,以论文中给出的参数作为初始参数。至少论文中的参数,是个不差的结果。&/li&&li&如果找不到参考,那么只能自己尝试了。可以先从比较重要,对实验结果影响比较大的参数开始,同时固定其他参数,得到一个差不多的结果以后,在这个结果的基础上,再调其他参数。例如学习率一般就比正则值,dropout值重要的话,学习率设置的不合适,不仅结果可能变差,模型甚至会无法收敛。&/li&&li&如果实在找不到一组参数,可以让模型收敛。那么就需要检查,是不是其他地方出了问题,例如模型实现,数据等等。可以参考我写的&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&深度学习网络调试技巧&/a&&/li&&/ol&&h1&提高速度&/h1&&p&调参只是为了寻找合适的参数,而不是产出最终模型。一般在小数据集上合适的参数,在大数据集上效果也不会太差。因此可以尝试对数据进行精简,以提高速度,在有限的时间内可以尝试更多参数。&/p&&ul&&li&对训练数据进行采样。例如原来100W条数据,先采样成1W,进行实验看看。&/li&&li&减少训练类别。例如手写数字识别任务,原来是10个类别,那么我们可以先在2个类别上训练,看看结果如何。&/li&&/ul&&h1&超参数范围&/h1&&p&建议优先在对数尺度上进行超参数搜索。比较典型的是学习率和正则化项,我们可以从诸如0.001 0.01 0.1 1 10,以10为阶数进行尝试。因为他们对训练的影响是相乘的效果。不过有些参数,还是建议在原始尺度上进行搜索,例如dropout值: 0.3 0.5 0.7)。&/p&&h1&经验参数&/h1&&p&这里给出一些参数的经验值,避免大家调参的时候,毫无头绪。&/p&&ul&&li&learning rate: 1 0.1 0.01 0.001, 一般从1开始尝试。很少见learning rate大于10的。学习率一般要随着训练进行衰减。衰减系数一般是0.5。 衰减时机,可以是验证集准确率不再上升时,或固定训练多少个周期以后。 &br&不过更建议使用自适应梯度的办法,例如adam,adadelta,rmsprop等,这些一般使用相关论文提供的默认值即可,可以避免再费劲调节学习率。对RNN来说,有个经验,如果RNN要处理的序列比较长,或者RNN层数比较多,那么learning rate一般小一些比较好,否则有可能出现结果不收敛,甚至Nan等问题。&/li&&li&网络层数: 先从1层开始。&/li&&li&每层结点数: 16 32 128,超过1000的情况比较少见。超过1W的从来没有见过。&/li&&li&batch size: 128上下开始。batch size值增加,的确能提高训练速度。但是有可能收敛结果变差。如果显存大小允许,可以考虑从一个比较大的值开始尝试。因为batch size太大,一般不会对结果有太大的影响,而batch size太小的话,结果有可能很差。&/li&&li&clip c(梯度裁剪): 限制最大梯度,其实是value = sqrt(w1^2+w2^2….),如果value超过了阈值,就算一个衰减系系数,让value的值等于阈值: 5,10,15&/li&&li&dropout: 0.5&/li&&li&L2正则:1.0,超过10的很少见。&/li&&li&词向量embedding大小:128,256&/li&&li&正负样本比例: 这个是非常忽视,但是在很多分类问题上,又非常重要的参数。很多人往往习惯使用训练数据中默认的正负类别比例,当训练数据非常不平衡的时候,模型很有可能会偏向数目较大的类别,从而影响最终训练结果。除了尝试训练数据默认的正负类别比例之外,建议对数目较小的样本做过采样,例如进行复制。提高他们的比例,看看效果如何,这个对多分类问题同样适用。 &br&在使用mini-batch方法进行训练的时候,尽量让一个batch内,各类别的比例平衡,这个在图像识别等多分类任务上非常重要。&/li&&/ul&&h1&自动调参&/h1&&p&人工一直盯着实验,毕竟太累。自动调参当前也有不少研究。下面介绍几种比较实用的办法:&/p&&ul&&li&Gird Search. 这个是最常见的。具体说,就是每种参数确定好几个要尝试的值,然后像一个网格一样,把所有参数值的组合遍历一下。优点是实现简单暴力,如果能全部遍历的话,结果比较可靠。缺点是太费时间了,特别像神经网络,一般尝试不了太多的参数组合。&/li&&li&Random Search。Bengio在&a href=&https://link.zhihu.com/?target=http%3A//www.jmlr.org/papers/volume13/bergstra12a/bergstra12a.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Random Search for Hyper-Parameter Optimization&/a&中指出,Random Search比Gird Search更有效。实际操作的时候,一般也是先用Gird Search的方法,得到所有候选参数,然后每次从中随机选择进行训练。&/li&&li&Bayesian Optimization. 贝叶斯优化,考虑到了不同参数对应的实验结果值,因此更节省时间。和网络搜索相比简直就是老牛和跑车的区别。具体原理可以参考这个论文: &a href=&https://link.zhihu.com/?target=http%3A//papers.nips.cc/paper/4522-practical-bayesian-optimization-of-machine-learning-algorithms.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Practical Bayesian Optimization of Machine Learning Algorithms&/a& ,这里同时推荐两个实现了贝叶斯调参的Python库,可以上手即用:&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//github.com/jaberg/hyperopt& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&jaberg/hyperopt&/a&, 比较简单。&/li&&li&&a href=&https://link.zhihu.com/?target=https%3A//github.com/fmfn/BayesianOptimization& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&fmfn/BayesianOptimization&/a&, 比较复杂,支持并行调参。&/li&&/ul&&/li&&/ul&&h1&总结&/h1&&ul&&li&合理性检查,确定模型,数据和其他地方没有问题。&/li&&li&训练时跟踪损失函数值,训练集和验证集准确率。&/li&&li&使用Random Search来搜索最优超参数,分阶段从粗(较大超参数范围训练较少周期)到细(较小超参数范围训练较长周期)进行搜索。&/li&&/ul&&h1&参考资料&/h1&&p&这里列了一些参数资料,大家有时间,可以进一步阅读。 &br&&a href=&https://link.zhihu.com/?target=https%3A//arxiv.org/abs/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Practical recommendations for gradient-based training of deep architectures by Yoshua Bengio (2012)&/a&&br&&a href=&https://link.zhihu.com/?target=http%3A//yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Efficient BackProp, by Yann LeCun, Léon Bottou, Genevieve Orr and Klaus-Robert Müller&/a&&br&&a href=&https://link.zhihu.com/?target=http%3A//www.springer.com/computer/theoretical%2Bcomputer%2Bscience/book/978-3-642-35288-1& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Neural Networks: Tricks of the Trade, edited by Grégoire Montavon, Geneviève Orr, and Klaus-Robert Müller.&/a&&/p&
转载请注明: 之前曾经写过一篇文章,讲了一些深度学习训练的技巧,其中包含了部分调参心得:。不过由于一般深度学习实验,相比普通机器学习任务,时间较长,因此调参技巧就显得尤为重要。同时个人实践中,又有一些新的调参心得…
&figure&&img src=&https://pic4.zhimg.com/v2-ab904178abfe2d0fa7c0584_b.jpg& data-rawwidth=&1702& data-rawheight=&642& class=&origin_image zh-lightbox-thumb& width=&1702& data-original=&https://pic4.zhimg.com/v2-ab904178abfe2d0fa7c0584_r.jpg&&&/figure&&p&近来在同时做一个应用深度学习解决淘宝商品的类目预测问题的项目,恰好硕士毕业时论文题目便是文本分类问题,趁此机会总结下文本分类领域特别是应用深度学习解决文本分类的相关的思路、做法和部分实践的经验。&/p&&p&&b&业务问题描述&/b&:&/p&&p&淘宝商品的一个典型的例子见下图,图中商品的标题是“&u&夏装雪纺条纹短袖t恤女春半袖衣服夏天中长款大码胖mm显瘦上衣夏&/u&”。淘宝网后台是通过树形的多层的类目体系管理商品的,覆盖叶子类目数量达上万个,商品量也是10亿量级,我们是任务是根据商品标题预测其所在叶子类目,示例中商品归属的类目为“女装/女士精品&&蕾丝衫/雪纺衫”。很显然,这是一个非常典型的短文本多分类问题。接下来分别会介绍下文本分类传统和深度学习的做法,最后简单梳理下实践的经验。&/p&&br&&figure&&img src=&https://pic4.zhimg.com/v2-e4ac260cc61de_b.jpg& data-rawwidth=&1002& data-rawheight=&527& class=&origin_image zh-lightbox-thumb& width=&1002& data-original=&https://pic4.zhimg.com/v2-e4ac260cc61de_r.jpg&&&/figure&&br&&h2&&b&一、传统文本分类方法&/b&&/h2&&p&文本分类问题算是自然语言处理领域中一个非常经典的问题了,相关研究最早可以追溯到上世纪50年代,当时是通过专家规则(Pattern)进行分类,甚至在80年代初一度发展到利用知识工程建立专家系统,这样做的好处是短平快的解决top问题,但显然天花板非常低,不仅费时费力,覆盖的范围和准确率都非常有限。&/p&&br&&p&后来伴随着统计学习方法的发展,特别是90年代后互联网在线文本数量增长和机器学习学科的兴起,逐渐形成了一套解决大规模文本分类问题的经典玩法,这个阶段的主要套路是人工特征工程+浅层分类模型。训练文本分类器过程见下图:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-e8ccfb6b7e58_b.jpg& data-rawwidth=&1991& data-rawheight=&469& class=&origin_image zh-lightbox-thumb& width=&1991& data-original=&https://pic1.zhimg.com/v2-e8ccfb6b7e58_r.jpg&&&/figure&&p&整个文本分类问题就拆分成了特征工程和分类器两部分,玩机器学习的同学对此自然再熟悉不过了&/p&&p&&b&1.1 特征工程&/b&&/p&&br&&p&特征工程在机器学习中往往是最耗时耗力的,但却极其的重要。抽象来讲,机器学习问题是把数据转换成信息再提炼到知识的过程,特征是“数据--&信息”的过程,决定了结果的上限,而分类器是“信息--&知识”的过程,则是去逼近这个上限。然而特征工程不同于分类器模型,不具备很强的通用性,往往需要结合对特征任务的理解。&/p&&p&文本分类问题所在的自然语言领域自然也有其特有的特征处理逻辑,传统分本分类任务大部分工作也在此处。文本特征工程分位文本预处理、特征提取、文本表示三个部分,最终目的是把文本转换成计算机可理解的格式,并封装足够用于分类的信息,即很强的特征表达能力。&/p&&p&&b&1)文本预处理&/b&&/p&&p&文本预处理过程是在文本中提取关键词表示文本的过程,中文文本处理中主要包括文本分词和去停用词两个阶段。之所以进行分词,是因为很多研究表明特征粒度为词粒度远好于字粒度,其实很好理解,因为大部分分类算法不考虑词序信息,基于字粒度显然损失了过多“n-gram”信息。&/p&&p&具体到中文分词,不同于英文有天然的空格间隔,需要设计复杂的分词算法。传统算法主要有基于字符串匹配的正向/逆向/双向最大匹配;基于理解的句法和语义分析消歧;基于统计的互信息/CRF方法。近年来随着深度学习的应用,WordEmbedding + Bi-LSTM+CRF方法逐渐成为主流,本文重点在文本分类,就不展开了。而停止词是文本中一些高频的代词连词介词等对文本分类无意义的词,通常维护一个停用词表,特征提取过程中删除停用表中出现的词,本质上属于特征选择的一部分。&/p&&p&经过文本分词和去停止词之后淘宝商品示例标题变成了下图“ / ”分割的一个个关键词的形式:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&夏装 / 雪纺 / 条纹 / 短袖 / t恤 / 女 / 春 / 半袖 / 衣服 / 夏天 / 中长款 / 大码 / 胖mm / 显瘦 / 上衣 / 夏
&/code&&/pre&&/div&&p&&b&2)文本表示和特征提取&/b&&/p&&p&&b&文本表示:&/b&&/p&&p&文本表示的目的是把文本预处理后的转换成计算机可理解的方式,是决定文本分类质量最重要的部分。传统做法常用词袋模型(BOW, Bag Of Words)或向量空间模型(Vector Space Model),最大的不足是忽略文本上下文关系,每个词之间彼此独立,并且无法表征语义信息。词袋模型的示例如下:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
( 0, 0, 0, 0, .... , 1, ... 0, 0, 0, 0)
&/code&&/pre&&/div&&p&一般来说词库量至少都是百万级别,因此词袋模型有个两个最大的问题:高纬度、高稀疏性。词袋模型是向量空间模型的基础,因此向量空间模型通过特征项选择降低维度,通过特征权重计算增加稠密性。&/p&&br&&p&&b&特征提取:&/b&&/p&&p&向量空间模型的文本表示方法的特征提取对应特征项的选择和特征权重计算两部分。特征选择的基本思路是根据某个评价指标独立的对原始特征项(词项)进行评分排序,从中选择得分最高的一些特征项,过滤掉其余的特征项。常用的评价有文档频率、互信息、信息增益、χ?统计量等。&/p&&p&特征权重主要是经典的TF-IDF方法及其扩展方法,主要思路是一个词的重要度与在类别内的词频成正比,与所有类别出现的次数成反比。&/p&&p&&b&3)基于语义的文本表示&/b&&/p&&p&传统做法在文本表示方面除了向量空间模型,还有基于语义的文本表示方法,比如LDA主题模型、LSI/PLSI概率潜在语义索引等方法,一般认为这些方法得到的文本表示可以认为文档的深层表示,而word embedding文本分布式表示方法则是深度学习方法的重要基础,下文会展现。&/p&&p&&b&1.2 分类器&/b&&/p&&p&分类器基本都是统计分类方法了,基本上大部分机器学习方法都在文本分类领域有所应用,比如朴素贝叶斯分类算法(Na?ve Bayes)、KNN、SVM、最大熵和神经网络等等,传统分类模型不是本文重点,在这里就不展开了。&br&&/p&&br&&br&&h2&&b&二、深度学习&/b&&b&文本分类&/b&&b&方法&/b&&/h2&&p&上文介绍了传统的文本分类做法,传统做法主要问题的文本表示是高纬度高稀疏的,特征表达能力很弱,而且神经网络很不擅长对此类数据的处理;此外需要人工进行特征工程,成本很高。而深度学习最初在之所以图像和语音取得巨大成功,一个很重要的原因是图像和语音原始数据是连续和稠密的,有局部相关性,。应用深度学习解决大规模文本分类问题最重要的是解决文本表示,再利用CNN/RNN等网络结构自动获取特征表达能力,去掉繁杂的人工特征工程,端到端的解决问题。接下来会分别介绍:&/p&&br&&p&&b&2.1 文本的分布式表示:词向量(word embedding)&/b&&/p&&br&&p&分布式表示(Distributed Representation)其实Hinton 最早在1986年就提出了,基本思想是将每个词表达成 n 维稠密、连续的实数向量,与之相对的one-hot encoding向量空间只有一个维度是1,其余都是0。分布式表示最大的优点是具备非常powerful的特征表达能力,比如 n 维向量每维 k 个值,可以表征 &img src=&https://www.zhihu.com/equation?tex=k%5E%7Bn%7D& alt=&k^{n}& eeimg=&1&& 个概念。事实上,不管是神经网络的隐层,还是多个潜在变量的概率主题模型,都是应用分布式表示。下图是03年Bengio在 &a href=&https://link.zhihu.com/?target=http%3A//www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&A Neural Probabilistic Language Model&/a& 的网络结构:&/p&&br&&p&&figure&&img src=&https://pic1.zhimg.com/v2-dc007baa415cf419cc2de_b.jpg& data-rawwidth=&1164& data-rawheight=&666& class=&origin_image zh-lightbox-thumb& width=&1164& data-original=&https://pic1.zhimg.com/v2-dc007baa415cf419cc2de_r.jpg&&&/figure&这篇文章提出的神经网络语言模型(NNLM,Neural Probabilistic Language Model)采用的是文本分布式表示,即每个词表示为稠密的实数向量。NNLM模型的目标是构建语言模型:&/p&&p&&figure&&img src=&https://pic1.zhimg.com/v2-855f785db4_b.jpg& data-rawwidth=&1054& data-rawheight=&54& class=&origin_image zh-lightbox-thumb& width=&1054& data-original=&https://pic1.zhimg.com/v2-855f785db4_r.jpg&&&/figure&词的分布式表示即词向量(word embedding)是训练语言模型的一个附加产物,即图中的Matrix C。&/p&&br&尽管Hinton 86年就提出了词的分布式表示,Bengio 03年便提出了NNLM,词向量真正火起来是google Mikolov 13年发表的两篇word2vec的文章 &a href=&https://link.zhihu.com/?target=http%3A//ttic.uchicago.edu/%7Ehaotang/speech/.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Efficient Estimation of Word Representations in Vector Space&/a& 和 &a href=&https://link.zhihu.com/?target=https%3A//papers.nips.cc/paper/5021-distributed-representations-of-words-and-phrases-and-their-compositionality.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Distributed Representations of Words and Phrases and their Compositionality&/a&,更重要的是发布了简单好用的&a href=&https://link.zhihu.com/?target=https%3A//code.google.com/archive/p/word2vec/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&word2vec工具包&/a&,在语义维度上得到了很好的验证,极大的推进了文本分析的进程。下图是文中提出的CBOW 和 Skip-Gram两个模型的结构,基本类似于NNLM,不同的是模型去掉了非线性隐层,预测目标不同,CBOW是上下文词预测当前词,Skip-Gram则相反。&figure&&img src=&https://pic3.zhimg.com/v2-04bfcae5251_b.jpg& data-rawwidth=&1420& data-rawheight=&610& class=&origin_image zh-lightbox-thumb& width=&1420& data-original=&https://pic3.zhimg.com/v2-04bfcae5251_r.jpg&&&/figure&&p&除此之外,提出了Hierarchical Softmax 和 Negative Sample两个方法,很好的解决了计算有效性,事实上这两个方法都没有严格的理论证明,有些trick之处,非常的实用主义。详细的过程不再阐述了,有兴趣深入理解word2vec的,推荐读读这篇很不错的paper:&a href=&https://link.zhihu.com/?target=http%3A//www-personal.umich.edu/%7Eronxin/pdf/w2vexp.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&word2vec Parameter Learning Explained&/a&。额外多提一点,实际上word2vec学习的向量和真正语义还有差距,更多学到的是具备相似上下文的词,比如“good”“bad”相似度也很高,反而是文本分类任务输入有监督的语义能够学到更好的语义表示,有机会后续系统分享下。&/p&&p&至此,文本的表示通过词向量的表示方式,把文本数据从高纬度高稀疏的神经网络难处理的方式,变成了类似图像、语音的的连续稠密数据。深度学习算法本身有很强的数据迁移性,很多之前在图像领域很适用的深度学习算法比如CNN等也可以很好的迁移到文本领域了,下一小节具体阐述下文本分类领域深度学习的方法。&/p&&br&&p&&b&2.2 深度学习文本分类模型&/b&&/p&&p&词向量解决了文本表示的问题,该部分介绍的文本分类模型则是利用CNN/RNN等深度学习网络及其变体解决自动特征提取(即特征表达)的问题。&/p&&br&&p&&b&1)fastText&/b&&/p&&p&fastText 是上文提到的 word2vec 作者 Mikolov 转战 Facebook 后16年7月刚发表的一篇论文 &a href=&https://link.zhihu.com/?target=https%3A//arxiv.org/pdf/v2.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Bag of Tricks for Efficient Text Classification&/a&。把 fastText 放在此处并非因为它是文本分类的主流做法,而是它极致简单,模型图见下:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-ec902f184beacb26cebd4dd_b.jpg& data-rawwidth=&2062& data-rawheight=&1046& class=&origin_image zh-lightbox-thumb& width=&2062& data-original=&https://pic1.zhimg.com/v2-ec902f184beacb26cebd4dd_r.jpg&&&/figure&&p&原理是把句子中所有的词向量进行平均(某种意义上可以理解为只有一个avg pooling特殊CNN),然后直接接 softmax 层。其实文章也加入了一些 n-gram 特征的 trick 来捕获局部序列信息。文章倒没太多信息量,算是“水文”吧,带来的思考是文本分类问题是有一些“线性”问题的部分[from项亮],也就是说不必做过多的非线性转换、特征组合即可捕获很多分类信息,因此有些任务即便简单的模型便可以搞定了。&/p&&p&&b&2)TextCNN&/b&&br&&/p&&p&本篇文章的题图选用的就是14年这篇文章提出的TextCNN的结构(见下图)。fastText 中的网络结果是完全没有考虑词序信息的,而它用的 n-gram 特征 trick 恰恰说明了局部序列信息的重要意义。&a href=&https://link.zhihu.com/?target=http%3A//colah.github.io/posts/2014-07-Understanding-Convolutions/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&卷积神经网络(CNN Convolutional Neural Network)&/a&最初在图像领域取得了巨大成功,CNN原理就不讲了,核心点在于可以&b&捕捉局部相关性&/b&,具体到文本分类任务中可以利用CNN来提取句子中类似 n-gram 的关键信息。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-ab904178abfe2d0fa7c0584_b.jpg& data-rawwidth=&1702& data-rawheight=&642& class=&origin_image zh-lightbox-thumb& width=&1702& data-original=&https://pic4.zhimg.com/v2-ab904178abfe2d0fa7c0584_r.jpg&&&/figure&&p&TextCNN的详细过程原理图见下:&br&&/p&&p&&figure&&img src=&https://pic3.zhimg.com/v2-bb10ad5bbdcf887e60a6_b.jpg& data-rawwidth=&1270& data-rawheight=&1244& class=&origin_image zh-lightbox-thumb& width=&1270& data-original=&https://pic3.zhimg.com/v2-bb10ad5bbdcf887e60a6_r.jpg&&&/figure&&b&TextCNN详细过程&/b&:第一层是图中最左边的7乘5的句子矩阵,每行是词向量,维度=5,这个可以类比为图像中的原始像素点了。然后经过有 filter_size=(2,3,4) 的一维卷积层,每个filter_size 有两个输出 channel。第三层是一个1-max pooling层,这样不同长度句子经过pooling层之后都能变成定长的表示了,最后接一层全连接的 softmax 层,输出每个类别的概率。&/p&&p&&b&特征&/b&:这里的特征就是词向量,有静态(static)和非静态(non-static)方式。static方式采用比如word2vec预训练的词向量,训练过程不更新词向量,实质上属于迁移学习了,特别是数据量比较小的情况下,采用静态的词向量往往效果不错。non-static则是在训练过程中更新词向量。推荐的方式是 non-static 中的 fine-tunning方式,它是以预训练(pre-train)的word2vec向量初始化词向量,训练过程中调整词向量,能加速收敛,当然如果有充足的训练数据和资源,直接随机初始化词向量效果也是可以的。&/p&&br&&p&&b&通道(Channels)&/b&:图像中可以利用 (R, G, B) 作为不同channel,而文本的输入的channel通常是不同方式的embedding方式(比如 word2vec或Glove),实践中也有利用静态词向量和fine-tunning词向量作为不同channel的做法。&br&&/p&&p&&b&一维卷积(conv-1d)&/b&:图像是二维数据,经过词向量表达的文本为一维数据,因此在TextCNN卷积用的是一维卷积。一维卷积带来的问题是需要设计通过不同 filter_size 的 filter 获取不同宽度的视野。&/p&&p&&b&Pooling层&/b&:利用CNN解决文本分类问题的文章还是很多的,比如这篇 &a href=&https://link.zhihu.com/?target=https%3A//arxiv.org/pdf/.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&A Convolutional Neural Network for Modelling Sentences&/a& 最有意思的输入是在 pooling 改成 (dynamic) k-max pooling ,pooling阶段保留 k 个最大的信息,保留了全局的序列信息。比如在情感分析场景,举个例子:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
“ 我觉得这个地方景色还不错,但是人也实在太多了 ”
&/code&&/pre&&/div&&p&虽然前半部分体现情感是正向的,全局文本表达的是偏负面的情感,利用 k-max pooling能够很好捕捉这类信息。&/p&&p&&b&3)TextRNN&/b&&/p&&br&&p&尽管TextCNN能够在很多任务里面能有不错的表现,但CNN有个最大问题是固定 filter_size 的视野,一方面无法建模更长的序列信息,另一方面 filter_size 的超参调节也很繁琐。CNN本质是做文本的特征表达工作,而自然语言处理中更常用的是递归神经网络(RNN, Recurrent Neural Network),能够更好的表达上下文信息。具体在文本分类任务中,Bi-directional RNN(实际使用的是双向LSTM)从某种意义上可以理解为可以捕获变长且双向的的 &n-gram& 信息。&/p&&p&RNN算是在自然语言处理领域非常一个标配网络了,在序列标注/命名体识别/seq2seq模型等很多场景都有应用,&a href=&https://link.zhihu.com/?target=https%3A//www.ijcai.org/Proceedings/16/Papers/408.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Recurrent Neural Network for Text Classification with Multi-Task Learning&/a&文中介绍了RNN用于分类问题的设计,下图LSTM用于网络结构原理示意图,示例中的是利用最后一个词的结果直接接全连接层softmax输出了。&/p&&br&&figure&&img src=&https://pic1.zhimg.com/v2-92e49aef6626add56e85c2ee1b36e9aa_b.jpg& data-rawwidth=&728& data-rawheight=&228& class=&origin_image zh-lightbox-thumb& width=&728& data-original=&https://pic1.zhimg.com/v2-92e49aef6626add56e85c2ee1b36e9aa_r.jpg&&&/figure&&br&&p&&b&4)TextRNN + Attention&/b&&/p&&p&CNN和RNN用在文本分类任务中尽管效果显著,但都有一个不足的地方就是不够直观,可解释性不好,特别是在分析badcase时候感受尤其深刻。而注意力(Attention)机制是自然语言处理领域一个常用的建模长时间记忆机制,能够很直观的给出每个词对结果的贡献,基本成了Seq2Seq模型的标配了。实际上文本分类从某种意义上也可以理解为一种特殊的Seq2Seq,所以考虑把Attention机制引入近来,研究了下学术界果然有类似做法。&/p&&br&&p&&b&Attention机制介绍&/b&:&/p&&p&详细介绍Attention恐怕需要一小篇文章的篇幅,感兴趣的可参考14年这篇paper &a href=&https://link.zhihu.com/?target=https%3A//arxiv.org/pdf/.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&NEURAL MACHINE TRANSLATION BY JOINTLY LEARNING TO ALIGN AND TRANSLATE&/a&。&/p&&p&以机器翻译为例简单介绍下,下图中 &img src=&https://www.zhihu.com/equation?tex=x_%7Bt%7D& alt=&x_{t}& eeimg=&1&& 是源语言的一个词,&img src=&https://www.zhihu.com/equation?tex=y_%7Bt%7D& alt=&y_{t}& eeimg=&1&& 是目标语言的一个词,机器翻译的任务就是给定源序列得到目标序列。翻译 &img src=&https://www.zhihu.com/equation?tex=y_%7Bt%7D& alt=&y_{t}& eeimg=&1&& 的过程产生取决于上一个词 &img src=&https://www.zhihu.com/equation?tex=y_%7Bt-1%7D& alt=&y_{t-1}& eeimg=&1&& 和源语言的词的表示 &img src=&https://www.zhihu.com/equation?tex=h_%7Bj%7D& alt=&h_{j}& eeimg=&1&&(&img src=&https://www.zhihu.com/equation?tex=x_%7Bj%7D& alt=&x_{j}& eeimg=&1&& 的 bi-RNN 模型的表示),而每个词所占的权重是不一样的。比如源语言是中文 “我 / 是 / 中国人” 目标语言 “i / am / Chinese”,翻译出“Chinese”时候显然取决于“中国人”,而与“我 / 是”基本无关。下图公式, &img src=&https://www.zhihu.com/equation?tex=%5Calpha+_%7Bij%7D& alt=&\alpha _{ij}& eeimg=&1&& 则是翻译英文第 &img src=&https://www.zhihu.com/equation?tex=i& alt=&i& eeimg=&1&& 个词时,中文第 &img src=&https://www.zhihu.com/equation?tex=j& alt=&j& eeimg=&1&& 个词的贡献,也就是注意力。显然在翻译“Chinese”时,“中国人”的注意力值非常大。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-dedfe7efcf12ae_b.jpg& data-rawwidth=&2104& data-rawheight=&922& class=&origin_image zh-lightbox-thumb& width=&2104& data-original=&https://pic4.zhimg.com/v2-dedfe7efcf12ae_r.jpg&&&/figure&&figure&&img src=&https://pic2.zhimg.com/v2-0ebc7b64a7d34a908b8d82d87c92f6b8_b.jpg& data-rawwidth=&1824& data-rawheight=&156& class=&origin_image zh-lightbox-thumb& width=&1824& data-original=&https://pic2.zhimg.com/v2-0ebc7b64a7d34a908b8d82d87c92f6b8_r.jpg&&&/figure&&p&Attention的核心point是在翻译每个目标词(或 预测商品标题文本所属类别)所用的上下文是不同的,这样的考虑显然是更合理的。&/p&&p&&b&TextRNN + Attention 模型&/b&:&br&&/p&&p&我们参考了这篇文章 &a href=&https://link.zhihu.com/?target=https%3A//www.cs.cmu.edu/%7Ediyiy/docs/naacl16.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Hierarchical Attention Networks for Document Classification&/a&,下图是模型的网络结构图,它一方面用层次化的结构保留了文档的结构,另一方面在word-level和sentence-level。淘宝标题场景只需要 word-level 这一层的 Attention 即可。&/p&&p&&figure&&img src=&https://pic3.zhimg.com/v2-4ff2c8099ccf0b2d8eb963a0ac248296_b.jpg& data-rawwidth=&2042& data-rawheight=&1356& class=&origin_image zh-lightbox-thumb& width=&2042& data-original=&https://pic3.zhimg.com/v2-4ff2c8099ccf0b2d8eb963a0ac248296_r.jpg&&&/figure&加入Attention之后最大的好处自然是能够直观的解释各个句子和词对分类类别的重要性。&/p&&p&&b&5)TextRCNN(TextRNN + CNN)&/b&&/p&&p&我们参考的是中科院15年发表在AAAI上的这篇文章 Recurrent Convolutional Neural Networks for Text Classification 的结构:&/p&&br&&figure&&img src=&https://pic1.zhimg.com/v2-c0941fece21de00065aa92_b.jpg& data-rawwidth=&1508& data-rawheight=&590& class=&origin_image zh-lightbox-thumb& width=&1508& data-original=&https://pic1.zhimg.com/v2-c0941fece21de00065aa92_r.jpg&&&/figure&&p&利用前向和后向RNN得到每个词的前向和后向上下文的表示:&/p&&figure&&img src=&https://pic3.zhimg.com/v2-d97b136cbb9cde0fd8b4_b.jpg& data-rawwidth=&1022& data-rawheight=&102& class=&origin_image zh-lightbox-thumb& width=&1022& data-original=&https://pic3.zhimg.com/v2-d97b136cbb9cde0fd8b4_r.jpg&&&/figure&&p&这样词的表示就变成词向量和前向后向上下文向量concat起来的形式了,即:&br&&figure&&img src=&https://pic3.zhimg.com/v2-152ed3f73_b.jpg& data-rawwidth=&976& data-rawheight=&44& class=&origin_image zh-lightbox-thumb& width=&976& data-original=&https://pic3.zhimg.com/v2-152ed3f73_r.jpg&&&/figure&最后再接跟TextCNN相同卷积层,pooling层即可,唯一不同的是卷积层 filter_size = 1就可以了,不再需要更大 filter_size 获得更大视野,这里词的表示也可以只用双向RNN输出。&/p&&br&&br&&h2&&b&三、一点经验&/b&&/h2&&p&理论和实践之间的Gap往往差异巨大,学术paper更关注的是模型架构设计的新颖性等,更重要的是新的思路;而实践最重要的是在落地场景的效果,关注的点和方法都不一样。这部分简单梳理实际做项目过程中的一点经验教训。&/p&&br&&p&&b&模型显然并不是最重要的&/b&:不能否认,好的模型设计对拿到好结果的至关重要,也更是学术关注热点。但实际使用中,模型的工作量占的时间其实相对比较少。虽然再第二部分介绍了5种CNN/RNN及其变体的模型,实际中文本分类任务单纯用CNN已经足以取得很不错的结果了,我们的实验测试RCNN对准确率提升大约1%,并不是十分的显著。最佳实践是先用TextCNN模型把整体任务效果调试到最好,再尝试改进模型。&/p&&p&&b&理解你的数据&/b&:虽然应用深度学习有一个很大的优势是不再需要繁琐低效的人工特征工程,然而如果你只是把他当做一个黑盒,难免会经常怀疑人生。一定要理解你的数据,记住无论传统方法还是深度学习方法,数据 sense 始终非常重要。要重视 badcase 分析,明白你的数据是否适合,为什么对为什么错。&/p&&br&&p&&b&关注迭代质量 - 记录和分析你的每次实验:&/b&迭代速度是决定算法项目成败的关键,学过概率的同学都很容易认同。而算法项目重要的不只是迭代速度,一定要关注迭代质量。如果你没有搭建一个快速实验分析的套路,迭代速度再快也只会替你公司心疼宝贵的计算资源。建议记录每次实验,实验分析至少回答这三个问题:为什么要实验?结论是什么?下一步怎么实验?&/p&&p&&b&超参调节&/b&:超参调节是各位调参工程师的日常了,推荐一篇文本分类实践的论文 &a href=&https://link.zhihu.com/?target=https%3A//arxiv.org/pdf/.pdf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&A Sensitivity Analysis of (and Practitioners’ Guide to) Convolutional Neural Networks for Sentence Classification&/a&,里面贴了一些超参的对比实验,如果你刚开始启动文本分析任务,不妨按文章的结果设置超参,怎么最快的得到超参调节其实是一个非常重要的问题,可以读读 萧瑟的这篇文章 &a href=&https://zhuanlan.zhihu.com/p/?utm_source=zhihu&utm_medium=social& class=&internal&&深度学习网络调参技巧 - 知乎专栏&/a&。&/p&&br&&p&&b&一定要用 &/b&&b&dropout&/b&&b&:&/b&有两种情况可以不用:数据量特别小,或者你用了更好的正则方法,比如bn。实际中我们尝试了不同参数的dropout,最好的还是0.5,所以如果你的计算资源很有限,默认0.5是一个很好的选择。&br&&/p&&p&&b&fine-tuning 是必选的&/b&:上文聊到了,如果只是使用word2vec训练的词向量作为特征表示,我赌你一定会损失很大的效果。&/p&&p&&b&未必一定要 softmax loss&/b&: 这取决与你的数据,如果你的任务是多个类别间非互斥,可以试试着训练多个二分类器,也就是把问题定义为multi lable 而非 multi class,我们调整后准确率还是增加了&1%。&br&&/p&&p&&b&类目不均衡问题&/b&:基本是一个在很多场景都验证过的结论:如果你的loss被一部分类别dominate,对总体而言大多是负向的。建议可以尝试类似 booststrap 方法调整 loss 中样本权重方式解决。&br&&/p&&br&&p&&b&避免训练震荡&/b&:默认一定要增加随机采样因素尽可能使得数据分布iid,默认shuffle机制能使得训练结果更稳定。如果训练模型仍然很震荡,可以考虑调整学习率或 mini_batch_size。&/p&&p&&b&没有收敛前不要过早的下结论&/b&:玩到最后的才是玩的最好的,特别是一些新的角度的测试,不要轻易否定,至少要等到收敛吧。&/p&&br&&br&&h2&&b&四、写在最后&/b&&/h2&&p&几年前校招面阿里时,一面二面聊的都是一个文本分类的项目(一个新浪微博主题分类的学校课题项目),用的还是文中介绍的传统的做法。面试时对特征项处理和各个分类器可谓如数家珍,被要求在白板上写了好几个特征选择公式,短短几年传统做法已经被远远超越,不得不感慨深度学习的发展。&/p&&p&值得感慨的一方面是今天技术的发展非常快,故步自封自然是万万万万不可取,深知还有很多理论尚且不懂还要继续深读paper;另一方面,理解理论原理和做好项目间实际非常有巨大的gap,特别是身处工业界的同仁们,学术圈值得钻但要把握分寸,如果仅仅追逐技术深度,不免容易陷入空中阁楼。&/p&&br&&p&最后老规矩再次安利下我们team的招聘,对淘宝搜索排序和自然语言处理方向感兴趣的同学欢迎邮件我 qingsong.,来淘宝,一起成长!&/p&&p&以上,感谢阅读。&/p&
近来在同时做一个应用深度学习解决淘宝商品的类目预测问题的项目,恰好硕士毕业时论文题目便是文本分类问题,趁此机会总结下文本分类领域特别是应用深度学习解决文本分类的相关的思路、做法和部分实践的经验。业务问题描述:淘宝商品的一个典型的例子见下图…
&blockquote&近日,Dishashree Gupta 在 Analyticsvidhya 上发表了一篇题为《Architecture of Convolutional Neural Networks (CNNs) demystified》的文章,对用于图像识别和分类的卷积神经网络架构作了深度揭秘;作者在文中还作了通盘演示,期望对 CNN 的工作机制有一个深入的剖析。机器之心对本文进行了编译,&a href=&//link.zhihu.com/?target=https%3A//www.analyticsvidhya.com/blog/2017/06/architecture-of-convolutional-neural-networks-simplified-demystified/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&原文链接在此&/a&,希望对你有帮助。&/blockquote&&h2&&a href=&//link.zhihu.com/?target=https%3A//mp.weixin.qq.com/s%3F__biz%3DMzA3MzI4MjgzMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D61e9cbc505eb464escene%3D0%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&机器视角:长文揭秘图像处理和卷积神经网络架构&/a&&/h2&&p&&br&&/p&&h2&&b&引言&/b&&/h2&&p&先坦白地说,有一段时间我无法真正理解深度学习。我查看相关研究论文和文章,感觉深度学习异常复杂。我尝试去理解神经网络及其变体,但依然感到困难。&/p&&p&&br&&/p&&p&接着有一天,我决定一步一步,从基础开始。我把技术操作的步骤分解开来,并手动执行这些步骤(和计算),直到我理解它们如何工作。这相当费时,且令人紧张,但是结果非凡。&/p&&p&&br&&/p&&p&现在,我不仅对深度学习有了全面的理解,还在此基础上有了好想法,因为我的基础很扎实。随意地应用神经网络是一回事,理解它是什么以及背后的发生机制是另外一回事。&/p&&p&&br&&/p&&p&今天,我将与你共享我的心得,展示我如何上手卷积神经网络并最终弄明白了它。我将做一个通盘的展示,从而使你对 CNN 的工作机制有一个深入的了解。&/p&&p&&br&&/p&&p&在本文中,我将会讨论 CNN 背后的架构,其设计初衷在于解决图像识别和分类问题。同时我也会假设你对神经网络已经有了初步了解。&/p&&p&&br&&/p&&h2&&b&目录&/b&&/h2&&p&1.机器如何看图?&/p&&p&2.如何帮助神经网络识别图像?&/p&&p&3.定义卷积神经网络&/p&&ul&&li&卷积层&/li&&li&池化层&/li&&li&输出层&/li&&/ul&&p&4.小结&/p&&p&5.使用 CNN 分类图像&/p&&p&&br&&/p&&h2&&b&1. 机器如何看图?&/b&&/h2&&p&人类大脑是一非常强大的机器,每秒内能看(捕捉)多张图,并在意识不到的情况下就完成了对这些图的处理。但机器并非如此。机器处理图像的第一步是理解,理解如何表达一张图像,进而读取图片。&/p&&p&&br&&/p&&p&简单来说,每个图像都是一系列特定排序的图点(像素)。如果你改变像素的顺序或颜色,图像也随之改变。举个例子,存储并读取一张上面写着数字 4 的图像。&/p&&p&&br&&/p&&p&基本上,机器会把图像打碎成像素矩阵,存储每个表示位置像素的颜色码。在下图的表示中,数值 1 是白色,256 是最深的绿色(为了简化,我们示例限制到了一种颜色)。&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-cef0c90b60ba_b.png& data-rawwidth=&387& data-rawheight=&380& class=&content_image& width=&387&&&/figure&&p&&br&&/p&&p&一旦你以这种格式存储完图像信息,下一步就是让神经网络理解这种排序与模式。&/p&&p&&br&&/p&&h2&&b&2. 如何帮助神经网络识别图像?&/b&&/h2&&p&表征像素的数值是以特定的方式排序的。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-d6efa_b.png& data-rawwidth=&848& data-rawheight=&808& class=&origin_image zh-lightbox-thumb& width=&848& data-original=&https://pic2.zhimg.com/v2-d6efa_r.png&&&/figure&&p&假设我们尝试使用全连接网络识别图像,该如何做?&/p&&p&&br&&/p&&p&全连接网络可以通过平化它,把图像当作一个数组,并把像素值当作预测图像中数值的特征。明确地说,让网络理解理解下面图中发生了什么,非常的艰难。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-25be163bbf174bc95613a21_b.png& data-rawwidth=&1340& data-rawheight=&140& class=&origin_image zh-lightbox-thumb& width=&1340& data-original=&https://pic2.zhimg.com/v2-25be163bbf174bc95613a21_r.png&&&/figure&&p&即使人类也很难理解上图中表达的含义是数字 4。我们完全丢失了像素的空间排列。&/p&&p&我们能做什么呢?可以尝试从原图像中提取特征,从而保留空间排列。&/p&&p&&br&&/p&&h2&&b&案例 1&/b&&/h2&&p&这里我们使用一个权重乘以初始像素值。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-f2bb2b737c_b.png& data-rawwidth=&1326& data-rawheight=&604& class=&origin_image zh-lightbox-thumb& width=&1326& data-original=&https://pic1.zhimg.com/v2-f2bb2b737c_r.png&&&/figure&&p&现在裸眼识别出这是「4」就变得更简单了。但把它交给全连接网络之前,还需要平整化(flatten) 它,要让我们能够保留图像的空间排列。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-ecb23f7cce51ed444ceefa1d35bd4240_b.png& data-rawwidth=&1354& data-rawheight=&106& class=&origin_image zh-lightbox-thumb& width=&1354& data-original=&https://pic1.zhimg.com/v2-ecb23f7cce51ed444ceefa1d35bd4240_r.png&&&/figure&&p&&br&&/p&&h2&&b&案例 2&/b&&/h2&&p&现在我们可以看到,把图像平整化完全破坏了它的排列。我们需要想出一种方式在没有平整化的情况下把图片馈送给网络,并且还要保留空间排列特征,也就是需要馈送像素值的 2D/3D 排列。&/p&&p&我们可以尝试一次采用图像的两个像素值,而非一个。这能给网络很好的洞见,观察邻近像素的特征。既然一次采用两个像素,那也就需要一次采用两个权重值了&/p&&figure&&img src=&https://pic2.zhimg.com/v2-5aae57fcba2b5_b.jpg& data-rawwidth=&994& data-rawheight=&383& class=&origin_image zh-lightbox-thumb& width=&994& data-original=&https://pic2.zhimg.com/v2-5aae57fcba2b5_r.jpg&&&/figure&&p&&br&&/p&&p&希望你能注意到图像从之前的 4 列数值变成了 3 列。因为我们现在一次移用两个像素(在每次移动中像素被共享),图像变的更小了。虽然图像变小了,我们仍能在很大程度上理解这是「4」。而且,要意识到的一个重点是,我们采用的是两个连贯的水平像素,因此只会考虑水平的排列。&/p&&p&&br&&/p&&p&这是我们从图像中提取特征的一种方式。我们可以看到左边和中间部分,但右边部分看起来不那么清楚。主要是因为两个问题:&/p&&p&&br&&/p&&p&1. 图片角落左边和右边是权重相乘一次得到的。&/p&&p&2. 左边仍旧保留,因为权重值高;右边因为略低的权重,有些丢失。&/p&&p&&br&&/p&&p&现在我们有两个问题,需要两个解决方案。&/p&&p&&br&&/p&&h2&&b&案例 3&/b&&/h2&&p&遇到的问题是图像左右两角只被权重通过一次。我们需要做的是让网络像考虑其他像素一样考虑角落。我们有一个简单的方法解决这一问题:把零放在权重运动的两边。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-b87ae12947cffa0f429d5f1_b.jpg& data-rawwidth=&1225& data-rawheight=&389& class=&origin_image zh-lightbox-thumb& width=&1225& data-original=&https://pic2.zhimg.com/v2-b87ae12947cffa0f429d5f1_r.jpg&&&/figure&&p&&br&&/p&&p&你可以看到通过添加零,来自角落的信息被再训练。图像也变得更大。这可被用于我们不想要缩小图像的情况下。&/p&&p&&br&&/p&&h2&&b&案例 4&/b&&/h2&&p&这里我们试图解决的问题是右侧角落更小的权重值正在降低像素值,因此使其难以被我们识别。我们所能做的是采取多个权重值并将其结合起来。&/p&&p&&br&&/p&&p&(1,0.3) 的权重值给了我们一个输出表格&/p&&figure&&img src=&https://pic3.zhimg.com/v2-ca6e6b4afb696bccdcbda_b.png& data-rawwidth=&333& data-rawheight=&376& class=&content_image& width=&333&&&/figure&&p&&br&&/p&&p&同时表格 (0.1,5) 的权重值也将给我们一个输出表格。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-cf8ff64d38ce55d2c1de2_b.png& data-rawwidth=&331& data-rawheight=&396& class=&content_image& width=&331&&&/figure&&p&两张图像的结合版本将会给我们一个清晰的图片。因此,我们所做的是简单地使用多个权重而不是一个,从而再训练图像的更多信息。最终结果将是上述两张图像的一个结合版本。&/p&&p&&br&&/p&&h2&&b&案例 5&/b&&/h2&&p&我们到现在通过使用权重,试图把水平像素(horizontal pixel)结合起来。但是大多数情况下我们需要在水平和垂直方向上保持空间布局。我们采取 2D 矩阵权重,把像素在水平和垂直方向上结合起来。同样,记住已经有了水平和垂直方向的权重运动,输出会在水平和垂直方向上低一个像素。&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-fdebef4ea66_b.jpg& data-rawwidth=&1002& data-rawheight=&363& class=&origin_image zh-lightbox-thumb& width=&1002& data-original=&https://pic3.zhimg.com/v2-fdebef4ea66_r.jpg&&&/figure&&p&&br&&/p&&p&特别感谢 Jeremy Howard 启发我创作了这些图像。&/p&&p&&br&&/p&&h2&&b&因此我们做了什么?&/b&&/h2&&p&上面我们所做的事是试图通过使用图像的空间的安排从图像中提取特征。为了理解图像,理解像素如何安排对于一个网络极其重要。上面我们所做的也恰恰是一个卷积网络所做的。我们可以采用输入图像,定义权重矩阵,并且输入被卷积以从图像中提取特殊特征而无需损失其有关空间安排的信息。&/p&&p&&br&&/p&&p&这个方法的另一个重大好处是它可以减少图像的参数数量。正如所见,卷积图像相比于原始图像有更少的像素。&/p&&p&&br&&/p&&h2&&b&3.定义一个卷积神经网络&/b&&/h2&&p&我们需要三个基本的元素来定义一个基本的卷积网络&/p&&p&&br&&/p&&p&1. 卷积层&/p&&p&2. 池化层(可选)&/p&&p&3. 输出层&/p&&p&&br&&/p&&h2&&b&卷积层&/b&&/h2&&p&在这一层中,实际所发生的就像我们在上述案例 5 中见到的一样。假设我们有一个 6*6 的图像。我们定义一个权值矩阵,用来从图像中提取一定的特征。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-1e95f13c1f0d650e826e813c0e1f493a_b.png& data-rawwidth=&425& data-rawheight=&159& class=&origin_image zh-lightbox-thumb& width=&425& data-original=&https://pic3.zhimg.com/v2-1e95f13c1f0d650e826e813c0e1f493a_r.png&&&/figure&&p&我们把权值初始化成一个 3*3 的矩阵。这个权值现在应该与图像结合,所有的像素都被覆盖至少一次,从而来产生一个卷积化的输出。上述的 429,是通过计算权值矩阵和输入图像的 3*3 高亮部分以元素方式进行的乘积的值而得到的。&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-f9dabe62c1e5c63e418f1_b.jpg& data-rawwidth=&487& data-rawheight=&168& class=&origin_image zh-lightbox-thumb& width=&487& data-original=&https://pic2.zhimg.com/v2-f9dabe62c1e5c63e418f1_r.jpg&&&/figure&&p&&br&&/p&&p&现在 6*6 的图像转换成了 4*4 的图像。想象一下权值矩阵就像用来刷墙的刷子。首先在水平方向上用这个刷子进行刷墙,然后再向下移,对下一行进行水平粉刷。当权值矩阵沿着图像移动的时候,像素值再一次被使用。实际上,这样可以使参数在卷积神经网络中被共享。&/p&&p&&br&&/p&&p&下面我们以一个真实图像为例。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-56acff17e4c36aba47234_b.png& data-rawwidth=&640& data-rawheight=&249& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic1.zhimg.com/v2-56acff17e4c36aba47234_r.png&&&/figure&&p&权值矩阵在图像里表现的像一个从原始图像矩阵中提取特定信息的过滤器。一个权值组合可能用来提取边缘(edge)信息,另一个可能是用来提取一个特定颜色,下一个就可能就是对不需要的噪点进行模糊化。&/p&&p&先对权值进行学习,然后损失函数可以被最小化,类似于多层感知机(MLP)。因此需要通过对参数进行学习来从原始图像中提取信息,从而来帮助网络进行正确的预测。当我们有多个卷积层的时候,初始层往往提取较多的一般特征,随着网络结构变得更深,权值矩阵提取的特征越来越复杂,并且越来越适用于眼前的问题。&/p&&p&&br&&/p&&h2&&b&步长(stride)和边界(padding)的概念&/b&&/h2&&p&像我们在上面看到的一样,过滤器或者说权值矩阵,在整个图像范围内一次移动一个像素。我们可以把它定义成一个超参数(hyperparameter),从而来表示我们想让权值矩阵在图像内如何移动。如果权值矩阵一次移动一个像素,我们称其步长为 1。下面我们看一下步长为 2 时的情况。&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-2d5ce7b1af041dab1bb71b_b.jpg& data-rawwidth=&421& data-rawheight=&150& class=&origin_image zh-lightbox-thumb& width=&421& data-original=&https://pic4.zhimg.com/v2-2d5ce7b1af041dab1bb71b_r.jpg&&&/figure&&p&&br&&/p&&p&你可以看见当我们增加步长值的时候,图像的规格持续变小。在输入图像四周填充 0 边界可以解决这个问题。我们也可以在高步长值的情况下在图像四周填加不只一层的 0 边界。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-67c54ac5b709f0d13ce78e9e17c8991f_b.png& data-rawwidth=&246& data-rawheight=&188& class=&content_image& width=&246&&&/figure&&p&我们可以看见在我们给图像填加一层 0 边界后,图像的原始形状是如何被保持的。由于输出图像和输入图像是大小相同的,所以这被称为 same padding。&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-19f50c5cb8e1_b.jpg& data-rawwidth=&419& data-rawheight=&189& class=&content_image& width=&419&&&/figure&&p&&br&&/p&&p&这就是 same padding(意味着我们仅考虑输入图像的有效像素)。中间的 4*4 像素是相同的。这里我们已经利用边界保留了更多信息,并且也已经保留了图像的原大小。&/p&&p&&br&&/p&&p&&b&多过滤与激活图&/b&&/p&&p&需要记住的是权值的纵深维度(depth dimension)和输入图像的纵深维度是相同的。权值会延伸到输入图像的整个深度。因此,和一个单一权值矩阵进行卷积会产生一个单一纵深维度的卷积化输出。大多数情况下都不使用单一过滤器(权值矩阵),而是应用维度相同的多个过滤器。&/p&&p&&br&&/p&&p&每一个过滤器的输出被堆叠在一起,形成卷积图像的纵深维度。假设我们有一个 32*32*3 的输入。我们使用 5*5*3,带有 valid padding 的 10 个过滤器。输出的维度将会是 28*28*10。&/p&&p&&br&&/p&&p&如下图所示:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-defbc123f52a27bdddf8_b.png& data-rawwidth=&640& data-rawheight=&220& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic1.zhimg.com/v2-defbc123f52a27bdddf8_r.png&&&/figure&&p&&br&&/p&&p&激活图是卷积层的输出。&/p&&p&&br&&/p&&h2&&b&池化层&/b&&/h2&&p&有时图像太大,我们需要减少训练参数的数量,它被要求在随后的卷积层之间周期性地引进池化层。池化的唯一目的是减少图像的空间大小。池化在每一个纵深维度上独自完成,因此图像的纵深保持不变。池化层的最常见形式是最大池化。&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-cae74f156d80e8e12ec6_b.png& data-rawwidth=&259& data-rawheight=&110& class=&content_image& width=&259&&&/figure&&p&在这里,我们把步幅定为 2,池化尺寸也为 2。最大化执行也应用在每个卷机输出的深度尺寸中。正如你所看到的,最大池化操作后,4*4 卷积的输出变成了 2*2。&/p&&p&让我们看看最大池化在真实图片中的效果如何。&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-e62be992ba35c0f79a2f54191da1defb_b.png& data-rawwidth=&640& data-rawheight=&246& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic4.zhimg.com/v2-e62be992ba35c0f79a2f54191da1defb_r.png&&&/figure&&p&&br&&/p&&p&正如你看到的,我们卷积了图像,并最大池化了它。最大池化图像仍然保留了汽车在街上的信息。如果你仔细观察的话,你会发现图像的尺寸已经减半。这可以很大程度上减少参数。&/p&&p&&br&&/p&&p&同样,其他形式的池化也可以在系统中应用,如平均池化和 L2 规范池化。&/p&&p&&br&&/p&&h2&&b&输出维度&/b&&/h2&&p&理解每个卷积层输入和输出的尺寸可能会有点难度。以下三点或许可以让你了解输出尺寸的问题。有三个超参数可以控制输出卷的大小。&/p&&p&&br&&/p&&p&1. 过滤器数量-输出卷的深度与过滤器的数量成正比。请记住该如何堆叠每个过滤器的输出以形成激活映射。激活图的深度等于过滤器的数量。&/p&&p&2. 步幅(Stride)-如果步幅是 1,那么我们处理图片的精细度就进入单像素级别了。更高的步幅意味着同时处理更多的像素,从而产生较小的输出量。&/p&&p&3. 零填充(zero padding)-这有助于我们保留输入图像的尺寸。如果添加了单零填充,则单步幅过滤器的运动会保持在原图尺寸。&/p&&p&&br&&/p&&p&我们可以应用一个简单的公式来计算输出尺寸。输出图像的空间尺寸可以计算为([W-F + 2P] / S)+1。在这里,W 是输入尺寸,F 是过滤器的尺寸,P 是填充数量,S 是步幅数字。假如我们有一张 32*32*3 的输入图像,我们使用 10 个尺寸为 3*3*3 的过滤器,单步幅和零填充。&/p&&p&&br&&/p&&p&那么 W=32,F=3,P=0,S=1。输出深度等于应用的滤波器的数量,即 10,输出尺寸大小为 ([32-3+0]/1)+1 = 30。因此输出尺寸是 30*30*10。&/p&&p&&br&&/p&&h2&&b&输出层&/b&&/h2&&p&在多层卷积和填充后,我们需要以类的形式输出。卷积和池化层只会提取特征,并减少原始图像带来的参数。然而,为了生成最终的输出,我们需要应用全连接层来生成一个等于我们需要的类的数量的输出。仅仅依靠卷积层是难以达到这个要求的。卷积层可以生成 3D 激活图,而我们只需要图像是否属于一个特定的类这样的内容。输出层具有类似分类交叉熵的损失函数,用于计算预测误差。一旦前向传播完成,反向传播就会开始更新权重与偏差,以减少误差和损失。&/p&&p&&br&&/p&&h2&&b&4. 小结&/b&&/h2&&p&正如你所看到的,CNN 由不同的卷积层和池化层组成。让我们看看整个网络是什么样子:&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-a182bd59d24_b.png& data-rawwidth=&640& data-rawheight=&188& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic1.zhimg.com/v2-a182bd59d24_r.png&&&/figure&&p&&br&&/p&&ul&&li&我们将输入图像传递到第一个卷积层中,卷积后以激活图形式输出。图片在卷积层中过滤后的特征会被输出,并传递下去。&br&&/li&&li&每个过滤器都会给出不同的特征,以帮助进行正确的类预测。因为我们需要保证图像大小的一致,所以我们使用同样的填充(零填充),否则填充会被使用,因为它可以帮助减少特征的数量。&br&&/li&&li&随后加入池化层进一步减少参数的数量。&br&&/li&&li&在预测最终提出前,数据会经过多个卷积和池化层的处理。卷积层会帮助提取特征,越深的卷积神经网络会提取越具体的特征,越浅的网络提取越浅显的特征。&br&&/li&&li&如前所述,CNN 中的输出层是全连接层,其中来自其他层的输入在这里被平化和发送,以便将输出转换为网络所需的参数。&br&&/li&&li&随后输出层会产生输出,这些信息会互相比较排除错误。损失函数是全连接输出层计算的均方根损失。随后我们会计算梯度错误。&br&&/li&&li&错误会进行反向传播,以不断改进过滤器(权重)和偏差值。&br&&/li&&li&一个训练周期由单次正向和反向传递完成。&br&&/li&&/ul&&p&&b&5. 在 KERAS 中使用 CNN 对图像进行分类&/b&&/p&&p&让我们尝试一下,输入猫和狗的图片,让计算机识别它们。这是图像识别和分类的经典问题,机器在这里需要做的是看到图像,并理解猫与狗的不同外形特征。这些特征可以是外形轮廓,也可以是猫的胡须之类,卷积层会攫取这些特征。让我们把数据集拿来试验一下吧。&/p&&p&&br&&/p&&p&以下这些图片均来自数据集。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-298e3e184cabf4e7102afbd2_b.png& data-rawwidth=&640& data-rawheight=&254& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/v2-298e3e184cabf4e7102afbd2_r.png&&&/figure&&p&&br&&/p&&p&我们首先需要调整这些图像的大小,让它们形状相同。这是处理图像之前通常需要做的,因为在拍照时,让照下的图像都大小相同几乎不可能。&/p&&p&&br&&/p&&p&为了简化理解,我们在这里只用一个卷积层和一个池化层。注意:在 CNN 的应用阶段,这种简单的情况是不会发生的。&/p&&div class=&highlight&&&pre&&code class=&language-text&&#import various packagesimport osimport numpy as npimport pandas as pdimport scipyimport sklearnimport kerasfrom keras.models import Sequentialimport cv2from skimage import io
%matplotlib inline
#Defining the File Path
cat=os.listdir(&/mnt/hdd/datasets/dogs_cats/train/cat&)
dog=os.listdir(&/mnt/hdd/datasets/dogs_cats/train/dog&)
filepath=&/mnt/hdd/datasets/dogs_cats/train/cat/&filepath2=&/mnt/hdd/datasets/dogs_cats/train/dog/&#Loading the Images
label = []for i in cat:
image = scipy.misc.imread(filepath+i)
images.append(image)
label.append(0) #for cat imagesfor i in dog:
image = scipy.misc.imread(filepath2+i)
images.append(image)
label.append(1) #for dog images
#resizing all the imagesfor i in range(0,23000):
images[i]=cv2.resize(images[i],(300,300))
#converting images to arrays
images=np.array(images)
label=np.array(label)
# Defining the hyperparameters
filters=10filtersize=(5,5)
epochs =5batchsize=128input_shape=(300,300,3)
#Converting the target variable to the required sizefrom keras.utils.np_utils import to_categorical
label = to_categorical(label)
#Defining the model
model = Sequential()
model.add(keras.layers.InputLayer(input_shape=input_shape))
model.add(keras.layers.convolutional.Conv2D(filters, filtersize, strides=(1, 1), padding='valid', data_format=&channels_last&, activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2, 2)))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(units=2, input_dim=50,activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(images, label, epochs=epochs, batch_size=batchsize,validation_split=0.3)
model.summary()
&/code&&/pre&&/div&&p&&br&&/p&&p&在这一模型中,我只使用了单一卷积和池化层,可训练参数是 219,801。很好奇如果我在这种情况使用了 MLP 会有多少参数。通过增加更多的卷积和池化层,你可以进一步降低参数的数量。我们添加的卷积层越多,被提取的特征就会更具体和复杂。&/p&&p&&br&&/p&&p&在该模型中,我只使用了一个卷积层和池化层,可训练参数量为 219,801。如果想知道使用 MLP 在这种情况下会得到多少,你可以通过加入更多卷积和池化层来减少参数的数量。越多的卷积层意味着提取出来的特征更加具体,更加复杂。&/p&&p&&br&&/p&&h2&&b&结语&/b&&/h2&&p&希望本文能够让你认识卷积神经网络,这篇文章没有深入 CNN 的复杂数学原理。如果希望增进了解,你可以尝试构建自己的卷积神经网络,借此来了解它运行和预测的原理。&/p&&p&&br&&/p&&p&本文首发于微信公众号:机器之心(almosthuman2014),如需转载,请私信联系,感谢。&/p&
近日,Dishashree Gupta 在 Analyticsvidhya 上发表了一篇题为《Architecture of Convolutional Neural Networks (CNNs) demystified》的文章,对用于图像识别和分类的卷积神经网络架构作了深度揭秘;作者在文中还作了通盘演示,期望对 CNN 的工作机制有一…
&p&&strong&Part 1:图像识别任务&/strong&&br&&/p&&br&&p&卷积神经网络,听起来像是计算机科学、生物学和数学的诡异组合,但它们已经成为计算机视觉领域中最具影响力的革新的一部分。神经网络在 2012 年崭露头角,Alex Krizhevsky 凭借它们赢得了那一年的 ImageNet 挑战赛(大体上相当于计算机视觉的年度奥林匹克),他把分类误差记录从 26% 降到了 15%,在当时震惊了世界。自那之后,大量公司开始将深度学习用作服务的核心。Facebook 将神经网络用于自动标注算法、谷歌将它用于图片搜索、亚马逊将它用于商品推荐、Pinterest 将它用于个性化主页推送、Instagram 将它用于搜索架构。&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-a015ef9d7cf04de0cf03cca_b.jpg& data-rawwidth=&640& data-rawheight=&249& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/v2-a015ef9d7cf04de0cf03cca_r.jpg&&&/figure&&p&然而,应用这些网络最经典最流行的案例是进行图像处理。在图像处理任务中,让我们看一下如何使用卷积神经网络进行图像分类。&/p&&br&&p&&strong&问题空间&/strong&&/p&&br&&p&图像分类是对输入图像的操作,最终输出一组最好地描述了图像内容的分类(如猫、狗等)或分类的概率。对人类来说,识别是打出生便开始学习的技能之一,对成人来说更是信手拈来,毫不费力。我们只需一眼便能快速识别我们所处的环境以及环绕在我们身边的物体。当我们看到一张图片或是环看四周的时候,无需刻意观察,多数时候也能立即描述出场景特征并标记出每一个对象。快速识别不同模式、根据早前知识进行归纳、以及适应不同的图像环境一直都是人类的专属技能,机器尚未享有。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-acacdd44475cce_b.jpg& data-rawwidth=&636& data-rawheight=&222& class=&origin_image zh-lightbox-thumb& width=&636& data-original=&https://pic3.zhimg.com/v2-acacdd44475cce_r.jpg&&&/figure&&p&&strong&输入与输出&/strong&&/p&&br&&p&当计算机看到一张图像(输入一张图像)时,它看的是一大堆像素值。根据图片的分辨率和尺寸,它将看到一个 32 x 32 x 3 的数组(3 指代的是 RGB 值)。为了讲清楚这一点,假设我们有一张 JPG 格式的 480 x 480 大小的彩色图片,那么它对应的数组就有 480 x 480 x 3 个元素。其中每个数字的值从 0 到 255 不等,其描述了对应那一点的像素灰度。当我们人类对图像进行分类时,这些数字毫无用处,可它们却是计算机可获得的唯一输入。其中的思想是:当你提供给计算机这一数组后,它将输出描述该图像属于某一特定分类的概率的数字(比如:80% 是猫、15% 是狗、5% 是鸟)。&/p&&br&&p&&strong&我们想要计算机做什么&/strong&&/p&&br&&p&现在我们知道了问题所在以及输入与输出,就该考虑如何处理了。我们想要计算机能够区分开所有提供给它的图片,以及搞清楚猫猫狗狗各自的特有特征。这也是我们人类的大脑中不自觉进行着的过程。当我们看到一幅狗的图片时,如果有诸如爪子或四条腿之类的明显特征,我们便能将它归类为狗。同样地,计算机也可以通过寻找诸如边缘和曲线之类的低级特点来分类图片,继而通过一系列卷积层级建构出更为抽象的概念。这是 CNN(卷积神经网络)工作方式的大体概述,下面是具体细节。&/p&&br&&p&&strong&生物学连接&/strong&&/p&&br&&p&首先介绍些背景。当你第一次听到卷积神经网络这一术语,可能会联想到神经科学或生物学,那就对了。可以这样说。CNN 的确是从视觉皮层的生物学上获得启发的。视觉皮层有小部分细胞对特定部分的视觉区域敏感。Hubel 和 Wiesel 于 1962 年进行的一项有趣的试验详细说明了这一观点,他们验证出大脑中的一些个体神经细胞只有在特定方向的边缘存在时才能做出反应(即放电)。例如,一些神经元只对垂直边缘兴奋,另一些对水平或对角边缘兴奋。Hubel 和 Wisesl 发现所有这些神经元都以柱状结构的形式进行排列,而且一起工作才能产生视觉感知。这种一个系统中的特定组件有特定任务的观点(视觉皮层的神经元细胞寻找特定特征)在机器中同样适用,这就是 CNN 的基础。&/p&&br&&p&&strong&结构&/strong&&/p&&br&&p&回到细节上来。更为详细的 CNN 工作概述指的是你挑一张图像,让它历经一系列卷积层、非线性层、池化(下采样(downsampling))层和完全连接层,最终得到输出。正如之前所说,输出可以是最好地描述了图像内容的一个单独分类或一组分类的概率。如今,难点在于理解其中每一层的工作方法。我们先来看最重要的部分。&/p&&br&&p&&strong&第一层——数学部分&/strong&&/p&&br&&p&CNN 的第一层通常是卷积层(Convolutional Layer)。首先需要了解卷积层的输入内容是什么。如上所述,输入内容为一个 32 x 32 x 3 的像素值数组。现在,解释卷积层的最佳方法是想象有一束手电筒光正从图像的左上角照过。假设手电筒光可以覆盖 5 x 5 的区域,想象一下手电筒光照过输入图像的所有区域。在机器学习术语中,这束手电筒被叫做过滤器(filter,有时候也被称为神经元(neuron)或核(kernel)),被照过的区域被称为感受野(receptive field)。过滤器同样也是一个数组(其中的数字被称作权重或参数)。重点在于过滤器的深度必须与输入内容的深度相同(这样才能确保可以进行数学运算),因此过滤器大小为 5 x 5 x 3。现在,以过滤器所处在的第一个位置为例,即图像的左上角。当筛选值在图像上滑动(卷积运算)时,过滤器中的值会与图像中的原始像素值相乘(又称为计算点积)。这些乘积被加在一起(从数学上来说,一共会有 75 个乘积)。现在你得到了一个数字。切记,该数字只是表示过滤器位于图片左上角的情况。我们在输入内容上的每一位置重复该过程。(下一步将是将过滤器右移 1 单元,接着再右移 1 单元,以此类推。)输入内容上的每一特定位置都会产生一个数字。过滤器滑过所有位置后将得到一个 28 x 28 x 1 的数组,我们称之为激活映射(activation map)或特征映射(feature map)。之所以得到一个 28 x 28 的数组的原因在于,在一张 32 x 32 的输入图像上,5 x 5 的过滤器能够覆盖到 784 个不同的位置。这 784 个位置可映射为一个 28 x 28 的数组。&/p&&br&&figure&&img src=&https://pic3.zhimg.com/v2-790a3d600c6bdb27c393a1ea_b.jpg& data-rawwidth=&640& data-rawheight=&347& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/v2-790a3d600c6bdb27c393a1ea_r.jpg&&&/figure&&p&(注意:包括上图在内的一些图片来自于 Micheal Nielsen 的 「神经网络与深度学习( Neural Networks and Deep Learning)」一书。我强烈推荐这本书。这本书可免费在线浏览:&a href=&//link.zhihu.com/?target=http%3A//neuralnetworksanddeeplearning.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Neural networks and deep learning&/a&)&/p&&br&&p&当我们使用两个而不是一个 5 x 5 x 3 的过滤器时,输出总量将会变成
28 x 28 x 2。采用的过滤器越多,空间维度( spatial dimensions)保留得也就越好。数学上而言,这就是卷积层上发生的事情。&/p&&br&&p&&strong&第一层——高层次角度&/strong&&/p&&br&&p&不过,从高层次角度而言卷积是如何工作的?每个过滤器可以被看成是特征标识符( feature identifiers)。这里的特征指的是例如直边缘、原色、曲线之类的东西。想一想所有图像都共有的一些最简单的特征。假设第一组过滤器是 7 x 7 x 3 的曲线检测器。(在这一节,为了易于分析,暂且忽略该过滤器的深度为 3 个单元,只考虑过滤器和图像的顶层层面。)作为曲线过滤器,它将有一个像素结构,在曲线形状旁时会产生更高的数值(切记,我们所讨论的过滤器不过是一组数值!)&/p&&figure&&img src=&https://pic4.zhimg.com/v2-4e15bce4bc6dca_b.png& data-rawwidth=&624& data-rawheight=&278& class=&origin_image zh-lightbox-thumb& width=&624& data-original=&https://pic4.zhimg.com/v2-4e15bce4bc6dca_r.png&&&/figure&&p&&em&左图:过滤器的像素表示;右图:曲线检测器过滤器的可视化;对比两图可以看到数值和形状的对应&/em&&/p&&br&&p&回到数学角度来看这一过程。当我们将过滤器置于输入内容的左上角时,它将计算过滤器和这一区域像素值之间的点积。拿一张需要分类的照片为例,将过滤器放在它的左上角。&/p&&p&&figure&&img src=&https://pic2.zhimg.com/v2-a7a8f5b74d66f7ba1417c09_b.png& data-rawwidth=&640& data-rawheight=&227& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic2.zhimg.com/v2-a7a8f5b74d66f7ba1417c09_r.png&&&/figure&切记,我

我要回帖

更多关于 suo.im是什么网站 的文章

 

随机推荐