爱德华·拉夫(Edward Raff)是 Java 机器学习库 JSAT(Java 统计分析工具的缩写)的作者。
爱德华在创建这个库时实现了许多算法,我最近联系了他,询问他能给从头开始实现机器学习算法的初学者提供什么建议。
在这篇文章中,我们将根据爱德华的建议,探讨实现机器学习算法的技巧。
通过我的新书《掌握机器学习算法》启动你的项目,包括分步教程和所有示例的 Excel 电子表格文件。

从头开始实现机器学习算法
图片来源:hackNY.org,保留部分权利
不要阅读他人的源代码
至少,最初不要。
我之所以向爱德华提出关于从头开始实现机器学习算法的建议,是因为他在一个 Reddit 问题上的评论,标题恰如其分地命名为“实现机器学习算法”。
在他的评论中,爱德华建议初学者尽可能避免查看其他开源实现的源代码。他知道这与大多数建议(甚至我自己的)背道而驰,这真的引起了我的注意。
爱德华一开始就指出,在实现机器学习算法时,有两个截然不同的任务
- 实现知名算法。这些算法在许多论文、书籍、网站讲义等中都有详细描述。你有许多来源,这些算法相对简单,是自学的良好案例研究。
- 从论文中实现算法。这些算法在文献中描述有限且稀疏,需要大量工作和先验知识才能理解和实现。
获取您的免费算法思维导图

