别迷信艾宾浩斯:学习算法选型的坑与替代方案
本文从产品实践出发,对比艾宾浩斯、Leitner、SM-2、FSRS 等算法,指出艾宾浩斯在真实学习场景中的三个致命坑,并给出选型决策框架。
为什么我不再迷信艾宾浩斯曲线
2年前我第一次做背单词 App 时,几乎没犹豫就选了艾宾浩斯遗忘曲线作为复习算法。它被写进所有教科书,有明确的数学公式,看起来最“科学”。
结果上线一个月,用户留存掉了 40%。
不是曲线本身错了,是我把它用错了地方。艾宾浩斯原始实验用的是无意义音节,而我用它来安排真实单词的复习——单词有语义、有语境、有词根,记忆难度远低于无意义音节,但算法还是按原始衰减曲线在催用户复习,导致过度复习,用户觉得很烦。
艾宾浩斯算法的三个致命坑
坑一:固定时间窗,忽略个体差异
艾宾浩斯曲线假设遗忘速率对所有人和所有材料都一致。但实际中,一个单词对初学者可能是新知识,对进阶者只是确认。用同一套时间窗去推,要么压垮初学者,要么让进阶者觉得无聊。
示例对比:
| 用户类型 | 艾宾浩斯推荐的复习间隔 | 实际需要的间隔 |
|---|---|---|
| 初学者 | 1天、2天、4天、7天、15天 | 1天、3天、7天、14天、30天 |
| 进阶者 | 同上 | 3天、7天、14天、30天、60天 |
固定时间窗意味着你强迫所有用户走同一条遗忘曲线,结果就是谁都不舒服。
坑二:无法处理“已经记住”的情况
艾宾浩斯算法是纯时间驱动的:到点就提醒复习。它不考虑用户当前对这条内容的掌握程度。
如果一个用户在第一次复习时就正确回忆了,按 SM-2 或 Leitner 系统,这条卡片的间隔会翻倍。但艾宾浩斯不会——它还在用原始计划。这意味着用户被要求复习他已经牢牢记住的内容,浪费时间和耐心。
坑三:缺乏对“难度”的反馈
真实学习材料有难有易。一个单词“apple”和一个单词“ephemeral”的难度天差地别。艾宾浩斯公式里没有难度参数,所有条目被一视同仁。
这导致用户花大量时间复习简单的词,而真正需要重复的难词却被低频复习。
替代方案:三种主流算法对比
Leitner 系统
最简单的手动间隔重复系统。用户准备几个盒子,每个盒子对应不同复习频率。正确回答的卡片升级到更高盒子,错误回答的降级。
优点: 直观、无需计算、适合纸质卡片或简单 App。 缺点: 盒子数量固定,间隔跳跃大,无法自适应个体差异。
SM-2(SuperMemo 2)
Piotr Wozniak 的经典算法,引入“质量评分”(0-5),根据评分调整间隔和难度。
优点: 自适应个体表现,间隔随正确次数指数增长,已被 Anki 等工具验证。 缺点: 质量评分主观,不同用户评分习惯不同;算法对评分波动敏感。
**伪代码示例(TypeScript):**
```typescript
function calculateNextReview(
quality: number, // 0-5
repetitions: number,
previousInterval: number,
easinessFactor: number
) {
if (quality < 3) {
repetitions = 0;
return { interval: 1, ef: easinessFactor };
}
if (repetitions === 1) {
return { interval: 1, ef: easinessFactor };
} else if (repetitions === 2) {
return { interval: 6, ef: easinessFactor };
} else {
const interval = Math.round(previousInterval * easinessFactor);
return { interval, ef: easinessFactor };
}
}
### FSRS(Free Spaced Repetition Scheduler)
较新的算法,基于机器学习模型,根据用户历史复习数据预测遗忘概率,动态调整间隔。
**优点:** 无需用户评分,自动学习用户记忆模式,准确度高。
**缺点:** 实现复杂,需要足够历史数据(通常 >100 次复习)才能收敛。
## 选型决策框架
**我后来做了一个简单的决策树来选学习算法:**
```text
1. **用户是否需要手动标记掌握程度?**
- 是:用 Leitner(简单)或 SM-2(精确)
- 否:用 FSRS(自动)
2. **数据量是否足够?**
- <100 条:用 SM-2 或 Leitner
- ≥100 条:考虑 FSRS
3. **产品形态是工具还是内容?**
- 工具(如背单词 App):推荐 SM-2 + 难度标记
- 内容(如文章阅读):推荐 FSRS 或自定义间隔策略
工程实践中的注意事项
1. 不要一次性推送所有复习
很多开发者拿到算法就一次性计算所有待复习条目,然后一股脑推给用户。这会造成认知过载。正确做法是每次只展示 5-10 条,复习完一批再加载下一批。
2. 允许用户手动跳过
无论算法多好,总有预测不准的时候。给用户一个“跳过/已掌握”按钮,并在算法中记录这个动作作为负样本。
3. 难度分级要独立于间隔
不要把“难度”和“间隔”混在一起。难度是输入参数,间隔是输出结果。在 SM-2 中,我建议把难度拆成两个独立因子:
- 语义难度(词根、词频)
- 用户历史表现(正确率、反应时)
4. 冷启动策略
新用户没有历史数据,建议用一套保守的默认间隔(如 1天、3天、7天、14天),并在前 10 次复习中收集数据,之后切换到主算法。
最后的判断
学习算法没有银弹。艾宾浩斯曲线作为理论基石值得尊重,但直接把它当产品算法用,大概率会翻车。
我现在的做法是:
- 小产品用 SM-2(它在 Anki 里被验证了十几年)
- 有数据后用 FSRS 做微调
- 永远保留用户手动干预的接口
算法是引擎,产品是车。引擎再好,车开起来不舒服,用户照样下车。
PaxLee