SuperMemo 与 Anki:间隔重复算法笔记
本页目录
2014 年想做一个背单词应用时,我首先碰到的问题是:怎样安排复习,才能适应每天不一样的空闲时间?当时我研究了 SuperMemo 和 Anki,希望找一个自己能够理解、实现并逐步验证的起点。
这份笔记保留这个问题,但需要先修正原稿:不能把 Anki 简化成固定的 SM-2 实现,也不能说它们一旦漏掉一天复习就会失效。算法的调度与用户实际能投入的时间,是需要一起设计的两件事。
SM-2 的基本模型
SM-2 为每个记忆项目保存复习间隔和容易度因子 EF,而不是对所有词使用同一张固定日程表。初始 EF 为 2.5。在连续成功回忆的序列中,间隔按天计算:
I(1) = 1
I(2) = 6
I(n) = ceil(I(n - 1) × EF),n > 2
这里需要区分“间隔近似按比例增长”和“间隔固定不变”。EF 控制增长幅度,但它也会随回答质量更新。对全新的内容,还需要先学习;给 EF 一个初值不等于已经学会了这张卡片。
回答质量 q 使用 0 至 5 的评分:0 至 2 属于回忆失败,3 至 5 表示成功但困难程度不同。更新公式为:
EF_new = max(1.3, EF + 0.1 - (5 - q) × (0.08 + (5 - q) × 0.02))
括号内展开后等于 EF - 0.8 + 0.28q - 0.02q²。原稿把它们写成先后两个版本,这是不对的:两式完全等价。q = 4 时 EF 不变,q = 5 时增加 0.1,因此 EF 也不是只会下降,更不能把初值 2.5 当作上限。
失败后要重新开始成功复习序列,而不是不加区分地继续放大上一次间隔;也不应把这理解为所有历史参数都重置成初始值。完整步骤还包含当日对低评分项目的再次复习,不能只拿间隔递推式就声称实现了完整 SM-2。算法定义见 SuperMemo 的 SM-2 原始说明。
Anki 不只是“SM-2 换个按钮”
Anki 的传统调度器在 SM-2 基础上做了调整,区分新卡学习、复习和重新学习,并提供 Again、Hard、Good、Easy 四种反馈。学习步骤可以很短,正常复习间隔也可以按天或更长计算,原稿“Anki 只按小时计划”的说法不准确。
现在 Anki 还支持 FSRS。具体行为需要结合所选调度器和牌组选项理解,不能用 2014 年的观察概括今天的实现。Anki 官方的算法说明介绍了两类调度器。
原稿还把“推迟了几天才复习”误解为“打开卡片后回答得慢”。它们不是一回事。设计调度时,要分别记录计划到期时间、实际复习时间和反馈;不要仅凭按钮名称或倒计时界面推断内部算法。
提示,能不能成为第三面
我当时觉得六档甚至四档自评有点难选,于是想到“三面卡片”:词汇、提示、释义。提示可以是词根或语境。用户在没有提示时就想起答案,与看到提示后才想起来,应当能够被区分。
这样可以把交互化成三种结果:直接记得、提示后记得、不记得。但它只是产品假设,不意味着可以把三种结果随意映射到任何算法的评分。提示本身也改变了任务难度,必须明确要训练的是独立回忆,还是在语境中识别。
这个方案还有一个容易被忽略的条件:用户看完答案之后的“我认识”,不能等同于看答案之前就能回忆。先给用户回忆的机会,再显示提示与答案,反馈才更有解释力。
从算法到每天真的能用
原来的设计目标是:不强制每天学习固定数量的新词;允许中途暂停后继续;反馈不超过三种;支持提示面。这些目标仍值得讨论,但“复习数量不设上限”不等于用户应该无限增加负担。
迁移时,我把后续应验证的问题整理为:
- 先处理多少到期复习,再引入多少新词,才能适应当天可用的时间?
- 中断后如何展示积压,而不让用户觉得必须一次补完?
- 提示是否真的帮助了之后的独立回忆,还是只让当次回答更容易?
- 如何比较不同方案:除了完成卡片数,还要看延迟回忆表现和实际投入时间。
调度公式决定“什么时候再看”,交互决定“我们得到的反馈意味着什么”,内容决定“用户究竟在记什么”。三者必须放在一起考虑。相关的需求与数据设计整理在背单词软件设计案例中。
相关文章
- GeoHash 指南2016-09-07
- 从不顺手到自己做:背单词软件设计笔记2014-05-30
- 重新认识软件测试:从二度人脉设计测试用例2013-08-31
- 学习的悖论:用指标观察进步,而不是代替目标2026-11-06