有没有必要把机器学习算法自己实现一遍?
有没有必要把机器学习算法自己实现一遍? 我想这个题目我还是比较有发言权的,读书时候曾经把PRML所有算法实现过一遍。最后发布了一个库,现在是Github上星星最多的Matlab库之一(应该是排第二)。读PRML的同学可以参考一下,代码注释给出了重要部分对应的公式在PRML的出处。变量命名也尽量与书做了统一。希望对学习PRML的同学有所帮助。大家觉得有用请帮忙点星星。GitHub - PRML/PRMLT: Pattern Recognition and Machine Learning Toolbox
这个经历对我的帮助大概有以下几个方面:
1) 对算法细节的理解更加深刻了。书中毕竟不会给出所有细节,而且书本身可能就是错的。为了写出代码,我几乎是把所有公式重新推了一遍,自己存下的note里面公式数量绝对远远多于书本身,期间也发现了书中无数的错误,这些错误在初读的时候根本意识不到。这样一遍下来,让我对推公式的信心大增,看论文不会怕看不懂公式了。遇到看不懂的就推一遍,推不出的就抄一遍,之后总会懂的。一个side effect就是让我变得愤青了,看什么paper都觉得烂。因为读paper的时候,你会发现,很多paper违背基本常识,即使影响力非常大的一些paper里也有这样那样的错误。
2) 可以了解很多看书学不到的各种trick。所有算法几乎都有坑。比如hyper-parameter什么意义怎么设,怎么初始化,numerical stability的怎么保证,如何保证矩阵正定,计算机rounding error的影响,numerical underflow和overflow问题等等。
3) 对整个领域各个算法的关联有更深刻的了解,思维形成一个关系网。看到一个算法就会自然的去想跟其他算法的联系,怎么去扩展。如果一篇paper我不能把它纳入到这个关系网里,我就觉得自己没懂。要么推出联系,要么推出矛盾证明这篇paper垃圾。另一个side effect就是我看paper从来不根据实验好坏判断优劣。
虽然自己动手实现算法有好处,但是性价比几何还是个见仁见智的问题,毕竟这是一个很费时的过程。我并不认为一定有必要自己实现书上所有算法,毕竟每个人所能关注的领域还是有限的,懂得算法大致原理,具体用的时候在细研究就可以。很多算法我也是写完了从来没用过。几年过去后,我在回头看自己的代码也很难看的懂,细节还得看公式。
但是对于自己的研究领域我建议还是有必要把经典算法动手实现一遍加深理解。 更新:有评论说我说的东西都很虚, 关于如何准备AI岗位面试, 可以看我的另一篇回答。
非计算机专业学生如何转行 AI,并找到算法 offer?以下为原答案。
--------------------------------------------------
国内码农同学们很喜欢纸上谈兵, 讲概念, 玩概念(编造高大名词以显得自己很博学), 甚至后期自造概念(一个简单的bug搞不清, 就制造一个复杂的概念来描述这种现象), 简直不要太多。(尤其是培训班或者一部分转专业的没有受过系统长期的编程基本功训练的同学)
由于深度学习本身的黑盒性和对数学的一定要求, 导致这种不知其所以然就乱编乱解释概念的现象更加严重。社区里充斥着各种莫名其妙的歪理邪说, 一看就是根本没有看过相关代码的外行攒出来骗人的东西。让我想到了Scala的创始人Martin Ordersky曾经发推要求大家不要再编造各种概念来解释Monad, 因为这只会让人们更加费解。 最容易理解Monad的方法, 就是自己在编程的时候去体会。
不拿别的说, 就一个最简单的CNN, 梯度弥散, 梯度爆炸, 感知域几何增长, 白化池化批处理归一化等等。 这些虚幻的名词乍一听感觉很高端复杂, 但只要你自己实现一遍, 就会发现都是最基本最直白的东西。(不是说这些概念不重要, 只是他们并不是很难的概念, 但如果你抽象的割裂的去理解这些概念, 很容易陷入用更复杂的概念解释简单概念的怪圈)
再举个例子, 我在国内某一流大学和国外都修读了 计算机组成课程(原因就是我国内修的这一遍完全没听懂), 在国内, 老师每节课都在疯狂讲概念, 越听越糊涂, 需要你有扎实的抽象能力才能理解,实验课和理论课割裂感严重, 理论听不懂, 实验不知道在干嘛, 越学越崩溃。(当然这跟我能力有限也有关系) 在国外, 这门课的目标就是自己写一个最基本的CPU,包括ALU和CU都是自己写, 乍一听是不是很夸张, 但老师一步步带着你, 真的不难, 所有理论课就是在为实验课服务, 把下一次实验课可能需要的概念, 如何操作, 为什么这么做, 都讲的清清楚楚,这样你做实验就能做到心中有数,一学期下来, 我们小组不但全部完成了各项CPU功能电路的设计, 还因为设计了一个bonus的高效除法算法受到了嘉奖, 不仅如此, 因为全部都是自己写的, 你甚至能够清楚的说出CU上控制信号的每一个比特的作用。而且回过头来, 看到你花了四个月的时间写的CPU电路之复杂, 你自己都觉得不可思议。
所以这些年, 基本上我学习任何新东西的方法, 就是去自己实现一遍。 这使得我完全不会担心被一些莫名其妙的概念唬住, 还能对很多问题的本质讲的很清楚。
所以, 我的建议,你也许不需要实现一遍【全部】的算法, 但实现一个算法一定是你理解这个算法的最好方式。
当然, 觉得自己的工作是要创造解释深度学习的数学工具的,那您的智商根本不需要通过编程来理解算法。
<hr/>
随手附上我自己实现的深度学习库, bp都是自己用numpy撸的:
https://github.com/nick6918/MyDeepLearning
<hr/>10/31补充:
注意到很多同学都提到国内的组成实验也是写CPU, 这当然没错。 我在国内读组成的时候实验也是写CPU, 但是有几个问题:
1, 你是从头开始写的吗? 还是实验环境里已经有了几乎所有的【基础代码】, 你要做的就是写几行所谓【最核心】的加减法代码?你清楚每次实验之间的关系吗? 如果让你从头来写, 你写的出来吗?有工程经验的同学应该能体会,落地算法的工程代码往往比算法本身更复杂。
2, 即使你非常优秀, 对实验原理/背景/基础代码都了如指掌, 去问问你们班成绩在中位以后的同学, 他们理解程度如何?实验是不是抄的?
3,多久写出来真的不是重点。在我看来,学习曲线越平滑证明这门课的质量越高,而不是越难质量越高。以及如果我记得没错的话,国内绝大多数计组的实验课是不写流水线的,CU也只是粗糙的一小部分。
其次, 其实到底国内组成课的质量如何并不重要, 重要的是你有没有通过这些课程学习到良好的习惯, 如果你是大神, 只靠听课就能了解的非常透彻,那自然没问题。 如果你只是和我一样理解能力一般的同学, 那我的经验是, 自己从头到尾做一遍,而不是碎片化的理解几个所谓的【核心概念】, 要更有效率的多。
对了,评论中有一个拽名词的高手,大家没事可以去围观一下。 不少自学的朋友很容易陷入到焦虑当中,尤其是在学习理论受挫之后。再加上不少人是码农出身,实现算法是就成了最容易缓解焦虑的途径。
然而要警惕掉到“用忙碌而逃避困难“的陷阱当中去,更好的缓解焦虑的方法是应用算法,去解决具体问题。众所周知,机器学习最不友好的部分不是编程,而是背后的数学原理,以及如何使用它来解决问题。照我来看,只有两种情况值得动手造轮子:
做研究,没现成的轮子可用。以我的个人经验和观察,大部分研究的demo质量都比较堪忧。侧面上反映了“科研工作者不等于好工程师”对自己的学习进度感到怀疑,可以试着实现一下算法。但这种实现最多是验证你学会了思路,而不能用于生产,因为效率和优化都比较差
除此之外,对于研究者来说,复现前沿研究也有一定的价值,因为可能:
作者并没有开源(必须自己造轮子)在复现过程中你可能会发现作者值得改进的方向,发掘了新的灌水方向在复现过程中你可能发现作者的思路其实根本就是错的,这也是为什么很多paper不会公开代码,那么避开这个陷阱
对于大部分人而言,想要了解怎么调参、每个参数的含义,都不必重新实现算法。可以直接阅读文档,也可以在在各种场景中慢慢摸索。比如参加比赛的过程中,或者实际工作里,甚至看看博客、读读知乎都可以有些收获。同时,如果能够通过解决实际问题来加深对模型的理解,还可以增强自己的信心,比实现算法可能要更为划算且有效。
在不少公司,机器学习研究员和工程师是两个岗位,前者提出思路和理论,后者去高效的实现。从这点上也不难看出一个实践者不一定需要具备两方面技能,毕竟时间有限。如果你对自己的定位是使用者(更接近工程师的话),多补补理论是当务之急。如果你想成为一个研究者,必要的编程能力要有,但不要花过多的时间在提高码力上,能做好理论已经很难,可以交给工程师实现、优化你的理论。
所以,没什么特殊情况,实现算法可以当做玩票,多看看模型、了解一些理论、应用到具体案例上去才是正事。
<hr/>对于自学的朋友,也可以参考一下我的文章:如何用3个月零基础入门机器学习? 机器学习算法的实现分为两种:
from sklearn import svm以及
相比于调包,我想题主大概指的是第二种,也就是从数学底层原理出发,把整个算法的流程从0到1直接实现一遍。此时,编程语言只是载体,一般用到的包括python/Java/C++甚至Matlab。
先说建议:
如果你是学生/研究人员,且时间足够,可以自己实现一遍。但不要为了实现算法而写代码, @微调 说的很好,要警惕掉到“用忙碌而逃避困难“的陷阱当中去,更好的缓解焦虑的方法是应用算法,去解决具体问题。所以,去kaggle或者天池上找一个比赛/一份开放数据集,或者在自己的课题中设定一个可被算法解决的问题,然后一步步去实现,对你的算法学习有很大帮助。
如果你是从业者/交叉领域应用者,那么请尽量避免从底层往高层走的算法路径。说到底,机器学习算法就是数学在应用领域的扩展和普及,说直白点,现在AI的大火让数学这个古老学科焕发了第二春,为啥以前不“春”呢?因为很多数学相关的理论、应用都需要非常底层的知识铺垫,才能由特定领域的特定数学家应用到对应问题上,时间成本太高,比如航天轨道计算、天文探测。这在学术界或许没什么,但是在大众化的市场中是不被接受的。所以,从高层往底层走,走到合适的地方就停下来,再返回底层专注于应用,是更适合的方法。
我之前写过一个算法学习的4大步骤,放在这里也给大家一个参考:
第一步,即初步了解,是对算法的基本构成,大致用途以及基础假设有一个模糊的认识,比如从某某博客中看到一个不认识的算法,知道它主要是用于分类,基于线性模型,要求独立同分布等。
第二步是教材学习,就是说当你听到这个算法的大致意思后,去寻找教材,可以是一本书,一篇博客或是知乎的一个回答,进一步了解这个算法的原理和应用场景,如算法由Logit构成,属于广义线性模型,在定义域内充分饱和等,可以用于二分类和多分类。
第三步,深入原理,此时经过一定的教材,你已经完全了解了算法的流程,知道它为什么叫逻辑回归,以及逻辑回归的作用甚至衍生算法,但对其基础原理还是一知半解,不知道Logit函数怎么来的,为什么要用负对数似然函数做LOSS,以及什么时候不该用LR等。这一步往往是最难的一步,需要大量的时间和思考,来充分理解并推导算法的组成。
对于大部分工程师来说,这一步取决于项目的时间宽裕程度(往往都是跳过的),但对于研究人员或是有心深入的人,却是必不可少的地基。吃透这一步,不管是面试还是科研,都是成为你胸有成竹的不二法门。
最后一步,自我实践,顾名思义就是通过代码将所学算法实现,现如今python和tensorflow的封装API以及各种库、包已经十分完善,我个人的建议是,除非是算法底层架构开发方向的人员,否则没有必要从0开始编写一个算法(比如在某本中文教材中,作者连numpy或pandas都不用),适当的借助工具,如可以让自己的学习经验更加的实用化,同时也加强对算法的理解。当然,在这个专栏的部分文章中,针对基础性较强的一些算法,比如逻辑回归或KNN,从底层逻辑一步步实现也是必要的,届时也会给出对应代码供大家参考。
第2、3、4步并非固定顺序,也不是走过一次就可以高枕无忧。实际上,很多时候它们是打乱的,也是迭代的,比如早上的一个项目要临时迁移算法,那么下午之前你就要完成第一步和第四步,在初步完成后,或许你会花一些时间来把第、二三步走一遍。而迭代的循环这个学习链条,可以加固算法知识和理解。 更新一段话,Quora上对于Yoshua Bengio的最新访谈,关于一个问题:
对于进入机器学习领域的年轻研究人员,你有什么建议?(What advise do you have for young researchers entering the field of Machine Learning?)
他回答到:
Make sure you have a strong training in math and computer science (including the practical part, i.e., programming). Read books and (lots of) papers but that is not enough: you need to develop your intuitions by (a) programming a bunch of learning algorithms yourself, e.g., trying to reproduce existing papers, and (b) by learning to tune hyper-parameters and explore variants (in architecture, objective function, etc.), e.g., by participating in competitions or trying to improve on published results once you have been able to reproduce them. Then, find collaborators with whom you can brainstorm about ideas and share the workload involved in exploring and testing new ideas.Working with an existing group is ideal, of course, or recruit your own students to work on this with you, if you are a faculty.
---------------------------------------原答案-------------------------------------------
实现很有必要,甚至一定要。都实现一遍倒是不必。
1. 在掌握基本的算法流程、加深对算法的理解之外,实现机器学习算法能够帮助我们建立起一种直觉:数据--模型之间的关系。这一点可能有点玄学的味道...稍微往黑了点说,就是调参的直觉、模型选择的直觉、特征选择/设计的直觉等...经验有的时候是事半功倍的效果。
2. 在实际应用场景中,其实经常会遇到需要实现一些特殊设计的算法。比如要实现某篇paper中的算法/或者自己跑实验,一般情况下这些算法并不是(甚至肯定不是)通用算法包提供的算法,一定要自己实现。这样的时候,如果以前有实现过基础的算法的经验,会有很大帮助。
3. 实现基本的算法,帮助掌握算法流程。这样会更容易应对新的编程框架。
4. 其实很多模型也有很多种解法。拿LR来说,常见的一阶的Gradient Descent、二阶的BFGS/L-BFGS之外(这些是好多库的默认方法),一阶的Back-tracking Line Search方法、Nesterov&#39;s Line Search等方法,实现起来(特别是分布式实现)比较复杂,让没有自己实现过任何机器学习算法的人来写。。。还是算了吧。。。
5. 算法的细节:优化、高效计算等(矩阵乘法的加速等)在实际工作中是蛮重要的。因为机器学习在大规模数据下最大的挑战就是如何『算』得更快:收敛速度/计算时间、计算资源/机器开销等。所以得要知道在哪里有优化的空间才行。
6. 但是全部实现一遍确实没必要,不过常用的算法的基本版还是要尽量都写一写的。
。。。
其实第一条是最重要的。。。
说了这么多有没有觉得不写一遍简直有罪?
*随时修正答案,欢迎指出任何不足的地方! 底下的回答简直是个个抛github啊,我也上一个
Dod-o/Statistical-Learning-Method_Code首先说结论:非常有必要
我记得很清楚在我刚上研究生时问老师机器学习怎么能算学到位。当时老师回我:学机器学习很容易,但是你要学会改造。
咱们知道感知机是划分超平面,SVM有个核函数,隐马是状态链观测链。这些都看过了,全会了。
但是当你开始写代码了才发现,原来还是不会,很多推导上不占地方的细节没注意真写不下去。最主要的是写的过程中你会有新的理解,真正明白了它的工作原理。
当你以后发现用某某模型性能不够好时,能一下子想到是程序哪块地方可能有问题,怎么改。这是很重要的。
最后推销一下我的github,每行代码都带注释,里面还有我写的配套博客链接。我希望机器学习的入门难度不会阻碍每一个初学者。
我对象都能看懂,确定不来看看吗? 没有必要把所有算法都自己实现的,但原理一定要懂。
在深度学习方面,做 feedforward 难度不大,难度在 backpropagtion 方面,Karpathy的博客有用numpy实现 backpropagation的,你可以看一看,写得非常巧妙。如果你用 TensorFlow, Theano 的话,是自动做 backpropagation 的,你只要定义好模型 feedforward 和 cost function 就可以了,所以从时间角度,我建议你可以直接用 TensorFlow 或 Theano 做。
当然这种工作已经有很多人做过了,你可以看看别人是怎么做的,然后再找一些模型自己实现一下。
你可以看看 TensorLayer 来学,它官网有DL 和RL 的教程以及配套的代码。它是基于Google TensorFlow 开发的,是现在工业界和学术界比较火的框架。
它的好处是每个教程里除了自己的教程外,还会推荐一些很好的博客、论文、视频,方便读者在不明白的情况下进一步阅读。
英文网站首页:Welcome to TensorLayer
此外它也有 中文文档 和 微信交流群
===================================================================
增强学习 Reinforcement Learning: RL 教程:Tutorial — TensorLayer配套代码:tutorial_atari_pong.py
抗噪自编码器 Denoising Autoencoder: DAE 教程:Tutorial — TensorLayer配套代码:tutorial_mnist.py
卷积神经网络 Convolutional Neural Network: CNN 教程:Tutorial — TensorLayer 1.1 documentation配套代码:tutorial_cifar10.py
递归神经网络 LSTM: LSTM教程http://tensorlayer.readthedocs.io/en/latest/user/tutorial.html#understand-lstm 配套代码:https://github.com/zsdonghao/tensorlayer/blob/master/example/tutorial_ptb_lstm_state_is_tuple.py
Word Embedding 之 Word2vec: Word2vec 教程:Word2vec 教程配套代码:tutorial_word2vec_basic.py
等等 哈哈哈哈,我觉得很多人都有这个疑问吧。机器学习好高大上,多么牛逼的东西,光是看公式就已经眼花缭乱了,总觉得自己该全部去实现一遍,有的时候太懒,有的时候觉得能力不够。道理虽然明白——任何事情自己亲手做一做还是更好的,但机器学习已经有了大量的库了,SVM-Light,R里面的glm()方程,自己实现一遍,最后又不敢用(因为不知道算法究竟是否正确),或者不能用(一是速度赶不上大神写的库那么快,二是精度没有专业库那么高),耗时耗力的写了一堆后究竟有什么用?
这里很多答案都提供了一些解释,但我想从另一个角度来聊聊这个问题。
我在1年半前(本科阶段)就开始接触计算心理学和机器学习方面的研究,在NAACL(自然语言处理排名第三的论坛)上发表了一篇文章,用的计算机教授写的算法库,跑的是经过AdaGrad优化的向量支持机(SVM)算法。在这种论坛发文章,你是必须去做海报展示的,站在自己的大幅海报面前傻傻的待4个小时,我的两位教授(一位是认知语言学教授,一位是计算机教授)都在那里。我的位置不太好,在最边缘的角落里,本来以为就可以赢得一份清净,Philip Resnik走了过来。直到那一刹那之前,我一直不知道他是谁。但经过教授介绍后,他是马里兰大学的机器学习和自然语言处理教授,在这个领域混了多年,在Google Schoar上的论文引用数高达12,853。
他走过来的第一句话是:“假设我一点也不懂数学,告诉我你这篇论文做的是什么。”我解释后,看到我的计算机教授走了过来和Resnik聊天,Resnik问我的教授:“你用的是不是hinge loss(辛基损失函数)?”我的教授说:“是。但不是全局优化,所以我没有叫这玩意SVM……”(我凭回忆打出来的,可能不完全精确)。当时我站在一旁觉得这他们能这样大聊特聊数学,甚至是向量支持机(我当时认为这是最厉害的算法——除神经网络以外),简直是太厉害了,我一点也听不懂他们在讲什么。
直到现在,我才明白所谓的“辛基损失函数(Hinge loss)”其实就是Max(a,b)函数,就是比较 a 和 b 谁大谁小,然后选大的那个。这玩意究竟有什么难理解的?为什么要那么高大上?你让一个五岁的小孩,问他:“有一堆红球,一堆绿球,哪一堆的球更多啊?”这个小孩都能告诉你正确答案。
当然这说的有点偏题了。后来我非常幸运的考上了研究生,才终于开始了对“高档”算法的学习。第一个学期被Christopher Manning(克里斯多夫·曼宁)的CS224N自然语言处理虐了一番,这个学期开始上Andrej Karpathy(安杰·卡帕西)的神经网络(CS231N),该君是李菲菲教授(音译,Fei-Fei Li)的爱徒,在推特上有14.9K关注者,我越看他那张方块脸,越觉得他长得像贾斯丁·汀布莱克(Justin Timberlake)。这里有篇他的新闻报道:Karpathy打败了Google的超级人工智能,但也许再没有下次了 。
我其实也是自控能力很差的人,在上安杰·卡帕西的课之前,也从没有萌生过自己去写机器学习算法的想法。原因在文章开头有提过:1. 我的代码运行速度肯定赶不上经过多次迭代的专业库的运行速度;2. 我咋知道我的代码写的就是对的呢??
我直到现在都这样认为:不考虑对方的环境和条件,知识与技能,就一味要求对方把机器学习算法都实现一遍,估计是最无理取闹的行为了吧。前天晚上,我跟另一个研究生Jason Freeman(杰森·弗里曼)聊天,他在微软的西雅图总部工作了4年,在目前越来越有名的TypeScript团队工作了3年(TypeScript是静态的JavaScript语言,正在国内和国外开始流行)——他告诉我他和安德斯·海尔斯伯格(Anders Hejlsberg)一起工作,他还经常顶撞安德斯。我的第一反应是:“他是谁……”(安德斯·海尔斯伯格是Delphi和C#之父,但我不熟悉这两门语言,所以不会崇拜他——小广告:Scala是我目前最喜欢的语言)。
我和杰森讨论的是3月份开始究竟要不要选吴恩达(Andrew Ng)的机器学习课(CS229)。我持的立场是我可能不打算上那门课,因为我已经看过大部分他的视频了,还读了他讲义的一部分(这里是讲义链接: CS 229: Machine Learning (Course handouts) )。因为我已经确定以后要做神经网络方面的研究,所以觉得他课上的一些其他内容比如特征降维(PCA),对我而言用处不大,我只需要会用就行了。我不仅用过特征降维,还用过更好的降维可视化(tSNE算法)。这玩意和我的领域不搭,为什么我要浪费时间去学?
杰森的论点是,如果我学了它们的理论(甚至把它们实现一遍),就能更好的应用它们。我说:你把直觉(intuition)当什么了?在我看来,对算法进行“直观”上的了解,就已经很足够了。什么是向量支持机?就是拿一个平面去分隔一堆点。更术语一点的解释不外乎是拿一个超平面(Hyperplane)在高维空间里去分割。什么是特征降维?就是看如何把高维度的点阵降到两三个维度。什么是alpha值?就是看这个算法学得有多快。什么是正则化(regularization)?就是别让你的算法过度拟合数据(当然L1,L2等等都有区别,但这些区别都很简单,L1让你关注某个值,L2让你利用所有的值)。
为什么我谈这么多关于理论的问题?在我看来,学习机器学习的算法的进度是这样的:应用 -》理论 -》实现。就跟教小孩折射一样,你先让他看看筷子在水中如何弯折(应用),再告诉他光的折射原因(理论),再让他自己用其他物体来试试(实现)。实现,是这个漫长学习过程的最后一步。一开始就来谈实现,实在是很神奇的事情。
让我准确论述一下我的观点:如果你是学界精英,那么去学习那些你将要使用的算法的理论,最后再自己尝试着实现他们,是很有必要的,除非你是只做应用(比如社会科学,心理学,商学等等)。如果是普通的程序员/工程师,不需要强迫自己去实现这些算法。没人会给你一个小奖章,大公司招这类员工的时候,也是更看重学历,而不是看“哦,我把‘所有’的机器学习算法都实现了一遍”。
最后送上一点我觉得实现机器学习算法最好的路径:
最好用Python和Numpy库。这两样宝具会让你非常轻松。安杰·卡帕西(Andrej)推荐用ipython notebook(现在改名叫Jupyter了),来可视化数据,以及实验算法。昨天有一个下午茶会,我们系举办的,也邀请了安杰,我跑去凑热闹,跟安杰谈到了这个问题,他说就算是大公司做研究,也是这种路径,先从ipython notebook开始(这点让我很惊讶)。
机器学习算法最难的部分其实不是写出来,而是高效率的实现,让你的算法跑快一点。其中一个技巧叫做“矢量化”(Vectorization)。矢量化就是说,能做矩阵操作就矩阵操作,最好连一个外循环都不写。
这是我写的Softmax算法的测评:(在500个样本上跑的)
naive loss: 2.384533e+00 computed in 0.255952s
vectorized loss: 2.384533e+00 computed in 0.004148s
第一个是用普通的Python和循环写出来的,第二个是用矢量化操作写出来的,可以看到64倍速度的提升——侧面也可以看到Python有多垃圾(慢)。
这个是SVM(支持向量机)算法的测评:(同样500个样本)
Naive loss: 9.102322e+00 computed in 0.136226s
Vectorized loss: 9.102322e+00 computed in 0.005909s
这次的速度提升没有那么明显,但也是26倍的提速。
但我只想说:矢量化真是很难的事情。数学家随便就写公式,也不考虑考虑可怜的计算机科学孩子们。原初的公式几十分钟就搞定,矢量化要一两个小时的冥思苦想。
最后,对于那些读懂了理论,实在是闲得无聊,或者想要进军更高级的学术界的同志们,这里是安杰·卡帕西课代码的链接:CS231n Convolutional Neural Networks for Visual Recognition。如果你不属于这个类别,就不要瞎掺合啦,用用别人的库又怎么了?骇客精神(Hacker Code)中一条就是:“不要重复劳动,有库就要用库,不然就是对库写作者的不尊重。”
(如果你还是不知道究竟该不该实现,欢迎阅读下面我增加的内容)
------------------
最近这篇文章被学姐前辈Danqi Chen看到了。。所以我稍微补充几句,免得被大牛们看到后笑话。。- ___ - || Danqi前辈是清华姚班的高材生,Chris Manning的博士,在224N课上是首席助教,然后被我缠着问了好多次问题……
这篇文章有点接近“反智”文章的边缘,大意是实用主义至上,自己实现的必要性不大。这个观点还是有很多争议的,比如目前有一个答案就“实名”反对这个答案。机器学习是一个交叉学科,作为学生而言,从不同的部门学到的机器学习,必然是不一样的。在统计学部门学到的机器学习,和在计算机部门学的机器学习,肯定是两个样。我秋天的时候跟一位概率教授上了一节课,当我告诉他斯坦福计算机入门概率课要介绍MLE(最大拟然估值)和蒙特拉罗模拟(Monte Carlo Simulation)的时候,他沉重的摇摇头,说这么早就介绍这样深刻的概念,是很不应该的,在他的部门,要第三年的学生才接触这样的知识,因为直到那时,学生才有足够的知识框架去理解这些知识。
我写这篇文章是有一定的原因的。我认识一些国内的大学同学,都异常优秀,他们努力的程度是我一辈子都比不上的,他们中一部分人因为运气不好(高考),不幸去了一些相对不是那么优异的大学,但是他们用努力弥补这个缺陷,对数学和各种学科展开攻克,很多人的阅读量和数学解题技巧也是我不能企及的。还有一部分人,是处于业界转型边缘,本来已是成熟的程序员,或者数据分析师,但是想要进一步提升自己,亦或是转型。我把这两类人定做这篇回答的目标受众。我希望为他们写一篇回答,不让他们走我走过的弯路,不受太多的误导。
开复先生(李开复)最近说深度学习急缺人才。我非常的不赞同。深度学习领域是处于半饱和状态的,实际上就业情况就是一堆熠熠生辉(Scintillating)的博士们在学术界待腻了,想要去赚点钱玩玩,就跑去业界晃一圈的状况。这和大部分人的就业状况根本是不搭边的。深度学习,以及理论机器学习,除非是平台很高,起点很高,是很难得到广泛认可的。
我最近刚买了一本书:
这本书很详细的在讲Lasso Loss(L1),写SVM的部分也非常不错,很神奇的是,三位作者,两位是斯坦福统计学系的,一位是伯克利的。如果我能读完这本书,会上来改进一下这个答案的。
最近我想提一提答案末尾写的,关于“实现”的问题。我过去几周一直在写我自己的Theano库(是的,放着牛逼的Lasagne不用,非要自己手写),终于把CNN写完后,现在在写RNN的部分。当我已经花费这么多的时间,然后意识到,我的代码暂时还只能在CPU上跑,因为我暂时还没有用Theano的CUDA库,又意识到,仅仅几周后,我的两门春季课已经开始教TensorFlow了,于是觉得自己是个傻子。
所以我自己都陷入了我回答中所写的那个陷阱:实现之后却不能使用,但又不愿意放弃自己的代码,于是只有投入更多的时间去改代码,而不是去理解数学。愿与各位共勉。
------------------- 有必要,but it depends ...
看你现在的情况,和之后想达到的目标。
且假设你的目标是算法工程师好了。
那么,我们来讨论你从现在到算法工程师的路径。
如果你是学生
自己把算法实现一遍是很有必要的。
第一当然是为了更好的掌握知识
我自身的学习经历给我的感受是。
数学:理解公式的最好方式是把公式推导一遍
计算机:学习编程的最好方式是把代码写一遍
同理,掌握算法的最好方式是把算法实现一遍。
当然算法不是背书,要带着问题去实现算法。
是什么——这个算法背后的逻辑是什么?这里涉及到了算法的数学。随口一想,线性回归和逻辑回归都叫做回归,怎么一个输出了数值一个输出了分类?为什么——这个算法本身解决了什么问题?一些算法上的设计,为什么要这么做?比如,SVM里的Kernel是干什么的?为什么要这么用?怎么用——这个算法适合什么样的问题?并没有全能算法这回事,算法,有时候选择比努力重要。
第二是为面试做准备
因为在面试的时候,算法的实现是极容易被考察到。
比如现在深度学习这么火,第一轮面试很可能叫你手写一个感知机的前向和后向。
这一下就刷掉了很多人。
很过分吗?
其实啊,你这么想,应届毕业生,一般的应届毕业生,项目经历是乏善可陈的,你的本职工作就是学习。书本上的知识现在就说不记得了,实在是说不过去的。
而且我确实认为理解神经网络的前向和后向这件事情有用的。
如果你已经工作了
那么把算法实现一遍,有益,但不是当务之急了。
很赞同@微调的心态,要警惕掉到“用忙碌而逃避困难“的陷阱当中去明确目标,列出问题,解决问题。
如果你想要转行算法工程师
查漏补缺,哪里不行补哪里,并且也要看到自己的长处。
比如码农,代码能力过关,那就补理论啊赶快。现在的通稿,一个个把人工智能和深度学习搞的像门玄学,算法也一律黑箱化了。可是算法不是黑箱子啊!大多数算法是有很清晰的内在的,就算以黑箱子著称的深度学习,搞一搞你也大概知道里面在干些什么。那种算法不就是调个API调个参的想法,不能说有错,但画地为牢,按这个思路走,你一旦遇到问题了就不知道怎么办。
比如某一领域的工程师,学习编程,并且利用自身领域知识优势,先进入有算法团队的项目,开始转型的第一步。AI+的年代了,智能汽车、智能电网,算法在传统领域上的应用项目是很多的,对本领域的工程师的需求也是在的。说实话,你真的认为叫一个软件工程师/算法工程师去学汽车、学电力、学医疗,会比你自己学编程和学算法来得更容易吗?都不容易,各有各的不容易。
如果你已经是算法工程师
你的首要工作是解决问题啊,而不是造轮子。
啥?解决啥问题?问题多了去了啊!
什么任务用什么算法,用了一套算法怎么优化,优化到哪个点算是个头,一套算法不够用了要考虑算法架构,算法够用了怎么工程化,工程化靠谱了怎么产品化……
想想还真是有点小激动呢!