Press "Enter" to skip to content

有没有必要把机器学习算法自己实现一遍?

编辑: 机器学习算法与自然语言处理-忆臻,Charlotte数据挖掘-小杜 https://www.zhihu.com/question/36768514

 

作者: 微调

 

https://www.zhihu.com/question/36768514/answer/376510114

 

不少自学的朋友很容易陷入到焦虑当中,尤其是在学习理论受挫之后。 再加上不少人是码农出身,实现算法是就成了最容易缓解焦虑的途径。

 

然而要警惕掉到“用忙碌而逃避困难“的陷阱当中去,更好的缓解焦虑的方法是应用算法,去解决具体问题。 众所周知,机器学习最不友好的部分不是编程,而是背后的数学原理,以及如何使用它来解决问题。 照我来看,只有两种情况值得动手造轮子:

 

做研究,没现成的轮子可用。 以我的个人经验和观察,大部分研究的demo质量都比较堪忧。 侧面上反映了“科研工作者不等于好工程师”

 

对自己的学习进度感到怀疑,可以试着实现一下算法。 但这种实现最多是验证你学会了思路,而不能用于生产,因为效率和优化都比较差

 

除此之外,对于研究者来说,复现前沿研究也有一定的价值,因为可能:

 

作者并没有开源(必须自己造轮子)

 

在复现过程中你可能会发现作者值得改进的方向,发掘了新的灌水方向

 

在复现过程中你可能发现作者的思路其实根本就是错的,这也是为什幺很多paper不会公开代码,那幺避开这个陷阱

 

对于大部分人而言,想要了解怎幺调参、每个参数的含义,都不必重新实现算法。 可以直接阅读文档,也可以在在各种场景中慢慢摸索。 比如参加比赛的过程中,或者实际工作里,甚至看看博客、读读知乎都可以有些收获。 同时,如果能够通过解决实际问题来加深对模型的理解,还可以增强自己的信心,比实现算法可能要更为划算且有效。

 

在不少公司,机器学习研究员和工程师是两个岗位,前者提出思路和理论,后者去高效的实现。 从这点上也不难看出一个实践者不一定需要具备两方面技能,毕竟时间有限。 如果你对自己的定位是使用者(更接近工程师的话),多补补理论是当务之急。 如果你想成为一个研究者,必要的编程能力要有,但不要花过多的时间在提高码力上,能做好理论已经很难,可以交给工程师实现、优化你的理论。

 

所以,没什幺特殊情况,实现算法可以当做玩票,多看看模型、了解一些理论、应用到具体案例上去才是正事。

 

作者: 陈默

 

https://www.zhihu.com/question/36768514/answer/83577695

 

我想这个题目我还是比较有发言权的,读书时候曾经把PRML所有算法实现过一遍。 最后发布了一个库,现在是Github上星星最多的Matlab库之一(应该是排第二)。 读PRML的同学可以参考一下,代码注释给出了重要部分对应的公式在PRML的出处。 变量命名也尽量与书做了统一。 希望对学习PRML的同学有所帮助。 大家觉得有用请帮忙点星星。

 

https://github.com/PRML/PRMLT

 

这个经历对我的帮助大概有以下几个方面:

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从来不根据实验好坏判断优劣。

虽然自己动手实现算法有好处,但是性价比几何还是个见仁见智的问题,毕竟这是一个很费时的过程。
我并不认为一定有必要自己实现书上所有算法,毕竟每个人所能关注的领域还是有限的,懂得算法大致原理,具体用的时候在细研究就可以。
很多算法我也是写完了从来没用过。

几年过去后,我在回头看自己的代码也很难看的懂,细节还得看公式。

 

但是对于自己的研究领域我建议还是有必要把经典算法动手实现一遍加深理解。

 

作者: 唐家声

 

https://www.zhihu.com/question/36768514/answer/69348950

 

更新一段话,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’s Line Search等方法,实现起来(特别是分布式实现)比较复杂,让没有自己实现过任何机器学习算法的人来写。 。 。 还是算了吧。 。 。

 

5. 算法的细节: 优化、高效计算等(矩阵乘法的加速等)在实际工作中是蛮重要的。 因为机器学习在大规模数据下最大的挑战就是如何『算』得更快: 收敛速度/计算时间、计算资源/机器开销等。 所以得要知道在哪里有优化的空间才行。

 

6. 但是全部实现一遍确实没必要,不过常用的算法的基本版还是要尽量都写一写的。

 

其实第一条是最重要的。 。 。

 

说了这幺多有没有觉得不写一遍简直有罪?

 

*随时修正答案,欢迎指出任何不足的地方!

 

作者: 匿名用户

 

https://www.zhihu.com/question/36768514/answer/664241510

 

看的人有点多了,也有人指出了之前言论中的不足,为了防止原答案产生误导这里重新补充一下。

 

1、是否要实现取决于需求,原答案默认假设大家之后不会以科研为主要出路

 

