前文《在 Anki 制作 2.9 万张卡片,复习 33 万次之后,我转用了 SueprMemo》中简单地提到了渐进阅读,本文将进行更详细的介绍。
作为一名计算机的学生,渐进阅读令我非常印象深刻。因为渐进阅读(incremental reading)让我看到了,在学习上实现并发(concurrency)的可能性。
注:渐进阅读是我的翻译习惯,在其他文本中也被译作增量阅读[1]
当然,考虑到本文读者并非都是计算机专业,也不一定都学过操作系统,笔者尽可能用最通俗的语言来介绍——什么是渐进阅读。
注:本文不会介绍 SuperMemo 的具体操作,留个坑下次填。
PS:留个彩蛋,猜一下题目中的 IRAPP 是什么的缩写?
回顾线性阅读
渐进阅读是从传统的线性阅读发展而来的,想要介绍渐进阅读就避不开对线性阅读的分析。
让我们从一个例子说起:
小叶是一名计算机专业的学生,想要学习操作系统相关的知识。于是他拿起一本《计算机操作系统》开始阅读:
第三章 处理机调度与死锁
3.1 处理机调度的层次 ......................................84
3.1.1 高级调度...............................................84
3.1.2 低级调度...............................................86
3.1.3 中级调度...............................................87
3.2 调度队列模型和调度准则...........................88
3.2.1 调度队列模型.......................................88
3.2.2 选择调度方式和调度算法的若干准则......................................................90
3.3 调度算法 .....................................................91
3.3.1 先来先服务和短作业(进程)优先调度算法...............................................91
3.3.2 高优先权优先调度算法........................93
3.3.3 基于时间片的轮转调度算法.................95
3.4 实时调度 .....................................................97
3.4.1 实现实时调度的基本条件.....................97
3.4.2 实时调度算法的分类 ............................99
3.4.3 常用的几种实时调度算法...................100
。。。
小叶今天非常有时间,想要一口气学完这些内容。于是他开始从 3.3 节读到了 3.4 节。他遇到了个问题:
如选择太长的时间片,使得每个进程都能在一个时间片内完成, 时间片轮转算法便退化为 FCFS 算法,无法满足交互式用户的需求。
???FCFS 是啥来着??
好像前面的 3.1.1 有讲过,赶紧回去翻一下。哦,原来 FCFS 是先来先服务啊,好的我晓得了,继续看。
对于一些小型实时系统,如果能预知任务的开始截止时间,则对实时任务的调度可采用非抢占调度机制,以简化调度程序和对任务调度时所花费的系统开销。但在设计这种调度机制时,应使所有的实时任务都比较小,并在执行完关键性程序和临界区后,能及时地 将自己阻塞起来,以便释放出处理机,供调度程序去调度那种开始截止时间即将到达的 任务。
嗯?临界区?
好像有印象,不管了,先记住再说。
几个小时后,小叶筋疲力尽地看完了这个章节,却觉得自己脑中一团乱麻,好像没有学会什么。
。。。
大家在线性阅读时是不是经常遇到这种问题:
后文要求前文作为预备知识,而我们老是看了后文忘前文,需要经常回去看前文,浪费不少时间?而且一直记着几个关键词,总会影响自己深入思考正在阅读的文本?
这就是线性阅读的问题:被动的阅读让知识在我们的工作记忆中短暂停留,又很快的溜走。一旦忘记了预备知识,就会增大理解后文的难度。
类比
试着把我们的大脑当做一个计算机,那么阅读就像进行** I/0 操作。通过阅读,我们把信息从书本、网页上读入大脑的工作记忆**。
而工作记忆,就像缓存,读写速度快,但是容量极其有限。
当我们进行线性阅读时,很快就会达到工作记忆的瓶颈。就像 I/O 操作已经用掉了大部分缓存。
如果我们遇到需要预备知识,但是在工作记忆里找不到时,我们就需要返回前文重新阅读。就像 CPU 处理发现所需数据不在缓存里,需要重新进行 I/0 操作。
显而易见的是,I/0 操作的速度比读取缓存慢几个数量级。
当然,这里我们忘记了一种更为关键的记忆——长期记忆。如果我们能把前文的知识转入长期记忆,就可以避免返回前文阅读,直接把长期记忆调入工作记忆即可。
类比
长期记忆可以比作内存,从内存中读写虽然没有缓存快,但是要远比 I/O 操作快得多。
那么我们该怎么把知识装入长期记忆?答案是主动回忆[2]+间隔重复[3]。
唉?这个不是用 Anki 就行了,为啥还要 SuperMemo?
别急,接下来就是 SuperMemo 核心功能的介绍啦!
初识渐进阅读
把知识装入长期记忆,并不是一件简单的事情,需要主动回忆和间隔重复。主动回忆,需要我们针对知识提问,明确知识的用途和使用条件。间隔重复,需要我们在日后时不时来回顾知识,让知识保留的更长久。
所以,知识进入长期记忆需要不少时间,甚至可以说这个时间是以天为单位计算的。而我们在线性阅读中没有把预备知识装入长期记忆,阅读后文时必然遇到理解障碍。
如果我们不顾理解障碍继续阅读,会越来越懵。如果再把这种不理解的知识强行记住,不仅会很快忘记,还会损害我们的学习动力[4]。
而且,其实知识碎片化也是理解障碍的一个负面结果。没有理解的死记硬背,导致知识之间的联系不能形成连贯[5]的记忆,我们只记住了知识的形式(即字面表述)。
详见:不要在没有理解之前就去记忆 (zhihu.com)
那么该怎么办呢?让我们看看计算机是怎么做的:
类比
把阅读一篇文章视作一个进程(称为进程 R),遇到需要前置知识而在记忆中又找不到,就像一个进程请求不到它所需要的资源。
请求不到资源的进程 R 会占用 CPU,但它又不干活,白白浪费 CPU 的时间。
为了提高 CPU 的利用率,我们需要将进程 R 阻塞,转而让其他进程(比如阅读另一篇文章)使用 CPU。
阻塞的进程 R 则需等待请求的资源(预备知识)安排到位,才可继续执行。
那么我们可以把形成长期记忆视为另一个进程(称为进程 M)。形成长期记忆需要睡眠巩固、主动回忆和间隔重复。睡眠巩固并不占用白天的时间,所以进程 M 会在间隔重复时和进程 R 在白天交替使用 CPU 来做主动回忆。
当进程 M 执行后,知识进入了长期记忆,进程 R 就可以准备就绪,等待运行了。
总结一下,阅读文章和间隔重复需要互相合作,阅读文章可以提供所需要记忆的知识,但也需要预备知识的帮助,间隔重复则可以把知识装入长期记忆,以供后续阅读使用。
渐进阅读,其实就是这个思想的体现:阅读一篇文章,把目前可以理解的内容(即那些已经有预备知识帮助的内容)制作成问答卡片,以供间隔重复和主动回忆来将新的知识装入长期记忆。当读到不理解的内容,停止阅读,开始阅读其他文章。
等等,阅读其他文章?那之前的文章怎么办?
放心,我们只是暂时不继续阅读,直到我们做好准备,再进行下一次阅读。
这就是渐进阅读的意思——循序渐进,保证每一次阅读都建立在理解和记忆预备知识的基础之上。
类比
当我们有很多文章要阅读时,就像计算机中有大量进程 R 要处理。
阅读的过程中,我们需要对每个能够理解的知识点进行长期记忆。就像计算机中需要对进程 R 中得到的知识调用进程 M 来将知识装入内存。
为了避免在阅读中因为没有预备知识而卡住,我们需要换一篇文章阅读。就像计算机将请求资源的进程 R 阻塞,让其他进程 R 使用 CPU。
形成长期记忆需要睡眠、主动回忆和间隔重复,就像计算机调用进程 M 将知识写入并保持在内存。
这么一看,渐进阅读似乎挺简单的,但是要明白,并发并不是免费的,并发带来了极大的收益,也带来了不少相关的问题:
- 跳过的文章什么时候阅读?
- 该怎么制作易于记忆和使用的问答卡片?
- 怎么安排问答卡片的间隔重复?
- 怎么交错阅读与记忆?
- 我想读和想记的东西太多了,怎么权衡?
现在想来,Anki 本身只能解决问题 3,其他环节只能由使用者自己解决。而 SuperMemo 能解决 1,3,4,5,并且辅助使用者解决问题 2。
深入渐进阅读
关于问题 3,笔者已经翻译或介绍了很多相关理论和技术,在此处不再赘述,详情请见:记忆的双组分模型。
关于问题 1,4,5,SuperMemo 提出了优先级队列的概念。(是不是很像操作系统里的进程调度?沃兹博士果然是计算机专业出身233)
关于问题 2,SuperMemo 将渐进阅读划分为 6 个动作:导入、阅读、改写、摘录、挖空、回忆。这是渐进的重中之重。
优先级队列[6]
在优先级队列中,所有的问答卡片和文章都会有不同的优先级,根据优先级大小排序。
通过优先级队列,SuperMemo 会保证高优先级(排名靠前)的内容优先出现。如果我们无法完成每天的所有阅读和记忆,SuperMemo 可以自动延迟低优先级的内容,帮助我们权衡学习与时间。
注:T 表示文章,L 表示问答卡片
详情请见:Priority queue 优先级队列 · 语雀 (yuque.com)
渐进的 6 个动作
导入
导入,是我们渐进的第一步。导入什么内容,之后的一系列加工都会以此为基础。
如果我们把 SuperMemo 视作我们每日的学习工具,我们就必须慎重选择导入的材料,因为低质的文章只会浪费我们的时间。
同时,这也是我们学习动力的表现。我们的学习动力会驱使我们选择感兴趣的材料,但是我们依然要对学习内容进行一些挑选,这里是几个我认为比较有用的挑选标准:
- 基础先于实用
- 兴趣先于功利
第一条很好理解,知识不仅在一本书中有前后依赖关系,在一个领域中也是如此。打好基础对学会后续实用的内容有很大帮助,甚至可以说没有基础就难以学习后续的知识。举个例子,就比如只有学习了 C 语言、计算机组成原理、数据结构,我们才有办法理解操作系统中的知识。
第二条怎么理解呢?这又是一个很大的话题了,这里就简单说一下真正的兴趣该怎么判断:
三分钟热度、动机带有【功利】因素、来自【外在】的动机、【纯感官】的刺激导致的行为、【被动】的行为、始终停留在【心理舒适区】,不是真正的兴趣。
动机来自内心、持续时间长达多年、思维高度参与、愿意付出较高的代价、持续的自我提升(走出心理舒适区)存在【心流】(物我两忘)的现象,才是真正的兴趣。
这样看来,可能我对 Anki 和 SuperMemo 这类学习工具可能有着真正的兴趣,2333(当然,写知乎也很快乐哈哈)
关于学习的乐趣,详情请见:6 Learn drive and reward 学习内驱力和奖励 (zhihu.com)
阅读
导入了文章,自然是要阅读。关于如何阅读,大家读了这么多年书应该都有自己的习惯,我就只讲几个要点:
- 注意概念和方法
- 注意论题和结论
第一点很好理解,概念和方法都属于抽象知识,适用的范围很广泛(比如进程的概念被用于理解学习和记忆,进程调度的方法被用于渐进阅读),这种内容是阅读中最需要理解的内容。
第二点也很好理解,抓住文章主旨,可以让我们更好判断哪些是作者偏题的信息(233,作者也不是完美的),选择与主题最相关的内容阅读,并要尽快明白文章的结论,方便后续分析论证。
改写
改写往往是被人忽略的一个关键步骤。有时候我们对一段内容十分熟悉,但是真要运用的时候却发挥不出来。这就是“熟悉感”在欺骗我们,以为我们学会了。
另外,改写也是为了方便后续处理,比如补充一下文章里的指代。将代词替换为指代对象,避免之后复习时看到他、它、她,一脸懵逼。
改写还有一个好处,就是能把句子的组织逻辑拆散,还原为知识本身的逻辑。如何理解?看看这个例子就懂了:
改写还能显著降低我们的记忆难度,详情请见:基于主动回忆的学习中的知识结构与表述 (zhihu.com)
摘录
渐进里的摘录就像画重点:
不过与划重点不同之处在于,渐进阅读中摘录的重点会变成一篇新的文章,加入队列等待阅读。
这样的好处就是,我们可以不必马上制作问答卡片,而是让这些片段再飞一会儿,这些复杂的片段会在不断的改写和摘录中变成表述良好的知识。
挖空
挖空可以说是制作问答卡片最方便的方法:
在制作问答卡片时,我们往往要复制很多相同的内容。而通过挖空,我们只需要在原句上一键生成。
当然,挖空也有它的问题所在:太多的提示信息、不明的提问指向,等等。这需要我们进一步改写才能解决。
但是改写要花的时间可能比低优先级知识的复习时间还长,这显然是不合算的,所以在渐进中我们还要做出取舍。
详情请见:间隔重复中的简化与冗余 (zhihu.com)
回忆
主动回忆、测试效应这些内容说过很多了,他们的效果是有科学证明的,详情请见:【理论】测试效应——什么?考试有助于我的学习? (zhihu.com)
我想强调的重点是,知识是自己的,对知识负责,也是对自己负责。根据自己的反馈严格打分,对算法和对自己都有好处。
结语
渐进学习其实并不是一个复杂的概念,但是在学习上实现并发确实很反直觉。希望本文能够帮大家理清思路,理解到渐进学习的核心。哪怕不使用 SuperMemo,渐进学习的思想或许也能在大家的学习生活中发挥作用。
祝大家学习顺利!
2020 年 11 月 23 日
叶峻峣
彩蛋揭晓:
IRAPP 就是 Incremental Reading: A Programmer's Perspective,致敬一下 CSAPP,23333