背景
我是 FSRS 的作者。我在高中时期使用 Anki 取得了显著成效,这激发了我对间隔重复算法的浓厚兴趣。
- 技术细节
在高中使用 Anki 一年半后,我的成绩有了大幅提升,这帮助我成功考入了中国的一所顶尖大学。这段经历激发了我研究间隔重复调度算法的兴趣。若想了解更多关于我本科期间的科研工作,请参阅:我是如何在本科期间发表顶会论文的?(内含开源代码和数据集) - 知乎
我的完整论文可在此处获取:
A Stochastic Shortest Path Algorithm for Optimizing Spaced Repetition Scheduling
2023_Optimizing Spaced Repetition Schedule by Capturing the Dynamics of Memory_Su et al.pdf - Google
2022 年
2022 年 8 月 19 日
一切始于我在 Reddit 上发布的一篇帖子。当时我在墨墨背单词发表的论文被 ACM SIGKDD 会议接收了,然后我在 r/Anki 子版块分享了这一消息:
然而,一位评论者却不以为然,认为这不过是又一个「纸上谈兵听起来很酷,但最终无人付诸实践」的玩意儿。这条评论着实刺激到了我。于是,我下定决心要证明他是错的,决定亲自在 Anki 中实现 FSRS 算法。
- 技术细节
那时我已经有一段时间没用 Anki 了。在此期间,Anki 的代码库已经用 Rust 语言重写,其开发者也引入了通过 JavaScript 实现自定义调度的功能。由于我当时对 Rust 完全不熟悉,因此我选择了利用 Anki 基于 JavaScript 的自定义调度脚本功能来实现 FSRS。
2022 年 8 月 30 日
我很快便遇到了第一个障碍:自定义调度功能不支持直接在卡片中存储记忆状态,而这对于实现 FSRS 而言至关重要。我在 Anki 官方论坛上报告了此问题,Anki 的首席开发者 Dae 随后在 Anki 2.1.55 版本中加入了必要的功能支持。
2022年 9 月 8 日
我迅速实现了墨墨背单词论文中的 DHP 算法的简化版本,并将该调度器的代码以开源形式发布在了 GitHub 上。此举之后,那位最初对我的想法不屑一顾的 Reddit 用户收回了他先前的话。更有趣的是,他后来还成为了 FSRS 社区中最为活跃的贡献者之一。
Implement a new spaced repetition algorithm based on anki custom scheduling. : r/Anki
2022 年 9 月 18 日 (FSRS v1)
我通过 Google Colab 添加了一个优化器,从而创建了 FSRS 的第一个可用版本。
New progress in implementing the custom algorithm. : r/Anki
- 技术细节
FSRS 必须能够从用户的复习历史中学习其个体的记忆模式。由于我无法在 Anki 的 JavaScript 调度器内部或以插件形式运行优化器,因此我使用了 Google Colab 来托管机器学习相关的代码。FSRS 的优化器和调度器代码作为 FSRS v1 版本被发布在了 GitHub 上。
2022 年 9 月 21 日
我在 Colab 上构建了一个基于 Python 的 FSRS 模拟器,用以测试调度算法的效果。这使我能够观察到经过优化的 FSRS 实际上会如何安排复习计划。
- 技术细节
因为我个人更熟悉 Python,所以我在 Google Colab 中编写了一个模拟器的 Jupyter Notebook。
Release v1.1.0: run notebook in local & format outputs & add intro of simulator (#5) · open-spaced-repetition/fsrs4anki
2022 年 9 月 28 日 (FSRS v2)
我对模型进行了改进,增加了更多参数,并采用了我论文中提出的「遗忘后稳定性(post-lapse stability, PLS)」公式。刚好这次更新恰逢 Anki 2.1.55 Beta 测试版的发布。该测试版通过自定义调度脚本功能,实现了在卡片上存储自定义数据的功能。
Anki 2.1.55 Beta is now available. : r/Anki
- 技术细节
FSRS v1 版本使用的是 SuperMemo 的 PLS 公式,但该公式与我的数据拟合效果不佳。因此,我移植了自己论文中的 PLS 公式,为初始稳定性和难度添加了更多参数,并引入了「难度均值回归(difficulty mean reversion)」机制以避免陷入「简易地狱(ease hell)」的困境,从而将参数总数从 7 个增加到了 14 个。Anki 2.1.55 Beta 测试版则为存储自定义数据提供了支持。
Release v2.0.0 · open-spaced-repetition/fsrs4anki
2022 年 10 月 5 日 (FSRS v3 & 助手插件)
我开发了一个助手插件,用以读取完整的复习日志并准确地重新计算记忆状态。
- 技术细节
原先的脚本无法访问卡片的完整历史记录,因此将 SM-2 的数据转换为 FSRS 的状态只能做到近似。此外,更新参数还会导致「复合错误」的产生。为此,我开发了 FSRS 助手插件,它可以解析复习日志,使用当前参数重新计算记忆状态,并据此调整复习间隔。
从 Python 代码中解析 JavaScript 代码一度令我非常头疼。最终,我决定采用正则表达式直接从自定义调度脚本中提取参数。问题在于,FSRS v2 版本中的参数是根据其所属的记忆公式进行分组的,这使得正则表达式的匹配变得相当复杂。因此,我决定将所有参数存储在一个扁平化后的一维数组中。在为这种新的参数结构重构代码的过程中,我还借此机会借鉴了 SM-18 算法中的难度公式,重新设计了 FSRS 内部的难度计算方式。
FSRS v3 版本包含 13 个参数,而 FSRS v2 版本则有 14 个。
FSRS v3 版本发布帖:Big update in FSRS4Anki v3.0.0 : r/Anki
助手插件链接:⚙FSRS Helper (Postpone & Advance & Load Balance & Easy Days & Disperse Siblings) - AnkiWeb
2022 年 10 月 18 日
我开始面向志愿者收集用于间隔重复系统(SRS)研究的复习数据。
数据收集表单:收集用于 SRS 研究的复习数据。
2022 年 11 月 16 日
FSRS v3 版本发布后,纷至沓来的用户反馈促使我将工作重心放在了实现功能请求和修复 bug 上。在此阶段,我添加了「推荐保留率」功能,其设计目标是最大限度地减少用户的复习工作量。该功能采用了我论文中 SSP-MMC 优化算法的一个简化版本。
New features of FSRS4Anki from v3.0.0 to v3.6.0 : r/Anki
Introduce recent changes of FSRS4Anki, and want to collect some feedback : r/Anki
2023 年
2023 年 1 月 28 日
我使用 SuperMemo 的经验让我深刻体会到其「提前(Advance)」和「推迟(Postpone)」功能的价值。FSRS 算法本身具备智能判断哪些特定卡片最能从提前或延迟复习中获益的能力。因此,我将这两个功能整合进了 FSRS 助手插件中。
Let your review be freer: postpone & advance cards via FSRS4Anki Helper : r/Anki
2023 年 2 月 11 日
部分用户反映他们的每日复习量波动较大,另一些用户则希望减少周末的复习任务。尽管已存在解决此类问题的插件,但它们往往需要较长时间才能生效。然而,FSRS 能够在重新调度时批量修改卡片的到期日期和复习间隔。应几位用户的请求,我将「负载均衡(load balance)」和「休闲日(free days)」这两项功能都集成到了 FSRS 助手插件中。前者有助于平滑每日的复习负荷,后者则允许用户在每周的特定日子安排较少的复习任务。
Load Balance & Free Weekend have been implemented in the FSRS4Anki helper add-on! : r/Anki
2023 年 3 月 16 日
随着社区内积极反馈的日益增多,越来越多的 Anki 用户开始使用 FSRS。鉴于此,Anki 的开发者 Dae 考虑将 FSRS 直接集成到 Anki 软件中。对我而言,这无疑是最激动人心的消息,因为它意味着这款最流行的开源间隔重复软件将有可能采用由我研究和开发的算法。这也激励我着手规划对 FSRS 的进一步改进。
Integrate FSRS into Anki as an optional feature · Issue #2443 · ankitects/anki
2023 年 4 月 12 日
为了能够直观地识别 FSRS 算法的潜在缺陷,我将「校准图」引入到了优化器当中。
Feat/Calibration graph by L-M-Sherlock · Pull Request #212 · open-spaced-repetition/fsrs4anki
2023 年 4 月 16 日
校准图成了一个催化剂,极大地推动了社区成员共同改进 FSRS 算法的进程。从那时起,包括我在内的几位活跃贡献者共同提出并测试了数十个改进方案。
与此同时,部分用户反映 FSRS 会将「关联卡片」(即源自同一笔记的不同卡片)的复习安排得过于集中。为此,我在 FSRS 助手插件中实现了「分散关联卡片」功能。
Feat/disperse siblings by L-M-Sherlock · Pull Request #61 · open-spaced-repetition/fsrs4anki-helper
2023 年 4 月 30 日
还记得我在文章开头提到的那位评论者吗?正是他引发了这些极具价值的讨论。
几位热心的用户在网上展开了数百轮的激烈讨论,最终碰撞出了一些关键的创意火花,从而显著改进了 FSRS 算法。
2023 年 6 月 9 日
我将优化器重构为一个独立的 Python 软件包,加入了详细的评估功能,并引入了「小批量(mini-batch)」处理支持,从而将训练速度提升了约 10 倍。
Main updates of FSRS4Anki from v3.7.0 to v3.23.0 : r/Anki
- 技术细节
为了协助社区进行调试和验证各种想法,我添加了详尽的模型评估功能。在贡献者们的帮助下,我们还将优化器重构为一个独立的、封装良好的 Python 软件包,这极大地简化了后续的维护和开发工作。之后,为了进一步提升优化速度,我引入了小批量处理支持,将训练时间缩短了约 10 倍。
2023 年 7 月 13 日 (FSRS v4)
我发布了 FSRS v4 版本,该版本采用了「幂律遗忘曲线(power forgetting curve)」,改进了用于计算难度和记忆稳定性的公式,并加入了「异常值过滤(outlier filtering)」功能。
- 技术细节
主要变更包括:
1. 遗忘曲线模型从指数函数调整为幂律函数
2. 引入hard_penalty(困难惩罚)和easy_bonus(简单奖励)参数
3. 设置四个独立的初始稳定性参数
4. 针对首次复习进行预训练
5. 加入异常值过滤器
6. 采用最佳训练周期(epoch)的参数选择机制
参数数量从 13 个增加到 17 个。
Release v4.0.0 · open-spaced-repetition/fsrs4anki
2023 年 7 月 14 日
FSRS 的难度计算公式相当简陋,因此我们都认为这方面显然存在改进的空间。然而,大多数的尝试都以失败告终。
2023 年 7 月 29 日 (FSRS-Optimizer)
我将优化器部分的代码拆分到了一个独立的仓库中,并着手定义一套标准的复习日志格式,以便 FSRS 能够被更广泛地采用。
- 技术细节
为了简化开发和维护流程,我将优化器相关的代码从 fsrs4anki 代码库中提取出来,迁移到了一个专门的仓库——fsrs-optimizer。与此同时,我启动了为间隔重复系统的复习日志定义一套标准格式的工作。推行这项标准化工作的目的在于,使各种不同的间隔重复系统(SRS)应用程序都能够方便地采用 FSRS 算法,并利用其各自的用户数据来进行算法优化。
PyPI 上的 FSRS-Optimizer:FSRS-Optimizer · PyPI
2023 年 8 月 17 日 (FSRS-rs)
我和我的朋友 Asuka Minato 开始着手开发优化器的 Rust 版本。他在 Rust 语言方面拥有坚实的基础,但缺乏机器学习相关的知识;而我则具备机器学习背景,却对 Rust 一无所知。这看起来像是一个完美的组合,因此我们决定联手开发 FSRS 优化器的 Rust 版本,主要目的是为 FSRS 最终集成到 Anki 中做好准备。
- 技术细节
最初,我们尝试使用tch这个 crate(Rust 的软件包)。然而,由于它依赖于libtorch,导致编译后的文件体积达到了大约 200MB——几乎是 Anki 软件本身大小的一半——这显然是无法接受的。这次挫折几乎让我们彻底放弃了采用 Rust 的方案。之后,Minato 向我推荐了tinygrad。由于它不依赖于 torch,因此看起来很有希望在 Anki 内部使用。但在持续的努力之后,我发现其性能表现过于糟糕,并且充斥着大量缺陷(bug),迫使我也不得不放弃了这条路径。
此后,Minato 在经过一番调研后,又向我推荐了dfdx、candle以及burn。最终,burn被证明是最易于上手且最能满足我们需求的。于是,FSRS-rs 的开发工作正式拉开帷幕。
WIP/rewrite FSRS in burn · open-spaced-repetition/fsrs-rs@a9cc7df
Asuka Minato 的视角:陪伴是最长情的告白(contribute to anki)
顺便一提,在当时,GPT-4 对于编写代码来说简直是神器。它使得我这个对 Rust 一窍不通的人,也能够用它将 Python 代码翻译成 Rust。我也在这个过程中开始学习 Rust,Minato 也教了我不少。据我估计,FSRS-rs 最初大约 60% 的代码是由 AI 生成的。
2023 年 8 月 23 日
我发现校准图存在被「刻意操纵(gamed)」的可能性。这意味着,仅仅基于校准图得出的评估指标可能会产生误导。自此,「对数损失(Log loss)」成为了评估算法性能的首选黄金标准指标。
2023 年 9 月 6 日 (SRS 基准测试)
我利用 66 位志愿者提供的复习数据集合,创建了一个基准测试,用以评估 FSRS 及未来可能出现的其他模型。
- 技术细节
在 FSRS v4 版本的改进过程中,我们已经摘取了许多「低垂的果实」,使得后续的进一步提升变得愈发困难。此外,当时用于评估模型的数据集仅来源于少数几位活跃的贡献者,这使得对一些较小改进的可靠验证变得颇具挑战。在与社区成员商议后,我开始着手创建一个基准测试。其目标是利用我先前收集到的规模更大的复习数据集(当时包含了 66 个数据集合)来评估 FSRS v4 版本以及未来的改进方向。
[Doc] Introduction for FSRS v4 · Issue #351 · open-spaced-repetition/fsrs4anki
SRS 基准测试的首次提交记录:build dataset from anki file · open-spaced-repetition/srs-benchmark@450ee90
这个基准测试也帮助我将 FSRS-rs 与 FSRS-Optimizer 进行对齐,以确保两者的优化效果几乎完全一致。
2023 年 9 月 8 日
我在修复了一些问题之后,FSRS-rs 实现了完整的优化器功能,并开始着手将其集成到 Anki 之中。
- 技术细节
经过数周的开发,我遇到了一些 bug,后来发现这些是源自burn库的上游问题。在与burn的开发者们协作排查问题,并得益于社区成员提交的补丁之后,FSRS-rs 最终成功实现了优化器的全部功能。随后,便开始了将其集成到 Anki 的工作。在整个过程中,Anki 的开发者 Dae 给予了大量帮助,对此我深表感激。此外,这个时间点恰好是 FSRS 项目启动的一周年纪念日,我当时在 r/Anki 子版块分享了这一进展:In the 1st anniversary of FSRS, I want to share some progress of recent works. : r/Anki
Integrate the FSRS optimizer by dae · Pull Request #2633 · ankitects/anki
Integrate FSRS into Anki by dae · Pull Request #2654 · ankitects/anki
2023 年 9 月 14 日
又一次,社区内展开了数百轮的激烈讨论。
我无法在此一一概述所有讨论内容,但其关键成果在于调整了遗忘曲线的形状,使其更为平缓。
2023 年 11 月 1 日
Anki 23.10 版本正式发布,这标志着首个内置 FSRS 算法的 Anki 官方版本的诞生。这意味着采用 FSRS 算法的用户数量预计将迅速增长。同时,这也显著提升了 FSRS 在开发者社群中的知名度,促使基于其他编程语言实现的 FSRS 算法库逐渐涌现,并有越来越多的其他间隔重复软件开始采用 FSRS。
Release 23.10 · ankitects/anki
2023 年 11 月 22 日 (源自 Anki 的数据集)
我非常感谢 Dae。依据 Anki 隐私政策中允许将复习数据用于研究的条款,他向我提供了来自 20,000 名用户牌组集合的原始数据,其中包含了高达 14 亿条的复习日志——这是间隔重复领域同类型数据集中规模最大的一个。
- 技术细节
我将全部 20,000 个文件转换为了.csv格式。利用这个庞大的数据集,我更新了 SRS 基准测试,并将其扩展到能够与其他更多模型进行比较的程度,旨在从中发掘改进 FSRS 算法的潜在方向。
[Feature Request] More accurate default parameters using Anki user's data and help from Dae · Issue #493 · open-spaced-repetition/fsrs4anki
Updating the benchmark with new data · Issue #14 · open-spaced-repetition/srs-benchmark
Feat/re-benchmark with 20k collections by L-M-Sherlock · Pull Request #16 · open-spaced-repetition/srs-benchmark
2023 年 12 月 26 日 (FSRS-4.5)
基于早前的多轮讨论和分析结果,社区最终接纳了使遗忘曲线更为平缓的构想,我随之发布了包含此项变更的 FSRS-4.5 版本。
Feat/update to FSRS-4.5 by L-M-Sherlock · Pull Request #568 · open-spaced-repetition/fsrs4anki
2024 年
2024 年 1 月 6 日
我对短期复习效果的研究揭示了一项关键发现:当用户在学习新卡片的当天对其进行多次复习时,历次评分会显著影响该卡片的初始稳定性。这一洞见随后促成了 FSRS-5 版本中利用当日复习数据来更新稳定性的处理方法。
2024 年 1 月 29 日
我将 FSRS-rs v0.1.0 版本发布到了 http://crates.io(Rust 语言的官方包注册中心)。
Release v0.1.0 · open-spaced-repetition/fsrs-rs
fsrs - crates.io: Rust Package Registry
2024 年 2 月 23 日
随着 AnkiDroid 2.17.0 版本的发布,FSRS 在所有主流平台——包括桌面端、iOS 端和 Android 端——均已全面实现原生支持。
2024 年 2 月 24 日 (FSRS-Anki-20k 数据集)
为了吸引更多研究人员参与,我公开发布了用于 FSRS 开发的、包含了 20,000 个 Anki 用户牌组集合的数据集,并将其命名为 FSRS-Anki-20k。
open-spaced-repetition/FSRS-Anki-20k · Datasets at Hugging Face
2024 年 3 月 1 日
为了使评估指标更加直观且更难以被人为「操纵」,我重新设计了「分箱均方根误差(RMSE(bins))」这一指标。
- 技术细节
正如我先前所提及,校准图容易受到人为操纵,因此我们主要采用对数损失作为核心的评估指标。然而,对数损失本身不够直观。有鉴于此,我基于一种难以被人为「操纵」且易于解读的新型分箱方法,对 RMSE(bins) 进行了重新设计。
Feat/RMSE based on R-Matrix by L-M-Sherlock · Pull Request #87 · open-spaced-repetition/fsrs-optimizer
The Metric · open-spaced-repetition/fsrs4anki Wiki
2024 年 4 月 6 日
在投入数月时间研究短期记忆模型之后,我最终决定放弃。从尝试运用 FSRS 来预测短期记忆的过程中,我得到的关键启示是:短期记忆与长期记忆的运作机制之间存在着显著的差异。最终,我采取了一种简化的处理方法:利用短期复习的数据来优化关于长期记忆的预测。
- 技术细节
短期复习本身的结果数据并未被用于模型的优化过程。换句话说,我将短期复习的日志信息纳入了时间序列特征之中,但将它们从用于训练模型的标签数据中排除了出去。此外,由于并未构建专门的短期记忆模型,这些短期复习的具体时间间隔信息也被忽略了。这种简化的解决方案使得 FSRS 对于长期记忆保留率的预测误差略有降低,但这尚不足以支持进行一次重大的版本更新。
Feat/FSRS-5 by L-M-Sherlock · Pull Request #114 · open-spaced-repetition/fsrs-optimizer
2024 年 5 月 17 日
我将初始难度建模为初始评分的指数函数,此举略微提升了 FSRS 算法的准确性。
- 技术细节
在分析 FSRS 参数的分布时,我注意到对应于「简单」按钮的初始稳定性数值非常高。具体而言,「简单」与「良好」这两个按钮对应初始稳定性之间的差异,远大于「良好」与「困难」按钮对应初始稳定性之间的差异。同样地,「困难」与「重来」按钮对应初始稳定性之间的差距也呈现出类似的模式。这使我推测,初始难度本身可能也遵循着相似的规律。因此,我进行了一项实验,将初始难度建模为初始评分的指数函数。实验结果确实表明,FSRS 的预测误差略有降低。
Feat/FSRS-5 by L-M-Sherlock · Pull Request #114 · open-spaced-repetition/fsrs-optimizer
2024 年 6 月 13 日
我更新了模拟器,通过计算每日复习的平均次数和平均评分,来近似模拟短期复习的效果。
- 技术细节
要更新 FSRS 模拟器以使其能够反映 FSRS-5 版本中对短期复习效果的考量,这本身是一项挑战。现有的模拟器是按天为单位运作的,并且由于缺乏短期记忆模型,无法精细模拟同一天内多次复习的具体情况。我的解决方案是一种简化处理:我决定不再单独模拟每一次短期复习,而是将它们作为一个整体来代表。具体做法是,计算用户典型短期复习的平均次数和平均评分(此计算按学习步骤进行),然后将这个聚合的统计值视为模拟过程中的一个单一事件。这种方法有效地避免了对模拟器进行大规模改造的必要。为了进行获取这些平均数据所需的分析工作,我建立了一个专门的代码库:
open-spaced-repetition/Anki-button-usage: A preliminary analysis about the button usage in Anki dataset
Feat/FSRS-5 by L-M-Sherlock · Pull Request #114 · open-spaced-repetition/fsrs-optimizer
2024 年 7 月 10 日 (FSRS-5)
我发布了 FSRS 5 版本,该版本加入了短期复习效果的考量,并改进了初始难度的模型,从而将预测误差降低了约 4%。
- 技术细节
在完成了所有必要的相应更新和基准测试之后,我发布了 FSRS-5 版本。此版本考虑了短期复习所产生的影响,并包含了经过改进的初始难度计算方法,总共新增了两个参数。与 FSRS-4.5 版本相比,它将预测误差降低了大约 4%。在当时,我曾认为这将是 FSRS 的最终版本。这是因为,在此之后,我和社区成员又尝试了数十种其他的改进方法,但无一例外,所有这些尝试都被证明是无效的。
Feat/FSRS-5 by L-M-Sherlock · Pull Request #98 · open-spaced-repetition/srs-benchmark
Feat/FSRS-5 by L-M-Sherlock · Pull Request #114 · open-spaced-repetition/fsrs-optimizer
Feat/FSRS-5 by L-M-Sherlock · Pull Request #197 · open-spaced-repetition/fsrs-rs
2024 年 9 月 7 日 (FSRS Megathread)
随着关于 FSRS 的讨论日渐频繁,Anki Discord 服务器上创建了 FSRS 集中讨论帖(FSRS Megathread),为这些交流提供了一个集中的平台。此举吸引了更多的贡献者加入,并为改进 FSRS 催生了更多有益的想法。
https://discord.com/channels/368267295601983490/1282005522513530952
2024 年 10 月 11 日
一位贡献者重构了 Rust 版本的模拟器,将其运行速度提升了约 8 倍。
- 技术细节
最初,FSRS-rs 模拟器的实现与其 Python 版本非常相似。但两者之间存在一个关键差异:Python 版本利用了 Numpy 库来进行高效的并行处理,并且这种处理在每日的粒度上进行了优化,而 Rust 的实现中则缺少了这项优化。得益于一位社区成员的贡献,FSRS-rs 模拟器随后被重构为在卡片级别的粒度上运行。在重构过程中,我确保了这项变更与原先按天处理的方法相比,不会改变模拟的最终结果。这次重构最终使性能显著提升,模拟速度加快了将近 8 倍。
Make simulate iterate by card instead of by day. by Luc-Mcgrady · Pull Request #235 · open-spaced-repetition/fsrs-rs
2024 年 10 月 17 日
我对难度的更新机制引入了「阻尼」效应,使得难度值能够更缓慢地趋近其最大值。出乎意料的是,此举将预测误差降低了约 1%。
- 技术细节
一位 FSRS 用户观察到,他的许多卡片很快就达到了 10 这个最大难度值。这种情况显著削弱了难度指标区分不同卡片的能力,导致在卡片排序时提供的粒度过粗。因此,他建议在难度更新过程中加入阻尼机制,使得当难度(D)接近 10 时,更新的幅度相应减小。
我们社区成员进行的基准测试表明,这种方法出人意料地将预测误差降低了大约 1%,并且没有引入任何额外的参数。然而,在实现此方法的过程中,我遇到了一个问题:阻尼效应是双向的。这意味着当难度 D 接近 10 时,无论是难度的增加还是减少,其变化的幅度都会受到抑制。这可能会造成一种类似于「简易地狱」的局面,即难度值可能会卡在较高的水平。然而,当我尝试实现单向阻尼(即只减缓难度的增加,而不减缓其减少)时,评估指标的改善效果却消失了。
这促使我重新思考:或许所谓的「简易地狱」实际上并不像人们通常认为的那样是个严重的问题。大多数专门旨在消除它的尝试,似乎都会对评估指标产生负面影响。最终,尽管双向阻尼可能存在潜在的缺陷,但鉴于其在基准测试中的正面表现,我还是决定在 FSRS-5 版本中采纳并实现了这一方案。
Suggestion for Adjusting Difficulty Score to Use an Asymptote at 10 · Issue #697 · open-spaced-repetition/fsrs4anki
2024 年 11 月 5 日 (anki-revlogs-10k 数据集)
在 Dae 的帮助下,我们发布了一个全新的 Anki 数据集。该数据集包含 10,000 个用户牌组集合,并附带有笔记、牌组以及预设配置的 ID 信息,以便进行更为细致的分析。
- 技术细节
发布此数据集的动机源于我对 20k 数据集的分析,在分析过程中我注意到,部分用户的遗忘曲线并非单调递减。这些异常曲线看起来像是混合了不同学习材料和学习选项共同作用的结果。为了进一步探究这个问题,我需要了解不同的卡片具体属于哪个牌组,以及这些牌组是否采用了不同的预设配置。最终,我们在新的数据集中加入了笔记 ID、牌组 ID 和预设 ID。这使得研究诸如源自同一笔记的不同卡片之间的相互作用、针对不同牌组分别优化参数所产生的效果等问题成为可能。
open-spaced-repetition/anki-revlogs-10k · Datasets at Hugging Face
2024 年 11 月 10 日 (学习步骤统计功能)
由于短期记忆模型的开发进展缓慢,我考虑在 FSRS 助手插件中加入针对短期复习的统计分析功能。其目标在于帮助用户量化自身的短期记忆状况,并为他们提供可用于调整学习步骤的数据支持。
Feat/step stats by L-M-Sherlock · Pull Request #487 · open-spaced-repetition/fsrs4anki-helper
New Feature: Quantify Your Short-Term Memory in Detail. : r/Anki
Recommended (re)learning steps powered by FSRS Helper : r/Anki
2024 年 12 月 30 日 (FSRS-5 recency)
我向优化器中添加了「近期加权(recency weighting)」机制,即对 FSRS 在较新的、近期发生的复习上做出的错误预测施以更大的惩罚,而对在较早发生的复习上做出的错误预测则施以较小的惩罚。此举将预测误差降低了约 4.5%。
- 技术细节
由于在模型结构的精细调整上感到有些疲惫,我开始重新审视以往进行过的实验。我重新发现了一个早期的实验,在那个实验中我曾尝试过为不同的复习样本赋予不同的权重:fsrs4anki/archive/experiment/mini-batch_punish_pls.ipynb at main · open-spaced-repetition/fsrs4anki
这促使我重新思考,或许应该将注意力更多地放在优化过程本身——这有可能在不改变模型架构的前提下提升模型性能。SRS 基准测试中 TimeSeriesSplit(时间序列分割)的应用提醒了我,用户的记忆模式会随着时间的推移而演变(例如,由于学习了不同的材料或改变了学习习惯)。由此,我提出了一个假设:或许给予近期产生的数据更高的权重,能够提高模型对未来复习的预测准确性?通过与 Claude 的讨论,我了解到这种方法被称为「近期加权」。
于是,我在优化器中实现了这一方法并进行了基准测试。结果表明,该方法将预测误差进一步降低了 3%:https://discord.com/channels/368267295601983490/1282005522513530952/1318519440647655445
采纳社区成员的建议后,我接着测试了多种不同的加权函数,最终成功将预测误差降低了约 4.5%。随后,我在 FSRS-rs 版本中也实现了这一机制。
Feat/support recency weighting by L-M-Sherlock · Pull Request #260 · open-spaced-repetition/fsrs-rs
2025 年
FSRS-6 即将问世,敬请期待。
英文版:The History of FSRS for Anki