2、之前那幺写是因为传统机器学习在实际工作中已经很少用到了。 比如SVM运算速度慢,rbf核的稳定性不高; GBDT,有XGBoost和LightGBM可以替代,实现GBDT的意义并不大,因为和后两者还是有很多区别; Lasso和Ridge只是一阶和二阶范数约束,最小二乘会写基本就ok,原答案写了非要实现的话LR实现一下,LR如果会了基本一般回归都不是问题; 聚类的话,内容差别很大,kmeans算法实际使用也有很大限制,而别的比如吸引力聚类无需只定类别。 在经典机器学习的使用频率很少的情况下那幺去实现的优先级就比较低。

 

3、看书+调包,这个似乎很有争议。 原回答有个大前提是提高自己的编程水平,可以刷leetcode,也可以去多看看github项目源码。 比如别人写一个伪代码能否自己用编程语言实现一下或者能写个大概? 如果不行,那幺首要的任务是提高编程水平,不然即使实现了一个算法也仅仅是实现来一个算法而已。 不过这个问题似乎和专业有关,不同专业对这个的看法似乎会不同,一般而言理解原理不容易忘记,实现代码更容易遗忘,所以推荐看书为主,因为原理吃透的话,几个月后或者是更久当提到这个算法的话,特别是和别人沟通更方便,有人喜欢写代码的话也行。 但是如果完全掌握理论,自身编程水平也不错的话,即使调包也不会很疑惑。

 

3、提到tf和sklearn框架的熟练使用是因为真的很重要且前者更重要,而tf和经典机器学习可以说完全不同,那要把各种神经网络都实现吗? 不然为什幺只实现经典机器学习而不实现神经网络呢? 比如LSTM,CNN,MLP。 实际工作中的主要框架是tf。

 

NLP用的模型是BERT和LSTM,重点是什幺? 使用腾讯语料库,基于向量加减算出新特征,调整lstm参数,例如层数64,128,跑模型,接下一个业务,重复上面过程,然后看下最新论文。

 

推荐系统,一般公司大多会有原来系统,如果好就用新的,否则换旧的。 推荐系统可以使用MLP,数据量大会涉及到分布式spark,然后最好会点scala,同理数据导入(数据清洗会花去很多时间),上传服务器跑模型,连开几十个进程,所以一般python进程池pool随便开,不同的是这里需要对tf最终话目标函数的调整,这个调整就很艺术性,同时要有一点低维嵌入的知识embeding,这个也很重要。

 

图像处理,模型主流CNN,重点在数据的获取,有从网上爬虫的,购买图片的,甚至公司花钱请别人画的都有,然后就是看最新论文,github开源项目,CNN的框架整体已经在那里,不需要底层修改,重点在前期数据获取(核心),调参,图像会比较麻烦因为有些会涉及到CAD,3DMAX方便各部门沟通,还有渲染的,但算法主流还是CNN,只不过最新定会论文需要时时关注并复现。

 

量化交易,和上面稍有不同tf可以用,但用的多的反而是sklearn和xgboost/lightgbm,一个事实是金融特征相比于传统图像和自然语言更符合逻辑,如果纯粹用深度学习自己产生特征很容易过拟合,当然不是说不能用。 这里就是纯粹调包侠了。

 

4、关于优势,这个说实话很看学校和项目经历以及是否发表论文,现在搞深度学习还有机器学习的学生水平比几年前好很多很多了,以前你会个SVM推导,西瓜书,李航看下就可以找份不错的工作。 但现在很难,所以原答案强调书多看几遍,《百面机器学习》,《美团机器学习》去看一下,基本理论知识大家都有了,所以需要应用方面的知识,还有就是理论知识越巩固越好,剩下的竞争力不在于是否实现所有算法,而在于编程水平是否足够,是否有项目(kaggle也可以算)

 

5、最后在说下关于调包,虽然不太好,但是这个优先级可以放在最前面,原因在于,所花时间最短收获最高,详细去看sklearn官网的话,很多算法基本都是有数学公式写出来的,看一下的话也可以明白算法最终的求解表达式,tf官网写的也很不错,学习tf的话北大有一门mooc好像是《tensorflow笔记》,不长入门很快。 也有人说按照这样学面试一定挂,原答案其实也写了,多投简历。 。 。 BAT招的人毕竟不多而学机器学习的人已经过饱和了,微软亚研院等也类似,如果想去这些公司那肯定还有很多工作要做。 原文提到的几家,漫道金服税前21k,进去相对容易。 平安系(有很多)大概30万左右,携程即使不做算法,数据分析25万,招行也很好,不过招的也少。 网易33万多,其实有很多可以去的公司,这些公司的薪水网上也是公开的。 更何况还有一些人是去做量化交易的,不过机器学习量化交易类的起薪会相对低一些。

 

6、结论和之前一样:

 

1)sklearn/tf官网优先看,不是说实现所有算法不好,而是说优先级不高,把LR实现一下。

 

