曾几何时,我们读着比尔盖茨的传记,感叹他大学时就能徒手写OS的天才同时,也不禁唏嘘:现在写一个OS又哪是几个人几台电脑能搞的定的。乔布斯的车库创业,虽然听着比鸡汤还暖心,可是那个时代毕竟已经过去了。留下的,只有无数挣扎着从C++/Delphi转型的资深程序员。
互联网崛起的时代,马化腾带着几个人就开发出了OICQ,造就了如今偌大的腾讯帝国。智能手机爆发的时代,随便山寨一个游戏就能赚得钵满瓢满,而现在,即使用心做了一个APP,想要推广也至少是百万级的推广费用。互联网(以及移动互联网)的时代,也已经接近了尾声。草根创业将变得无比艰难。代表着互联网时代的JAVA程序员已经明显日落西山,而代表着移动互联网时代的Android/iOS程序员们,应该也感受到了就业形势的日趋严峻吧。
每一波浪潮的到来,都意味一片无人占领的蓝海,也意味着众多新成长起来的巨头,还意味着什么?大量的人员需求,供不应求的开发市场,以及从业者的高薪与众多的机会。
我们最常做的事情是目送着上一次浪潮的余波远去,感叹自己生不逢时,却没有意识到,下一波浪潮已经到了我们脚下。
没错,我们说的就是AI。
吴恩达曾经说过,在他看来,机器学习对我们世界的改变,可以与电能的使用相媲美。而更多的人,已经开始用“第四次工业革命”来预言人工智能带来的产业革新。前三次工业革命,让人类摆脱了重体力劳动、精细体力劳动、简单计算劳动。而机器学习,很可能让人类不必在简单思考判断类劳动上消耗大量人力资源。
比如,目前仅在中国有出租车130万辆,载货车辆超过千万,也就是说,每天以“驾驶”作为主要职业的人群就达到千万量级,如果自动驾驶得以普及,至少在中国就有千万人被“释放”,也就是说,得重新学一门吃饭的手艺了。再比如安防领域,全国每天坐在各种监控屏幕前的人(没错,就是每部谍战/犯罪类电影里都会被抹脖子的那个职业)也接近百万。此外还有诸如视频网站鉴黄师、专业翻译,起点网文筛选编辑、快递地址分拣员等等我们听说过或者没有听说过的职业,默默地消耗着无数人的时间精力。而机器学习在砸掉这些人饭碗的同时,也逼迫着他们投入到其他的工作中,使我们的社会分工结构悄然转型。
若是再想得长远一些,这些技术对我们生活的改变,其实远不仅仅是“以前用人的地方变成用机器”那么简单。
比如说自动驾驶,这个很多巨头公司投入了大量精力的领域。很多人觉得,以后可能买车以后开车就不用那么累了。
然而如果所有车辆都变成了自动驾驶,我们还真的需要买一辆车吗?
我们购买车辆的时候,其实不是买的四个轮子加一个发动机,而是购买“随时随心快速出行的能力”,使我们不必受公交太挤、打车费劲、急事出门很麻烦、偏远地区去了回不来等等这些困扰。
而在自动驾驶的情况下,司机交班,扎堆,偏远地方打不到车,网上叫车没人接单这些情况都将不复存在,那么我们何必再每个人买一辆车,忍受路上堵、停车难这些困扰呢?
也许到时候就会变成大量的无人车辆在各种巨型停车场静静地趴着,只要有人下单,几分钟后就会有一辆无人车辆来到你面前任你驱使。再想深一些,在这样的情况下,汽车是否一定有必要设计成五座?也许根据实际运营数据的分析,单人车辆,二人车辆会成为无人车辆的主流,从而大大减轻交通流量压力,缓解拥堵。而所有车辆的状况都通过网络汇总到管控机构的时候,拥堵也许也不再会成为一个问题,所有的车辆都会自动规划路径,将流量合理地分散到每一条道路上。如果再想想,当智能驾驶足够可靠的时候,现在的交通路口红绿灯机制是否还有必要?甚至说,现在的一切交通规则是否会有一个巨大的改变?
这仅仅是针对一项技术开出的脑洞,而其他的技术,将给我们带来什么,恐怕是现在没有人能说得清楚的。
唯一可以想象的是,我们在不需要学习外语,不需要考驾照的同时,会需要更多的机器学习专家和相关开发人员。
其实,上面这些事情,身在IT圈中的人,应该都有着直观的认识。最近这两年,谈论机器学习,神经网络的人越来越多,而各种“人工智能”相关的消息也是铺天盖地,大有“不入圈就淘汰”的汹汹势头。
但与此同时,各种不明觉厉的名词也吓退了很多非科班出身的开发者。什么叫卷积神经网络?什么叫凸优化?是不是还要回去重读高数,线代,概率?那么一大堆公式,感觉完全看不懂啊?听说没个名校博士出身都搞不了这个?
不光是普通程序猿这么说,文艺的程序猿和……额,高大上的程序猿也都这么说。
我说,呵呵。
在很久以前的一篇知乎回答中提过,作为开发人员,机器学习界在我看来会分成这么几个层次
1.学术研究者
他们的工作是从理论上诠释机器学习的各个方面,试图找出“这样设计模型/参数为什么效果更好”,并且为其他从业者提供更优秀的模型,甚至将理论研究向前推进一步。
能够做到这一步的人,可以说凤毛麟角,天赋是绕不过去的大山,机遇和努力也缺一不可。
对于这些人,其实也轮不到我们来建议,在长期的研究中他们都有自己喜好的工具和方法,甚至有一言不合就自己开发工具甚至开发语言的(比如LeCun……)。
2.算法改进者
他们也许无法回答出“我的方法为什么work”,也许没有Hinton,LeCun那样足以载入史册的重大成果,但是却能根据经验和一些奇思妙想,将现有的模型玩出更好的效果,或者提出一些改进的模型。这些人通常都是各个机器学习巨头公司的中坚力量或者成长中的独角兽,使用什么模型对他们来讲也不是问题,根据所处的环境,通常都有固定的几个选择。他们其实也并不怎么需要关心“我该用什么框架”,重要的是什么框架能够快速地把想法实现出来。所以你会看到caffe和theano和mxnet和torch都一样有大批的用户,仍然在贡献大量的新算法的实现。在这个层面,insight和idea才是重要的东西,各种工具的区别,影响真的没那么大。可能会让一个结果早得到或者晚得到几天或者几周,却不可能影响“有没有成果”。
3.工业实现者这些人基本上不会在算法领域涉入太深,也就是了解一下各个算法的实现,各个模型的结构。他们更多地是根据论文去复现优秀的成果,或者使用其他人复现出来的成果,并且试图去在工业上应用它。
对于大部分IT人来说,做到第三类,也就是工业实现这个层面,已经足够好了,至少,我们已经有了亲身参与这个大时代的机会,仅就这一点来说,便已经击败了全国99%的人(斜眼笑的表情)。
那么想要成为一个机器学习开发人员,究竟需要做些什么准备?到底如何才能从一个C++/JAVA/Android/iOS程序猿成为一个机器学习开发人员呢?
答案只有一个:
Just Do IT(去搞IT吧,少年)
作为程序员,读十遍书不如跑一遍程序,与其花费大量的时间去啃书本,不如亲手完成自己的程序并运行它。我们在写出代码的同时,就会了解到自己还有哪些地方不够清楚,从而针对性地学习。
基础知识
当然,勿在浮沙筑高台(对这句话眼熟的请举手),有一些基础的知识还是需要掌握的。例如在计算机视觉领域,根据我们团队内部培训的经验,为了能够独立进行机器学习的开发工作,最好首先完成这么几项课程:
入门,了解概念,算法基础:
coursera机器学习课程-by吴恩达
进阶,多层神经网络,卷积和softmax回归:
斯坦福机器学习课程UFLDL
http://ufldl.stanford.edu/wiki/index.php/UFLDL_Tutorial
重点关注其中的softmax回归,卷积和池化这几个章节
进阶,计算机视觉,卷积神经网络的新进展,实现和应用:
斯坦福计算机视觉课程CS231n
上面的课程大概会消耗你1到2个月的所有业余时间。但是相信我,这是值得的。网络上的课程非常多,也有很多优秀的免费课程,但是作为入门,我没有找到过比这三个更适合的。
如果实在连一两个月的业余时间都拿不出来,好吧,我来偷偷告诉你最最最基本的一个要求,满足了这个要求,你就能够算是机器学习入门了:
会算矩阵乘法
别笑,说正经的,在这个框架高度封装的年代,梯度不需要自己算,损失不需要自己求,反向传导更是被处理得妥妥的,在不求甚解的情况下,你甚至只需要知道这么几个概念就可以开始着手写第一个程序了:
它就是通过一系列矩阵运算(或者类似的一些其他运算)将输入空间映射到输出空间而已。参与运算的矩阵的值称为权重,是需要通过不断迭代来寻找到最优值。
当前的权重值离最优值还差多远,用一个数值来表示,这个值就叫损失,计算这个值的函数叫损失函数。
当前的权重值应该调大还是调小,这个值通过对损失函数求导来判断,这个求导得到的函数叫做梯度。
通过损失和梯度来更新权重的方法叫做反向传导。
迭代的方法称为梯度下降。
虽然这么写出来的程序一定是不知其所以然,但是其实20年前我第一次用C++写Hello world的时候也是一脸懵逼的,我相信,每个能够投身机器学习开发工作的程序猿,都是有大毅力大勇气的,自然不会欠缺继续学习的动力和决心。
选择框架
好吧,接下来你需要找一个框架来作为第一个程序的开发环境。
目前机器学习的框架非常的多,从面向的使用者这个维度去划分,大体上分成这么两个阵营:
学术友好型:
Theano,Torch,Caffe
学术研究时,弄出来一个新模型,新算法,新函数是常有的事,做出新的突破也是学术研究的最基本要求。所以,这些框架通常都可以方便地定制模型,也可以深入修改内部实现。很多新成果都会在发表论文的同时,提供这些框架上的实现代码供参考。性能方面也是比较出色。
而代价就是,要么使用了困难(Caffe:C++)或者小众(Torch:Lua)的开发语言界面,要么具有一些古怪的缺点(Theano:编译超级慢)。
而且,这些框架似乎都没怎么考虑过“怎么提供服务”的问题。想要部署到服务器上?Caffe已经是最简单的了,然而仍然要经历漫长而痛苦的摸索历程。
工业友好型:
Tensorflow,MXnet,Caffe
工业上往往更注重“把一个东西做出来,并且让它运行得良好”。所以这些框架首先就需要支持并行训练。其中Tensorflow和MXnet支持多机多卡、单机多卡,多机单卡并行,Caffe支持单机多卡。虽然性能并不是特别理想。在我们的测试中,Tensorflow的双卡并行只能达到单卡的1.5倍左右性能,卡越多,这个比例越低。Caffe要好一些,但是参数同步和梯度计算无论如何也都需要时间,所以没有哪个框架能没有性能损失地实现扩展。而多机的情况下,性能损失更大,很多时候都让人感到无法接受(这方面的优化只能以后有机会再提,如果有这方面的同好,欢迎讨论)。
相对来说,Tensorflow提供了比较好的部署机制(Serving),并且有直接部署到移动端的方案。而MXnet和Caffe则是直接编译的方式,虽然也可以实现,但是说实话,还是很麻烦。
至于缺点,就是除了Caffe之外,其他两种框架对于学术界的动态跟踪的都不太紧,Tensorflow到现在都没有pRelu的官方实现,在前阵子也才刚刚推出了一系列检测(Detection)的模型。MXnet这一点要积极些,可是受限于较小的开发者社区,很多成果都只能等待大神们的contribution或者自行实现。
这样看来,难道最好的框架是Caffe?兼顾学术和实现,灵活性和性能兼备……
我得说,我的确是这么认为的。当然有一个前提,得懂C++……【捂脸】
如果不是C++开发人员出身,这门语言也不比机器学习容易多少了。
对于大多数有志于投身于机器学习开发(而不是研究)的同学们来说,我推荐首选Tensorflow作为你的第一个开发框架。
除了上述的优点之外,最主要的因素是,它人气高。在遇到任何问题的时候,你都会找到一群志同道合的伙伴们去咨询或者一起研究。这对于初学者而言,重要程度不言而喻。
好吧,选择就是这么的简单粗暴。
此外,还有一个良心建议,不论你选择哪个框架,千万不要试图在windows上运行它。哪怕是号称支持windows的MXnet或者新版Tensorflow,不要问我怎么知道……还是去装个Linux系统吧。建议使用ubuntu14.04或16.04。
学习用机配置
OK,接下来我们就需要一台机器去把框架搭建起来,并且去写我们的helloAI。然而我在很多地方都看到小伙伴们在问:
我需要什么样的配置能学机器学习?
我需要买块GTX1080/Titan/Tesla吗?
我应该装几块显卡?一块?两块?还是四块?
答案也倾向于:“必须得有GPU啊,至少1080,没有四路titan你都不好意思和人打招呼”
其实,并不完全是这样。如果仅是入门和学习的话,CPU或者GPU完全不影响对代码和框架的学习。运行起类似Mnist或者Cifar之类的玩具数据集,其实差距也并不大。比如在我的机器上,运行自带的Cifar demo,i7 CPU和GTX 1080 Ti的速度大概 770 pics/s VS. 2200 pics/s。GPU大概是不到三倍的性能优势。
瞧,差距也没那么大。
不过这里有一个小窍门,如果想用CPU版本的Tensorflow,最好不要使用pip下载的方式,而是用自行编译的方法。因为在开发机上编译时它会自动打开所有支持的加速指令集(SSE4.1/SSE4.2/AVX/AVX2/FMA),从而使CPU的运算大大加快。根据我们的测试,在打开全部加速指令集的情况下,训练速度大概会有30%的提升,而预测的速度大概会提升一倍。
当然,如果真的想要使用一个复杂模型去处理实际的生产问题,模型的复杂度和数据量都不是Cifar这样的玩具数据集可以相比的。如果用我们的一个模型同样去运行Cifar数据集,其他参数和条件完全相同,它在i5/i7/960/GTX1080/GTX1080Ti的速度分别是(单位还是pics/s,越大越好):
19/25/140/460/620
这个时候大概就能看出差距了,1080Ti大概是i7 CPU的25倍。而在模型上线使用(inference)时,GPU也会有10-20倍的性能优势。模型越复杂,GPU的优势越明显。
综合这些来看,如果仅仅是入门时期的学习,我建议先不用专门购买带GPU的机器,先用你现有的机器,使用CPU版本,去学习框架和一些基础。等到你对基础已经掌握得比较扎实,那么自然就会有跑一些更复杂的模型和更“真实”的数据的想法,这个时候,可以考虑买一块GPU,来缩短训练的时间。
在选择GPU时,我听过一些朋友们推荐GTX1070 x 2这种选择。从理论上讲,1070的性能大概能达到1080的75%,而价格只是1080的一半,从各个方面来看,似乎都是双1070更有优势。然而不要忘记,双卡的性能是不可能达到单卡的2倍的,在目前的Tensorflow上,大概只能达到1.5倍上下,算下来其实和1080单卡差不多。而双显卡的主板和电源以及机箱散热都需要更多的考虑,从性价比上来看未必真的划算。
不过,如果显卡预算刚好卡在5000-6000这个档位,双1070也有它的优势。比如可以学习使用多显卡并行计算的用法,在不着急的时候可以同时用两块显卡跑两个不同的任务,合并起来就相当于有了16G的显存等等。考虑到这些因素,双1070的确是最适合入门学习的选择——如果买不起双1080/双TITAN的话(笑)。
如果你打算用笔记本来作为主力学习用机的话,我的建议是:最好不要,除非你使用Linux经验很丰富或者不打算用GPU加速。很多笔记本在安装Liunx之后出现驱动方面的问题,而且使用GPU加速时的高热量也会非常影响系统的稳定性。如果没有很丰富的经验,经常会在一个问题上卡掉几个小时宝贵的学习时间。
安装Tensorflow时的那些坑
一般来说,严格按照官网说明,在干净的系统上通过PIP安装CPU版,都不会遇到什么问题。
新手常犯的错误是忘记了执行
sudo pip install --upgrade pip
导致在安装tensorflow时找不到。
而GPU版本最常见的坑是:
忘记关闭lightdm就去装驱动
这个不要紧,执行
sudo stop lightdm
就好了。ubuntu 16.04用
sudo systemctl stop lightdm
安装CUDA时的第二个询问
Install NVIDIA Accelerated Graphics Driver for Linux-x86_64 xxx.xx?
这里输入yes是错的!
记住输入no!一定不要安装CUDA自带驱动。这一点格外重要,装上去以后往往就卡在GUI输入密码界面死循环了。
入门数据集选择
mnist?cifar?ImageNet?COCO?这些都是啥?
MNIST
不论选择哪本教材,哪个框架,在刚刚接触机器学习的时候,一定会接触到Mnist(读作M- nist)这个名字。
这是个由Yann LeCun(读成杨乐坤,不是严乐村)建立的手写数字库,每条数据是固定的784个字节,由28x28个灰度像素组成,大概长这样:
目标是对输入进行10-分类,从而输出每个手写数字所表达的真实数字。因为它体积小(10M左右),数据多(6万张训练图片),适用范围广(NN/CNN/SVM/KNN都可以拿来跑跑)而天下闻名,其地位相当于机器学习界的Hello World。在LeCun的Mnist官方网站上(MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges),贴有各种模型跑这个数据集的最好成绩,当前的最好得分是CNN的大概99.7%。
因为这个数据集实在非常的小,所以即使在CPU上,也可以用几秒钟时间跑完NN的训练,或者几分钟跑完一个简单的CNN的模型。
CIFAR
而对于打算从图像方面入手的同学,Cifar(读做see far)数据库(官网:CIFAR-10 and CIFAR-100 datasets)则是更好的入门选项。
这个数据库分为2个版本,CIFAR-10和CIFAR-100,顾名思义,CIFAR-10有10个分类,每个分类有5000张训练图片和1000张测试图片,每张图片是32x32像素的3通道位图。大概长这样:
而CIFAR-100有100个分类,每个分类变成了500张训练图片+100张测试图片,而图片的大小并没什么变化。
之所以说它比Mnist更适合作为图片处理的入门,是因为它虽然分辨率低了些,但是却是三通道,真实拍摄的照片。其中有些图片的背景还略微复杂,更贴近我们真实的图片处理场景。相对而言,Mnist的灰度输入和干净背景就显得有些过于简单,而且99.7%的准确率也确实很难有提升的空间。
Tensorflow给出了Cifar的例程:
https://www.tensorflow.org/tutorials/deep_cnn
并附有代码:
ImageNet和MS COCO
至于ImageNet(ImageNet)和COCO(http://mscoco.org/),则是两个工业级别的图像数据集。通常我们提到他们时,ImageNet指的是ILSVRC2012的训练集,而COCO则是COCO-2014训练集。
ImageNet具有大量的图片(一百多万张,分成1000个分类)和标注,大部分都是这样的:
COCO虽然图片数量少一些(8万多张,80个分类),但是每张图片都有轮廓标记,并且附带分类标注和5句描述话语(英文的)。大概是这样的:
所以当我们进入实际的工作时,可以根据具体的需要从中选择适合自己的数据集作为benchmark或者pretrain数据集。
运行一个CIFAR demo与显卡、显存的分配
在Tenforflow 安装完成后,我们可以用这种方式最快地跑起来第一个Cifar demo:
git clone https://github.com/tensorflow/models.git my_models
cd my_models/tutorials/image/cifar10/
python cifar10_train.py
OK,只需几分钟下载数据,我们就可以看到我们的第一个“图像识别模型”正在训练了。
训练过程中我们可以看到log中在不断地输出loss信息,但是我们除了想要跟踪loss之外,还希望能够看到当前训练的模型到底识别的准确率如何,这个就不是cifar10_train.py这个脚本能提供的了。我们还需要执行
python cifar10_eval.py
这个脚本会不断地验证最近的检查点的识别准确率。
如果使用GPU的话,会发现在运行起来训练脚本之后,所有的显存都已经被这个进程占满,再启动验证脚本的话会报错一大堆的内存不足(OOM),这是Tensorflow的机制决定的,它会默认占据所有显卡的所有显存,而不管自己是否真的用到那么多。
解决这个问题的办法也很简单。
首先,我们可以指定Tensorflow使用哪几块显卡进行训练。要做到这一点,可以在执行较本前,用命令行指定环境变量:
export CUDA_VISIBLE_DEVICES="0,2"
其中的“0,2”就是希望使用的GPU编号,从0开始,用逗号分隔开。
或者在代码中创建一个GPUOption,设置visible_device_list=‘0,2',也能起到同样的效果。
然后,我们可以限制Tensorflow使用的显存,使其动态增长而不是启动就占满。方法和上面的类似,代码中创建一个GPUOption,并设置allow_growth=True即可。
官方的Cifar例程大概能达到86%的准确率,这个成绩在现在可以说算是比较差的了,最新的模型通常都有97%左右的准确率,即使是不仔细调参随便训训,也能轻松达到93%左右,大家可以尝试着修改cifar10.py中定义的模型,得到更好的效果。
我跑完了,然后呢?
那么,在运行完这个例子之后,其实你已经可以算是机器学习工程师中的一员了。接下来就可以收集一些自己的数据,并且训练一些自己的识别引擎;或者尝试着优化这个模型,感受一下所谓调参党的痛苦;又或者直接尝试实现ResNet、Inception这些更为先进的网络来刷刷Cifar;再不然可以尝试着向NLP或者强化学习方向去学习一下。总之,这些事情远没有看起来那么难。
当然,不论那条路,学习,进步和自我鞭策都是逃避不掉的必修课。一个新生的领域,勃勃的生机必然也意味着新成果的层出不穷。完成我上面提到的三门课程只能让一个人从门外汉变成圈里人,有了进入这个领域,赶上这波浪潮的基本资格,至于到底是成为弄潮儿还是直接被大浪吞没,还是那句话,不劳苦必然无所得。努力学习不一定能修成正果,而不去努力学习,则注定是一无所获。
对于坚强地完成了所有课程的同学们,我得说声恭喜,我们掌握的数据来看,只有10%左右的现役程序员决定向AI转身,并付诸了行动;而能够完成基础课程的人,只占了其中的30%不到。也就是说,当你完成CS231n的最后一个作业开始,你就已经站在了开发者的Top 5%之列。
在这个层面上,通常就会面临两件更加困难的任务:追论文和补数学。
现在的机器学习界,“ArXiv醒”已经成了症候群,几乎每周都会有更先进的内容冒出来,隔一两个月就会发现很多公认的知识被刷新了,隔一两年?简直无法想象。所以跟踪学术界的动态就成了从业者的必修课。哪怕作为工业实现者,如果不能第一时间掌握学术界的动态,就一定会面临对手突然实力碾压自己的窘境。
好在机器学习界的风气和传统领域的学术界有一个很大的区别,得益于钢铁侠Elon Musk的OpenAI组织,学术界形成了ArXiv上预印论文和开源的风气。只是要想看懂这些论文和代码,前面提到的那些知识,却远远不够。看到这种论文([1706.02515] Self-Normalizing Neural Networks)的时候,你才会真正理解什么叫“没个博士学位都搞不了这东西”:
无论如何,感谢这开源的学术环境,让所有从业者都站在了同一起跑线上:最新的成果不再是大公司垄断,小公司也一样可以弯道超车,用最先进的产品占领某个细分领域市场。
同时,这也让所有人都变得压力倍增:也许辛辛苦苦积累的经验技巧模型和数据,在一个颠覆性的成果面前突然变得一文不值,随时随地都要面对后来者的降维打击。
这是个让人辛劳痛苦的领域
这是个让人振奋鼓舞的领域
这是个让人欲罢不能的领域
这是个让人充满期待的领域。
这是天堂。
这是地狱。
我们已经在这里等你,来吗,少年?