编程和机器学习建议:《My Advice for Programming and ML》
被卡马克推荐的编程和机器学习建议:《My Advice for Programming and ML》,作者Joseph Suárez,链接:x.com/jsuarez5341/status/1943692968013025457
编程 10 大建议:
1、通过实践学习。从耗时几小时的项目开始,逐步挑战需要数天完成的任务。简单的游戏是绝佳选择,因为你能快速获得大多数问题的可视化反馈。我推荐使用 raylib 进行渲染——它轻量级、支持几乎所有语言,且该库本身就是优秀软件设计的典范。
2、从 Python 开始。很多资深开发者讨厌 Python,我有时也讨厌它。但无论如何你都应该从 Python 入手,因为它能让你比几乎任何其他语言更快起步。你遇到的大多数 AI 项目至少表层代码都是用 Python 写的。不过别在 Python 上停留太久——语言的设计会引导你以特定方式思考问题。避免使用复杂的外部包、继承、装饰器,以及任何会让你偏离学习用赋值、条件、迭代和函数来表达逻辑的东西。写几个基础游戏、应用程序或工具后就转向其他语言。包管理推荐使用 uv。
3、尽早学习 C 语言。C 是一门非常适合编写高性能软件的极简语言。我之所以不建议初学者先学 C,唯一原因是它要求你同时理解计算机和操作系统的工作原理,这对新手来说信息量过大。你需要掌握的核心概念包括:数据类型、类型转换、结构体、(单遍)编译、链接、内存分配、栈与堆的区别、指针。现阶段请避开 C++,它只是在 C 语言基础上堆砌了大量你暂时用不着的复杂功能。
4、警惕过度抽象。始终以最简单的方式解决眼前问题为目标。除非能百分百确定未来会出现某种情况,否则不要为了追求通用性而增加复杂度。即便真有这种需求,通常也等真正遇到时再解决更明智。C 语言在这方面表现优异,因为它移除了继承体系和臃肿第三方库这类诱人但事与愿违的工具。
5、使用 Git。这一点基础到我差点忘了提。默认在 GitHub 上创建新项目并频繁提交。这是避免工作丢失的最佳方式,还能为那些"明明之前能用"的代码提供版本回溯。~所有开源项目都通过 GitHub 运作。
6、善用调试器。调试器能让你逐行执行代码并检查局部变量值,比到处塞 print 语句高效灵活得多,还能快速跳转检查。Python 用 pdb,C 语言用 gdb 就够。写 C 语言务必搭配地址消毒器(Address Sanitizer),它能提供可读的错误提示——重要到我建议没有它就别碰 C 语言。
7、掌握基础 Unix 工具。尽快熟悉命令行操作,不必追求花哨。像 ls、pwd、cat、head、mv、cp、cd、mkdir、top 等基础命令就能满足 90%的日常需求,最常用的工具不超过 10 个。条件允许尽量用原生 Linux 系统,MacOS 尚可,Windows 则不建议——若不想双系统就装 WSL。推荐安装基础版 Ubuntu,别过度折腾系统定制。熟悉发行版的包管理工具(很可能是 apt),别用 snap。
8、警惕技术陷阱。程序员总爱发明些让事情更糟的"聪明"办法来浪费你时间。新手尤其要避开:面向对象和函数式编程(都是教条)、测试驱动开发(少量测试无妨)、频繁更换语言和发行版、行业"最佳实践"(FAANG 里蹩脚工程师多的是)、Python 类型提示系统、C 语言的 make/cmake、Hydra 这类复杂配置解析器、GitHub 子模块和花哨的 CI、React 等现代前端框架(学基础 HTML+CSS 就够了)、系统美化、X 上最新的编程潮流,以及我在开发直播里吐槽过的一切。
9、不要为了学习而刷 LeetCode。虽然这对求职面试可能是种必要的妥协,但用巧妙算法解决刁钻问题并不能代表编程的全貌。你当然应该学习基础数据结构和算法,但相比构建更多项目,掌握十种动态编程变体在面试之外的作用有限。我已多年未参加编程面试,但我确信 18 岁的我会比 28 岁的我表现更好——而 28 岁的我在其他所有方面都更出色。
10、不必过度纠结 IDE 选择。这真的没那么重要。我只用带两个插件的 NeoVim,它轻量且不碍事。是的,我用过无数 IDE;不,这根本不重要。VSCode 就不错,但请坚持通过终端运行代码而非依赖项目配置和按钮。这会打破"IDE 是神奇必需品"的幻觉。别用 AI 优先的编辑器。当你掌握了基础后,像 Copilot 或 SuperMaven 这类代码补全工具无妨,但请仅用于节省打字和文档查阅时间——而非替代思考。
---
机器学习入门
成为一名高效的研究者实际上比成为一名优秀的程序员更容易。大多数研究者的编程水平都很糟糕。优秀的程序员比糟糕的程序员更容易成为优秀的研究者。
与通用编程不同,机器学习领域的可用资源其实相当优质。斯坦福大学的 CS231n 课程可免费在线观看。重点看 Andrej Karpathy 或 Justin Johnson 讲授的部分。更重要的是——必须完成配套习题。听着,我通常不喜欢大多数课程,但这个确实很好。它的设计能让你轻松掌握知识而不必过度挣扎。你只需要知道偏导数是什么、矩阵是什么就够了。就算没见过矩阵表达式的求导也不用担心——这和单变量求导完全一样,只是有时需要对矩阵进行转置。真的就这么简单。
完成 CS231n 课程后,你将理解 autograd 的工作原理(因为你亲手实现过它)并熟练使用 PyTorch(因为你已经用它构建过项目)。恭喜,你已经学完了所有实用课程内容。下一步就是开始阅读 ArXiv 上的学术论文。对 AI 某个特定领域感兴趣?搜索该领域最重要的论文清单并研读它们。起初这会让你应接不暇,但随着时间推移会逐渐变得轻松。我在上方主文中已为你准备了强化学习领域的论文清单。我最重要的通用建议都围绕着理解科学过程的局限性展开。我的措辞都是经过深思熟虑的。请定期重读这三个段落,直到你自己领悟到它们的真谛。
1、了解科学研究的运作方式。如果不理解论文撰写时的背景环境,你就无法真正读懂论文。大多数会议强制要求 8-9 页的篇幅限制。由于 arXiv 上的论文大多已发表或计划发表,你会发现它们也遵循 8-9 页的规范。为什么连简单概念也不写得更短?因为这个页数既是上限也是下限——提交 6 页论文通常会被拒稿。为什么大量论文充斥着无关紧要的公式化数学表达?因为审稿人偏爱公式(也有些研究者单纯喜欢写公式)。为什么论文缺少某个明显的消融实验或对照组?因为撰写论文的超负荷研究生耗尽了时间和 GPU 资源(主要是 GPU)。为什么 X 领域的研究论文如此稀少?因为审稿人不喜欢这类课题。对了,还有大量论文本身就是错误的,所以当两篇论文结论直接矛盾时——它们很可能确实互相矛盾!
2、不要迷信权威。我的观点是否值得关注,应该基于我实际构建的成果来判断。我之所以提及学术头衔,只是因为很多人仍看重这些标签——正因如此,我更有资格告诉你:不要默认相信 X 会议或 Y 大学的论文。这些顶多算是弱信号,我曾耗费精力复现过某些本应更严谨的研究者发表的虚假结果,深受其害。虽然较少见,但确实有人为发表论文而直接造假。更常见的情况是,实验室里连续六个月的超负荷工作导致了实验数据噪声和研究者的一厢情愿。判断研究可靠性的最佳指标是开源代码、多次独立复现以及在后续工作中的实际应用——即便如此,这个信号仍不完美,我在这方面也栽过跟头。复现论文结果是绝佳的学习方式,但要明白这可能耗时数月。不过在学习新领域时,你绝对应该动手实现一些基础性论文!
3、寻找错误。默认出版物存在错误,找出其中的隐患。实验设计是否控制不当?基线是否过于薄弱?提供的推理是否是结果的唯一合理解释?努力将论文内容与其通常过度复杂的表述分离开来。在论文正确的前提下,它如何与相关研究相契合?建立直觉需要验证主张和模式匹配相结合。你可以将其视为评估某个方向或方法是否值得投入时间的概率。当某个领域的所有论文都犯同样错误时,最大机遇就会出现。这种情况通常发生在某个主题的前提或标准评估存在根本缺陷时。杰出的研究者能穿透集体短视的面纱,开辟新方向。
编程 10 大建议:
1、通过实践学习。从耗时几小时的项目开始,逐步挑战需要数天完成的任务。简单的游戏是绝佳选择,因为你能快速获得大多数问题的可视化反馈。我推荐使用 raylib 进行渲染——它轻量级、支持几乎所有语言,且该库本身就是优秀软件设计的典范。
2、从 Python 开始。很多资深开发者讨厌 Python,我有时也讨厌它。但无论如何你都应该从 Python 入手,因为它能让你比几乎任何其他语言更快起步。你遇到的大多数 AI 项目至少表层代码都是用 Python 写的。不过别在 Python 上停留太久——语言的设计会引导你以特定方式思考问题。避免使用复杂的外部包、继承、装饰器,以及任何会让你偏离学习用赋值、条件、迭代和函数来表达逻辑的东西。写几个基础游戏、应用程序或工具后就转向其他语言。包管理推荐使用 uv。
3、尽早学习 C 语言。C 是一门非常适合编写高性能软件的极简语言。我之所以不建议初学者先学 C,唯一原因是它要求你同时理解计算机和操作系统的工作原理,这对新手来说信息量过大。你需要掌握的核心概念包括:数据类型、类型转换、结构体、(单遍)编译、链接、内存分配、栈与堆的区别、指针。现阶段请避开 C++,它只是在 C 语言基础上堆砌了大量你暂时用不着的复杂功能。
4、警惕过度抽象。始终以最简单的方式解决眼前问题为目标。除非能百分百确定未来会出现某种情况,否则不要为了追求通用性而增加复杂度。即便真有这种需求,通常也等真正遇到时再解决更明智。C 语言在这方面表现优异,因为它移除了继承体系和臃肿第三方库这类诱人但事与愿违的工具。
5、使用 Git。这一点基础到我差点忘了提。默认在 GitHub 上创建新项目并频繁提交。这是避免工作丢失的最佳方式,还能为那些"明明之前能用"的代码提供版本回溯。~所有开源项目都通过 GitHub 运作。
6、善用调试器。调试器能让你逐行执行代码并检查局部变量值,比到处塞 print 语句高效灵活得多,还能快速跳转检查。Python 用 pdb,C 语言用 gdb 就够。写 C 语言务必搭配地址消毒器(Address Sanitizer),它能提供可读的错误提示——重要到我建议没有它就别碰 C 语言。
7、掌握基础 Unix 工具。尽快熟悉命令行操作,不必追求花哨。像 ls、pwd、cat、head、mv、cp、cd、mkdir、top 等基础命令就能满足 90%的日常需求,最常用的工具不超过 10 个。条件允许尽量用原生 Linux 系统,MacOS 尚可,Windows 则不建议——若不想双系统就装 WSL。推荐安装基础版 Ubuntu,别过度折腾系统定制。熟悉发行版的包管理工具(很可能是 apt),别用 snap。
8、警惕技术陷阱。程序员总爱发明些让事情更糟的"聪明"办法来浪费你时间。新手尤其要避开:面向对象和函数式编程(都是教条)、测试驱动开发(少量测试无妨)、频繁更换语言和发行版、行业"最佳实践"(FAANG 里蹩脚工程师多的是)、Python 类型提示系统、C 语言的 make/cmake、Hydra 这类复杂配置解析器、GitHub 子模块和花哨的 CI、React 等现代前端框架(学基础 HTML+CSS 就够了)、系统美化、X 上最新的编程潮流,以及我在开发直播里吐槽过的一切。
9、不要为了学习而刷 LeetCode。虽然这对求职面试可能是种必要的妥协,但用巧妙算法解决刁钻问题并不能代表编程的全貌。你当然应该学习基础数据结构和算法,但相比构建更多项目,掌握十种动态编程变体在面试之外的作用有限。我已多年未参加编程面试,但我确信 18 岁的我会比 28 岁的我表现更好——而 28 岁的我在其他所有方面都更出色。
10、不必过度纠结 IDE 选择。这真的没那么重要。我只用带两个插件的 NeoVim,它轻量且不碍事。是的,我用过无数 IDE;不,这根本不重要。VSCode 就不错,但请坚持通过终端运行代码而非依赖项目配置和按钮。这会打破"IDE 是神奇必需品"的幻觉。别用 AI 优先的编辑器。当你掌握了基础后,像 Copilot 或 SuperMaven 这类代码补全工具无妨,但请仅用于节省打字和文档查阅时间——而非替代思考。
---
机器学习入门
成为一名高效的研究者实际上比成为一名优秀的程序员更容易。大多数研究者的编程水平都很糟糕。优秀的程序员比糟糕的程序员更容易成为优秀的研究者。
与通用编程不同,机器学习领域的可用资源其实相当优质。斯坦福大学的 CS231n 课程可免费在线观看。重点看 Andrej Karpathy 或 Justin Johnson 讲授的部分。更重要的是——必须完成配套习题。听着,我通常不喜欢大多数课程,但这个确实很好。它的设计能让你轻松掌握知识而不必过度挣扎。你只需要知道偏导数是什么、矩阵是什么就够了。就算没见过矩阵表达式的求导也不用担心——这和单变量求导完全一样,只是有时需要对矩阵进行转置。真的就这么简单。
完成 CS231n 课程后,你将理解 autograd 的工作原理(因为你亲手实现过它)并熟练使用 PyTorch(因为你已经用它构建过项目)。恭喜,你已经学完了所有实用课程内容。下一步就是开始阅读 ArXiv 上的学术论文。对 AI 某个特定领域感兴趣?搜索该领域最重要的论文清单并研读它们。起初这会让你应接不暇,但随着时间推移会逐渐变得轻松。我在上方主文中已为你准备了强化学习领域的论文清单。我最重要的通用建议都围绕着理解科学过程的局限性展开。我的措辞都是经过深思熟虑的。请定期重读这三个段落,直到你自己领悟到它们的真谛。
1、了解科学研究的运作方式。如果不理解论文撰写时的背景环境,你就无法真正读懂论文。大多数会议强制要求 8-9 页的篇幅限制。由于 arXiv 上的论文大多已发表或计划发表,你会发现它们也遵循 8-9 页的规范。为什么连简单概念也不写得更短?因为这个页数既是上限也是下限——提交 6 页论文通常会被拒稿。为什么大量论文充斥着无关紧要的公式化数学表达?因为审稿人偏爱公式(也有些研究者单纯喜欢写公式)。为什么论文缺少某个明显的消融实验或对照组?因为撰写论文的超负荷研究生耗尽了时间和 GPU 资源(主要是 GPU)。为什么 X 领域的研究论文如此稀少?因为审稿人不喜欢这类课题。对了,还有大量论文本身就是错误的,所以当两篇论文结论直接矛盾时——它们很可能确实互相矛盾!
2、不要迷信权威。我的观点是否值得关注,应该基于我实际构建的成果来判断。我之所以提及学术头衔,只是因为很多人仍看重这些标签——正因如此,我更有资格告诉你:不要默认相信 X 会议或 Y 大学的论文。这些顶多算是弱信号,我曾耗费精力复现过某些本应更严谨的研究者发表的虚假结果,深受其害。虽然较少见,但确实有人为发表论文而直接造假。更常见的情况是,实验室里连续六个月的超负荷工作导致了实验数据噪声和研究者的一厢情愿。判断研究可靠性的最佳指标是开源代码、多次独立复现以及在后续工作中的实际应用——即便如此,这个信号仍不完美,我在这方面也栽过跟头。复现论文结果是绝佳的学习方式,但要明白这可能耗时数月。不过在学习新领域时,你绝对应该动手实现一些基础性论文!
3、寻找错误。默认出版物存在错误,找出其中的隐患。实验设计是否控制不当?基线是否过于薄弱?提供的推理是否是结果的唯一合理解释?努力将论文内容与其通常过度复杂的表述分离开来。在论文正确的前提下,它如何与相关研究相契合?建立直觉需要验证主张和模式匹配相结合。你可以将其视为评估某个方向或方法是否值得投入时间的概率。当某个领域的所有论文都犯同样错误时,最大机遇就会出现。这种情况通常发生在某个主题的前提或标准评估存在根本缺陷时。杰出的研究者能穿透集体短视的面纱,开辟新方向。