分享一些高效阅读论文和代码的方法

来自:大猿搬砖简记

我们来聊聊一个比较轻松、也是很多朋友关注的话题:如何能更高效阅读一篇论文、学习一份源码呢?

以我自己的经验来看,有效的方法无外是3点:

  • 写笔记。按照自己的思路重新捋顺一个新东西的逻辑,并尽最大可能查缺补漏。

  • 多动手。少点幻想,多去实践。代码看不懂就跑,公式不理解就推,有难以验证的猜想就去做实验。

  • 有耐心。这是最重要的一点,很多我们认为难的东西,其实只是因为我们缺少了解它的耐心。

下面围绕这3点,配合我自己的一些实践例子,展开谈谈。

一、写笔记

1.1 如何写笔记

(1)一定要自己先读一遍论文/原始材料

很多朋友拿到论文,习惯先去网上找解读文章,其实我不推荐这种方法,因为别人的解读思路和观点可能会造成先入为主的效果,影响我们自身对论文的解读。

所以,请一定在自己还是一张白纸时,先做自行阅读,在英文方面有困难的朋友,可以借助gpt的帮助。

在阅读的过程中,可以按照作者的思路:

  • 总结要点

  • 标注不懂之处

(2)费曼学习法下的笔记策略

从学生时代开始,我就是费曼学习法的深度受益者,这个方法的要点就是:

  • 追溯这个新知识的前世今生。以我自己常读的cs技术论文为例。对于文中提出的技术,我们需要按符合常人逻辑思考顺序的方式想一遍,也即【之前的人是怎么解决这个问题的?】【之前的解决方法优缺点是什么?】【新技术的作者是基于什么提出目前的解决方法?】【为什么新技术要被设计成这样,换成另一种思路行不行】。在这个过程中,始终有一条主线牢牢贯穿你的整个逻辑思维过程,比起怎么做,多问问自己为什么。当然,这些“追溯”的内容在原始论文中基本不会有(related work是粗糙的),所以需要我们做大量的额外调查阅读。

  • 写笔记时,尽量抛开所有的参考材料,一气呵成。我一般习惯对着我记录的大纲、草稿纸上推演的公式来写笔记,这个过程基本不会再看原始资料了。只要第一点做好了,这个过程就是水到渠成。

  • 用老师的口吻来写笔记。即使笔记只有你自己一人看,也请假设你是在教别人一个全新的知识,进而你会自然而然爆发出非常多的问题,迫使你不断去探究这个问题的答案。

  • 不要害怕有一天会忘记这些知识。我们时常会有一种想法“很多技术不经常用,就会忘记了,因此即便我此刻学得如此认真,我也不能永久记住,那有什么用呢?”我个人觉得,“忘记”才是常态,而我们写笔记的目的就是,有一天当我们需要用起这些被忘记的技术时,我们能通过自己的这份笔记,在10分钟内迅速回忆起所有的细节,而不需要再四处查找资料。

1.2 什么时候才值得写笔记

上面我们聊了聊写笔记的方法,你可能已经感受到:写一篇学习笔记原来这么不容易!那我想要了解的东西有好多,难道每一个技术我都要写这样的笔记吗?

以我自己的经验来看:

  • 当开始了解一个新技术时,只简单记一些大纲、做一些批注。

  • 对于奠基类的经典技术(比如transformer,位置编码,rlhf等),一定要写笔记

  • 对于其余的技术变种(例如基于xxx经典模型架构改进的yyy之类),如果你需要用代码真得跑起来,那么你在代码实践后,可以补充一些架构图。以及当你有实操经验后,你再补充一些实践方法论总结。

  • 剩下的只是了解类的东西,就不需要再费时去整体详情了。

1.3 为什么经典技术值得写笔记

你可能想问,像transformer这些经典架构,网上已经有无数解读文章了,这些东西太基础了,似乎不值得我花时间再去整理它。

但是,越是经典的、被用得多的东西,可以探究的细节就越多,毕竟无数后人在这些框架上开发改进。我的想法是:常读常新,常学常悟。

