上期说到,Anki 算法是 sm-2 算法的变体,也是纯状态空间算法的代表[1]。今天我们就从 Anki 的算法说起,看看状态空间方法是怎样构建记忆模型的。
Anki 的状态空间方法
状态
想要确定状态空间,我们得先知道,什么是状态。
状态是一种如果重现则可以由观察者再次识别的情形[2]。
也就是说,划分状态能将多个发生时间点不同的相似情形归类,对同样的状态做同样的处理。
让我们看看 Anki 是怎么确定状态的:
这是 Anki 数据库中的 card 表,记录了每张卡片的元信息。其中,根据 Anki 的源码,以及数据库的相关文档可知[3],参与复习算法的数据主要来自 ivl、factor、due。另外学习者的反馈也是 Anki 算法的重要输入,这里记作 grade。
属性解释
ivl:算法安排的间隔
due:实际复习的日期
factor:间隔系数
为了方便理解,我们对这三个属性进行一个简单的变换处理,将 ivl 定义为记忆稳定性 S(参见:记忆难题),due 定义为实际间隔 t,factor 定义为难度 D。
状态转移
也就是说,Anki 对记忆的状态定义就是 。根据 Anki 的算法,我们便可以列出状态转移表:
grade | D | S | t |
---|---|---|---|
没有复习的一天 | 不变 | 不变 | +1 |
重来 | -20% | =1 | =0 |
困难 | -15% | = S * 1.2 | =0 |
一般 | 不变 | = [S + (t - S)/2] * D | =0 |
简单 | +15% | = t * D | =0 |
grade 是我们复习时的反馈,根据不同的反馈情况,记忆的状态会有不同的改变。虽然 Anki 的公式是基于经验的,但是在不少情况下它是符合我们对记忆的直觉的。
比如:
- 卡片越难(D 越小),记忆稳定性提升的就越少,显而易见
- 复习间隔越长(t 越大),记忆稳定性提升的就越多,也就是间隔效应
- 遗忘要增加卡片难度(D 变小),并使记忆稳定性归 1
- 太简单的卡片要降低卡片难度(D 变大)
至于遗忘曲线中提到的遗忘速率先快后慢,在这里并没有体现。这也是 Anki 的一个问题所在。之后会引入一个更好的状态定义方法,可以解决这个问题。
状态空间
从这张表中我们会发现,Anki 算法涉及了三个状态值和一个输入值。我们来考察一下这个状态空间有多大:
D 在 Anki 算法中有着上下界,大致为 [120%, 690%],由于 D 的加减都是 5 的倍数,所以可以将 (690 - 120) / 5 = 114 作为定义域的基数(也就是可能取值的个数)
S、t 的取值只有 1 作为下界,并以天作为最小单位,如果我们将研究范围缩小到一年以内,那么它们的基数都为 365。
grade 的取值也是只有 4 种,进一步缩小我们的研究范围,只看做出复习反馈的结果(不做出反馈我们也无法研究),那么状态空间的大小就可以用以上四个属性的笛卡尔积空间大小来表示:114 * 365 * 365 * 4 = 60750600。
当然,这个只是状态空间的上界,考虑到实际的数据分布,有很多状态值的组合是不会被观察到的。
但是这个状态空间还是太大了,而且有些属性无法反映出记忆的本质属性。比如 t,作为实际复习间隔,只能反映出学习者隔了多久进行复习,想要反映出回忆概率,还需要与记忆稳定性相结合才能给出答案( )。
为此,不妨将 t 替换成 ,这样得到了一个 [0,1] 区间上的标准值。根据定义,我们可以称其为记忆可提取性,与记忆群体的保留率相对应,通过统计同一记忆状态下的不同反馈比例可以得出真实的保留率。(例如重来记作遗忘,其余记作记得,就能算出保留率)
这也是 SuperMemo 算法所基于的记忆模型,又称 DSR 模型(Difficulty, Stability, Retrievability)[4]。以后我们会进一步分析此模型,本期不会过多涉及。
有了状态空间,我们就能将记忆状态映射到坐标系空间中,将每次反馈的状态点连成行为线。通过研究记忆的行为,我们就能探寻更多关于记忆的规律。
算法适应性
说完了 Anki 的状态空间方法概要,我们来看看这种方法有哪些优点和局限。
优点
Anki 算法的优点其实很简单,那就是它够简单。一个状态转移表 + 状态向量,就能把算法描述完整。并且在经验上,Anki 的状态转移方法是符合直觉的。
缺点
Anki 的缺点就是状态转移十分死板,庞大的状态空间被不合理的利用浪费掉了。比如:
- Anki 对提前复习和自动延迟复习的支持不佳,大部分情况下,t 和 S 是相等的,对于 t 与 S 不相等的状态优化能力不足
- 稳定性增长只与 D 和 t 有关,忽略了 S 本身的影响
- 稳定性增长与 D 和 t 的关系被设定为线性,实际上根据数据统计结果来看,应当是非线性的,需要另外的函数进行拟合
- D 的变化被限制在 20% 以内,使得离初始值较远的状态空间需要很多反馈才有可能达到
为了改进这些不足,SuperMemo 做了长达 30 年的优化,主要也是围绕状态转移方法,在此基础上用数据拟合的方法来改进状态转移方法。
总结
总得来说,状态空间方法就是通过归纳,将相似的记忆情形归纳起来,然后用状态转移来描述记忆随着时间和复习的变化。
通过忽略无关的区别,缩小状态空间,观察到记忆状态的变化规律,得到状态转移方程,构建记忆算法。这就是这类算法的设计思路。
彩蛋
不知道大家有没有发现一个神奇的地方,那就是这些状态不包含卡片本身的内容。也就是说,状态空间方法仅仅通过反馈来估计记忆状态,而不涉及材料本身的内容。
这个特点也是一把双刃剑,对于 Anki 这种主要依靠用户自己制卡的软件,算法本身不可能得知别人记忆这些卡片的情况,所以状态空间方法就能发挥出其不依赖卡片内容的优势。
但是,如果是背单词之类的大量相同内容的话,平台可以很方便地收集大量用户对相同单词的记忆情况,便可以基于单词本身做算法优化(墨墨收集了四百多亿数据了,很强[5]),从而击败无法利用这些数据的状态空间方法。(当然,即使如此也有很多问题待解决)
当然,结合这两种方法,或许会得到更高效的算法?毕竟状态空间那么大,如果能用海量数据来填充状态空间,得到更优的状态转移方程也不是什么难事了。(当然,还是很难的,这涉及系统本身的各种性质,整理后再分享给大家)
算法之路慢慢,其修远兮。这里是学委叶哥,大家下期再会!
叶峻峣
2021 年 1 月 16 日
参考
1. 复习算法发展的两大方向 ./343419228.html2. 《系统化思维导论》[美] Gerald M. Weinberg 6.2 状态空间
3. Database Structure https://github.com/ankidroid/Anki-Android/wiki/Database-Structure
4. 记忆的两个组成成分|浓缩通俗版 ./179076885.html
5. 基于BMMS收集的记忆行为数据 https://www.maimemo.com/