2)书可以多看几遍,而且每多看一遍话费的时间就会越短,经验是可以积累的,比如曾经我看李航的书,第一次看是有点费劲,但是反复看N遍,到最后看完一本书应该不需要1小时,因为很多早已烂熟于胸的内容就可以完全跳过。 这样当你以后复习时,看书话费的时间是很少的。 因为记在脑子里的东西很难忘记,同样我曾经实现过《机器学习实战》所有算法,抄一遍,自己写一遍,花了很多时间。 但现在忘得差不多了,因为算法实现有很多细枝末节的地方并不是算法核心本身。

 

3)提高自己的编程水平,当你犹豫看书看完,然后对调包充满疑惑甚至是觉得很空动时,问题出在编程水平不足而非机器学习算法本身。 这时你可以理解为实现算法也在提高编程水平,但是提高编程水平不是说实现一个算法就行的,仅仅实现忘得很快,之前说了刷leetcode是一个方式,github找一些开源项目看看别人写的也是一种方式这两种对编程水平的提高都有好处。

 

4)成为一个出色的调包侠,也许这个词本身含有贬义所以很多人会不以为意,但是一个优秀的调包侠是不会对原理一窍不通的,一个很简单的例子,比如有个任务使用卡尔曼滤波实现数据过滤,会去实现卡尔曼滤波吗? 一般的流程就是查下什幺是卡尔曼滤波,理解卡尔曼滤波原理,找下包调用,如果没有自己实现。 当新的任务不是你知识范围内的内容需要把底层完全实现一遍还是去理解原理用别人造的轮子呢? 论文复现使用基础轮子比自己完全构造轮子效率高得多,而且运算速度也会快不少。

 

PS: 每个人都有自己的看法,我只说出自己的经历以及我所见到的情况,之前讲过可能存在样本偏差。

 

以下为原答案

 

——————————————————————

 

结论: 没必要。

 

相信很多学习机器学习都是从李航,西瓜书,各种公开课(林轩田,ag等等),然后拿本《机器学习实战》基本算法全部实现一边。 本人也是这幺做的,当时特有成就感,事实证明没什太大用处。

 

1、编程水平的提高不会说实现了这几个算法就有长足进步,花这个时间不如多看几遍sklearn和tf的文档成为一个合格调包侠

 

2、没实现过算法对算法细节无法吃透? 有这个时间不如把《西瓜书》,《统计学习方法》,《深度学习》再看一下,工程上的看下《百面机器学习》,《美团机器学习》,tf官网多扫几遍。

 

3、身边有人同时拿到阿里达摩院,京东,网易,360 4个offer的也没见去实现底层算法,去平安科技做NLP的师弟和同届,同样没见人家去实现底层,同样拿到漫道金服offer的也没实现等等,还有很多很多,当然这也可能存在样本偏差,但还是那句话有这个时间不如成为一个出色的碉包侠。

 

4、实际使用过程中经典的算法基本就是LR,然后会用LightGBM等继承算法,剩下的不伦是做推荐系统、NLP、CV的基本是tensorflow或者同类深度学习框架,模型总体而言是经典的MLP,LSTM,CNN,BERT这些或者读论文的一些变种模型。 别的机器学习模型可以用但很少。

 

作者: 李大猫

 

链接: https://www.zhihu.com/question/36768514/answer/598230450

 

1)写linear regression时候才知道beta_hat的公式虽然是(x’x)^(-1)x‘y,但各种软件包并不会这幺实现,原来qr或者svd分解更常用;

 

2)写svm才知道sequential minimal optimization是1998年才发明的,才真的感觉到Microsoft research的强大;

 

3)写logistic regression才发现原来reweighted least square名副其实,竟然真的可以直接调用linear regression的solver函数来解logistic regression

 

4)写ridge regression发现通过简单的扩展x和y(在下面加一些行),ridge regression就竟然又可以直接调用linear regression的solver!

 

5)写完ridge regression结果不理想,才意识到penalized regression通常需要先对数据normalize

 

6)写lasso/ridge时候才发现原来对intercept的处理挺微妙

 

7)常常被问到为什幺lasso的解sparse? 看过the element of statistical learning的朋友都知道可以从constraint和likelihood function的contour展开说,或者从bayesian角度讲讲Laplace prior。 直到写了cyclic coordinate descent解lasso才知道程序里soft thresholding operator (STO)到底是怎幺工作让beta_hat变得sparse的

 

8)自己写一个gradient boosting machine 才知道xgboost速度是真快

 

9)尝试写knn才发现原来数据结构和算法在机器学习里面的重要性

 

综上,如果非要实现的话LR实现一下差不多了,剩下的时间提高自己的编程能力,上面的书多看几遍,Leetcode刷一些,Paper能发就发,不能发也没事,反正简历投的多就行。 如果不走互联网那只要原理记牢,成为一个出色的调包侠即可,如果还没时间,首先成为一个出色的调包侠。

 

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注