举个例子:“在使用RoPE位置编码的情况下,现在长文本有一个很常用的训练范式,即先用较小的theta基数(比如常规的10000),较短的文本去做训练;然后再调大theta基数,在更长的文本上去做微调。”

为什么要这样做呢?如果一开始就用大基数和长文本训练,会有什么不一样吗?

尽管RoPE已经被使用得如此频繁,且大部分人都能熟练掌握它的形式,但面对这个问题,可能很多人还是很难大致回答出为什么。因为我们并没有尝试用一套能够自洽的逻辑阐述过RoPE到底在做什么,细致到它的超参选择上。

实操的改进和debug往往就藏在那些我们忽略的原理中。

二、多动手

当我们从原理上了解一个新技术后,下一步就是动手实践了,也就是读、改、跑代码的过程。这里我也简单分享一些经验。

2.1 代码 > 论文

当你发现论文很难读懂,或者代码和论文之间有gap,请你一定相信代码。

如果在阅读代码的过程中,你发现这个gap非常大,建议可以从代码本身出发,抛开原始论文,重构这个技术,并做好笔记。

2.2 从代码绘制架构图,讲好故事

和论文有一条逻辑主线一样,代码也有其主线。找到代码主线的好方法就是绘制架构图。使用【主体架构图 + 细节】的方式来把控整个代码的阅读。

  • 优先用官方提供的架构图。比如vllm这种,官方就给过几版很清晰的架构图,方便我们快速理解设计思想,然后在读代码的过程中不断完善架构图细节。

  • 没有官方架构图时,自己最好在阅读源码后绘制一张。

代码也是文字,它也能串成一个故事。如果你能在阅读源码后,把源码转变成一张张图,能做到对着图,从架构到关键细节复述一遍整个源码的设计思路,那么这份代码就算被完全理解了(不要只看架构,不看细节,有很多trick就藏在细节里)。

如果对于一些经典的、常用的代码我们能按这个方式走一遍,总有一天我们会发现,这一类架构的代码,我们基本都能做到扫一遍就能清楚知道它在做什么事。

2.3 写好注释

写注释是读代码(也是防止自己走神、打瞌睡)的好方法。对于一些关键函数,我们尽量把【输入输出类型、含义】以及【整个函数在做什么事】都写清楚。在函数内也尽量按一个比较漂亮规整的格式,分块注明他们在实现什么功能。

2.4 打印输入输出尺寸

对于算法这类代码来说,打印输入输出尺寸,往往可以帮助我们从直觉上快速了解这个模块在做一件什么事。在这个基础上我们再去看细节。

【看不懂就动手跑,千万不要原地纠结】

2.5 把代码重写成cpu版本

有时候,我们的手里的gpu不够,但跑起这个模型又需要大量的卡,我们该怎么办呢?

如果我们只是想学习这份代码,了解模型的运作细节,我们可以动手把模型改成cpu形式。我们知道一个模型中可能有许多架构近似的module,由于我们只是想知道数据是怎么流动的,我们可以动手删掉一些module,把整个模型改成cpu版本,然后拿1个batch去做试验。改写的过程也是帮助我们熟悉模型的过程,这一招是我常用的方法,从中获得很多收益。它适合你不以探索模型各种性能为目的,只想了解模型原理的细节的情况。

但是如果你想探究分布式训练性能,或者超参设置对性能的影响时,这一招就不管用了。不过尽管你可能无法实操,但依然不影响你阅读代码。

三、有耐心

这里想给大家一点信心,请不要因为担心自己努力钻研和做过的事情没有回报,而失去探索的热情。因为【用心做过的事情有回报】本来就是偶发事件,但【用心做过的事情会留下痕迹】却是必然事件,收获若不在此时,必然在未来没有想到的某一刻。

所以不管是付出的过程,还是等待收获的过程,都多一些耐心就可以。就和我们学习新技术和代码一样,最终能够达到一个令自己满意的、自洽的逻辑就行了,没有标准答案,否则就不会有后继无数次的迭代。


备注:昵称-学校/公司-方向/会议(eg.ACL),进入技术/投稿群

5e146e603a92f042b8e325cf51fd72d8.png

id:DLNLPer,记得备注呦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值