方便的机器学习算法思维导图样本。
我创建了一份方便的思维导图,其中包含60多种按类型组织的算法。
下载、打印并使用它。
还可以独家访问机器学习算法电子邮件迷你课程。
实现知名算法
爱德华建议,如果你有兴趣实现知名算法,阅读代码是一个糟糕的主意。
我从他的评论中至少提炼出三个关键原因:
- 代码优化:开源库中的代码很可能为执行速度、内存和准确性进行了高度优化。这意味着它实现了各种数学和编程技巧。因此,代码将非常难以理解。你将花费大部分时间弄清楚这些技巧,而不是弄清楚算法,这才是你最初的目标。
- 以项目为中心:代码不会是你可以独立运行的通用实现,它会经过精心设计以在项目框架内工作。很可能框架会“方便地”抽象和隐藏细节。你将花费时间学习该框架及其设计,以便理解算法实现。
- 理解有限:研究算法的实现无助于你理解算法的抱负,它只能教你高效算法实现的技巧。在最初最关键的时期,他人的代码会让你感到困惑。
我认为这里面蕴含着深刻的智慧。
我要指出的是,开源实现有时有助于理解特定的技术细节,例如更新规则或其他可能描述不佳但通过代码中的单个函数实现的模块化数学部分。我自己也多次遇到这种情况,但这是一种启发式方法,而不是规则。
爱德华建议以 k-means 和随机梯度下降等算法作为入门的良好示例。
从论文中实现算法
爱德华认为,如果你没有首先实现上述知名算法,那么从论文中实现机器学习算法是一个巨大的飞跃。
从爱德华的评论中,你可以勾勒出一个通过从头开始实现机器学习算法来学习的过程。我对这个过程的解释如下:
- 从头开始自己实现算法。
- 将性能与现成实现进行比较。
- 努力达到性能和结果。
- 查看开源代码以了解高级技巧和窍门。
他建议,创建自己的未优化实现将指出效率低下之处,促使你解决它们,促使你深入理解它们并寻求在其他地方如何解决它们。
他还建议,简单地复制实现不会教会你需要知道的东西,你会错过对算法及其未优化性能特征的深入理解,以及优化如何推广到类似类别的算法。
给初学者的建议
经过一些电子邮件讨论,爱德华在他的评论基础上进行了扩展,并在一篇名为“初学者学习实现机器学习算法的建议”的博客文章中写下了他的想法。
这是一篇很棒的文章。在其中他回答了三个关键问题:如何从头开始实现机器学习算法,初学者的常见陷阱以及可能有用的资源。
这篇文章之所以很棒,不仅因为这些建议是来自辛苦获得的智慧(爱德华以艰难的方式进行机器学习——他实践它,你也应该如此),而且因为很少有像这样的文章。没有人谈论如何从头开始实现机器学习算法。我目前的工作就是解决这个问题。
爱德华的关键信息是你需要练习。实现机器学习算法需要你理解每个算法的背景,包括理论、数学以及该领域和算法的历史。这不会很快或很容易到来。你必须为此努力,迭代你的理解并大量练习。
如果你是一名专业程序员,那么你知道,精通需要付出的努力丝毫不减。
实现算法的技巧
在他的博客文章中,爱德华提供了4个主要技巧,可以帮助你从头开始实现机器学习算法。总结起来,它们是:
- 通读整篇论文。慢慢地通读整篇论文。然后沉浸在这些想法中一段时间,比如几天。之后再读一遍,但不要在你对算法如何工作、数据流以及它如何协同工作有一个初步的心智模型之前。带着目的阅读。随后的阅读必须纠正和改进你对算法现有的理解。
- 设计一个测试问题。找到、选择或设计一个足够简单以让你理解和可视化算法结果或行为的测试问题,但又足够复杂以迫使程序展现出区别性的特征或结果。这个问题将是你的试金石,告诉你实现何时正确以及优化何时没有引入致命错误。爱德华称之为“有用的宏功能单元测试”。
- 最后优化。首先通过从头开始实现整个算法来理解其过程和逻辑,尽可能少地利用现有代码或技巧。只有在你理解并有了一个可工作的实现之后,才应该考虑在空间或时间复杂度方面提高性能,或通过算法扩展提高准确性。
- 理解基础。在生产级别的实现中,你可以利用现有库。爱德华提到了 LIBSVM 和 LIBLINEAR 等例子。这些是强大的库,融合了几十年的错误修复和优化。在采用它们之前,请确保你确切地了解你正在利用什么,它是如何工作的,以及它提供的好处。有目的地优化你的实现,使用最好的,并理解它做了什么。
这些技巧中再次蕴含着巨大的智慧。我自己也无法说得更好。特别是,我强烈同意需要从头开始低效地实现算法,以最大限度地学习。算法优化很重要,但它完全是另一种技能,用于完全不同的目的。
请记住这一点。
避免初学者的陷阱
爱德华接着强调了初学者常犯的陷阱。总结如下:
- 不要假设研究论文是正确的,同行评审并不完美,错误(有时是重大错误)也会出现在出版物中。
- 不要试图获得对算法的无数学理解,数学可以高效、无歧义地描述算法过程的突出部分,这一点至关重要。
- 不要从别人的源代码开始,如上所述。
- 你无法先验地知道如何有效地将算法应用于问题,请从类似论文中寻找可迁移的应用思路。
- 默认的随机数生成器通常不够用,使用更好的,但不需要加密强度。
- 在优化时,脚本语言不够用(他个人的观点,并声明可能存在争议。我个人发现静态类型在大型生产系统中可以省去很多麻烦)。
总结
实现机器学习算法是学习机器学习的绝佳方式(如果不是最好的方式)。知识是触手可及的,因为你必须汗流浃背地处理细节,它们变得亲密无间。这在你试图从算法中获得最大收益时有所帮助。
在这篇文章中,你发现“阅读开源实现”这一常被建议的建议并非错误,但需要仔细融入你的学习策略。
爱德华建议你以“艰难的方式”学习机器学习算法,自己弄清楚它们以便成长,然后转向开源实现,学习高效的数学和编程技巧来优化实现,如果你需要这些效率的话。
这是一个微妙而宝贵的建议。
感谢这篇很棒的帖子。很有帮助。
你能为计算机图形学或计算机视觉领域详细阐述一篇这样的帖子吗?你能联系一些知名且多产的研究人员,他们能给我们提供建议并推荐资源,以帮助我们从头开始实现并重现顶级研究论文(SIGGRAPH、CVPR等)。
谢谢。