From 0c0510b192aa3fa7809e1178ecfd2a877df8557f Mon Sep 17 00:00:00 2001
From: Brian Wo <45139213+brainwo@users.noreply.github.com>
Date: Fri, 8 Nov 2024 21:08:33 +0800
Subject: [PATCH 1/8] Init Jekyll
---
.gitignore | 7 +++
404.html | 25 ++++++++++
Gemfile | 35 ++++++++++++++
_config.yml | 49 ++++++++++++++++++--
_posts/2024-11-08-welcome-to-jekyll.markdown | 29 ++++++++++++
index.markdown | 6 +++
6 files changed, 148 insertions(+), 3 deletions(-)
create mode 100644 .gitignore
create mode 100644 404.html
create mode 100644 Gemfile
create mode 100644 _posts/2024-11-08-welcome-to-jekyll.markdown
create mode 100644 index.markdown
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4ce9212
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+_site
+.sass-cache
+.jekyll-cache
+.jekyll-metadata
+vendor
+
+Gemfile.lock
diff --git a/404.html b/404.html
new file mode 100644
index 0000000..086a5c9
--- /dev/null
+++ b/404.html
@@ -0,0 +1,25 @@
+---
+permalink: /404.html
+layout: default
+---
+
+
+
+
+
404
+
+
Page not found :(
+
The requested page could not be found.
+
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..6f8754a
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,35 @@
+source "https://rubygems.org"
+# Hello! This is where you manage which Jekyll version is used to run.
+# When you want to use a different version, change it below, save the
+# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
+#
+# bundle exec jekyll serve
+#
+# This will help ensure the proper Jekyll version is running.
+# Happy Jekylling!
+# gem "jekyll", "~> 4.3.4"
+# This is the default theme for new Jekyll sites. You may change this to anything you like.
+gem "minima", "~> 2.5"
+# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
+# uncomment the line below. To upgrade, run `bundle update github-pages`.
+gem "github-pages", group: :jekyll_plugins
+# If you have any plugins, put them here!
+group :jekyll_plugins do
+ gem "jekyll-feed", "~> 0.12"
+end
+
+# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
+# and associated library.
+platforms :mingw, :x64_mingw, :mswin, :jruby do
+ gem "tzinfo", ">= 1", "< 3"
+ gem "tzinfo-data"
+end
+
+# Performance-booster for watching directories on Windows
+gem "wdm", "~> 0.1", :platforms => [:mingw, :x64_mingw, :mswin]
+
+# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
+# do not have a Java counterpart.
+gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]
+
+gem "just-the-docs"
diff --git a/_config.yml b/_config.yml
index 3b2ddc7..085133f 100644
--- a/_config.yml
+++ b/_config.yml
@@ -1,5 +1,48 @@
+# Welcome to Jekyll!
+#
+# This config file is meant for settings that affect your whole blog, values
+# which you are expected to set up once and rarely edit after that. If you find
+# yourself editing this file very often, consider using Jekyll's data files
+# feature for the data you need to update frequently.
+#
+# For technical reasons, this file is *NOT* reloaded automatically when you use
+# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
+#
+# If you need help with YAML syntax, here are some quick references for you:
+# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
+# https://learnxinyminutes.com/docs/yaml/
+#
+# Site settings
+# These are used to personalize your new site. If you look in the HTML files,
+# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
+# You can create any custom variable you would like, and they will be accessible
+# in the templates via {{ site.myvariable }}.
+
title: Expertium's Blog
description: Spaced repetition stuff
-site_name: ""
-site_description: ""
-remote_theme: pages-themes/cayman@v0.2.0
+baseurl: "" # the subpath of your site, e.g. /blog
+url: "" # the base hostname & protocol for your site, e.g. http://example.com
+
+# Build settings
+theme: just-the-docs
+plugins:
+ - jekyll-feed
+# Exclude from processing.
+# The following items will not be processed, by default.
+# Any item listed under the `exclude:` key here will be automatically added to
+# the internal "default list".
+#
+# Excluded items can be processed by explicitly listing the directories or
+# their entries' file path in the `include:` list.
+#
+# exclude:
+# - .sass-cache/
+# - .jekyll-cache/
+# - gemfiles/
+# - Gemfile
+# - Gemfile.lock
+# - node_modules/
+# - vendor/bundle/
+# - vendor/cache/
+# - vendor/gems/
+# - vendor/ruby/
diff --git a/_posts/2024-11-08-welcome-to-jekyll.markdown b/_posts/2024-11-08-welcome-to-jekyll.markdown
new file mode 100644
index 0000000..18232d0
--- /dev/null
+++ b/_posts/2024-11-08-welcome-to-jekyll.markdown
@@ -0,0 +1,29 @@
+---
+layout: post
+title: "Welcome to Jekyll!"
+date: 2024-11-08 20:59:08 +0800
+categories: jekyll update
+---
+You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated.
+
+Jekyll requires blog post files to be named according to the following format:
+
+`YEAR-MONTH-DAY-title.MARKUP`
+
+Where `YEAR` is a four-digit number, `MONTH` and `DAY` are both two-digit numbers, and `MARKUP` is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works.
+
+Jekyll also offers powerful support for code snippets:
+
+{% highlight ruby %}
+def print_hi(name)
+ puts "Hi, #{name}"
+end
+print_hi('Tom')
+#=> prints 'Hi, Tom' to STDOUT.
+{% endhighlight %}
+
+Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll’s GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekyll Talk][jekyll-talk].
+
+[jekyll-docs]: https://jekyllrb.com/docs/home
+[jekyll-gh]: https://github.com/jekyll/jekyll
+[jekyll-talk]: https://talk.jekyllrb.com/
diff --git a/index.markdown b/index.markdown
new file mode 100644
index 0000000..0671507
--- /dev/null
+++ b/index.markdown
@@ -0,0 +1,6 @@
+---
+# Feel free to add content and custom Front Matter to this file.
+# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults
+
+layout: home
+---
From d7c29d26cf962cf70a116712aed283f38d6dd24c Mon Sep 17 00:00:00 2001
From: Brian Wo <45139213+brainwo@users.noreply.github.com>
Date: Mon, 11 Nov 2024 00:47:34 +0800
Subject: [PATCH 2/8] Add comment footer
---
_config.yml | 16 ++++++++++++++++
_includes/footer_custom.html | 11 +++++++++++
2 files changed, 27 insertions(+)
create mode 100644 _includes/footer_custom.html
diff --git a/_config.yml b/_config.yml
index 085133f..edc70de 100644
--- a/_config.yml
+++ b/_config.yml
@@ -46,3 +46,19 @@ plugins:
# - vendor/cache/
# - vendor/gems/
# - vendor/ruby/
+#
+color_scheme: dark
+
+giscus:
+ repo: "brainwo/expertium.github.io"
+ repo-id: "R_kgDOMxNzpA"
+ category: "General"
+ category-id: "DIC_kwDOMxNzpM4CkJZZ"
+ mapping: "pathname"
+ reaction-enabled: "1"
+ theme: "dark"
+ crossorigin: "anonymous"
+
+last_edit_timestamp: true
+
+gh_edit_link: true
diff --git a/_includes/footer_custom.html b/_includes/footer_custom.html
new file mode 100644
index 0000000..e901332
--- /dev/null
+++ b/_includes/footer_custom.html
@@ -0,0 +1,11 @@
+
From 4b9d791ce4492181ad9ebad9296786cf1bd754c5 Mon Sep 17 00:00:00 2001
From: Brian Wo <45139213+brainwo@users.noreply.github.com>
Date: Mon, 11 Nov 2024 00:52:57 +0800
Subject: [PATCH 3/8] Create jekyll.yml
---
.github/workflows/jekyll.yml | 64 ++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
create mode 100644 .github/workflows/jekyll.yml
diff --git a/.github/workflows/jekyll.yml b/.github/workflows/jekyll.yml
new file mode 100644
index 0000000..e2d248a
--- /dev/null
+++ b/.github/workflows/jekyll.yml
@@ -0,0 +1,64 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+
+# Sample workflow for building and deploying a Jekyll site to GitHub Pages
+name: Deploy Jekyll site to Pages
+
+on:
+ # Runs on pushes targeting the default branch
+ push:
+ branches: ["jekyll-2"]
+
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
+# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ # Build job
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Setup Ruby
+ uses: ruby/setup-ruby@8575951200e472d5f2d95c625da0c7bec8217c42 # v1.161.0
+ with:
+ ruby-version: '3.1' # Not needed with a .ruby-version file
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
+ cache-version: 0 # Increment this number if you need to re-download cached gems
+ - name: Setup Pages
+ id: pages
+ uses: actions/configure-pages@v5
+ - name: Build with Jekyll
+ # Outputs to the './_site' directory by default
+ run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}"
+ env:
+ JEKYLL_ENV: production
+ - name: Upload artifact
+ # Automatically uploads an artifact from the './_site' directory by default
+ uses: actions/upload-pages-artifact@v3
+
+ # Deployment job
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
From ff6fbc8009b9b6b07343def9f2d16d178e7d0749 Mon Sep 17 00:00:00 2001
From: Brian Wo <45139213+brainwo@users.noreply.github.com>
Date: Mon, 11 Nov 2024 00:58:04 +0800
Subject: [PATCH 4/8] Update footer
---
_includes/footer_custom.html | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/_includes/footer_custom.html b/_includes/footer_custom.html
index e901332..505d422 100644
--- a/_includes/footer_custom.html
+++ b/_includes/footer_custom.html
@@ -1,11 +1,15 @@
From f469f53b822feff0f331754bd117e999f8315cce Mon Sep 17 00:00:00 2001
From: Brian Wo <45139213+brainwo@users.noreply.github.com>
Date: Mon, 11 Nov 2024 01:09:33 +0800
Subject: [PATCH 5/8] Add index.md
---
_includes/footer_custom.html | 6 +++---
index.markdown | 6 ------
index.md | 15 +++++++++++++++
3 files changed, 18 insertions(+), 9 deletions(-)
delete mode 100644 index.markdown
create mode 100644 index.md
diff --git a/_includes/footer_custom.html b/_includes/footer_custom.html
index 505d422..56c60af 100644
--- a/_includes/footer_custom.html
+++ b/_includes/footer_custom.html
@@ -1,8 +1,8 @@
I rank this as relatively important simply because you won't find this information anywhere else.
+7. [Abridged history of spaced repetition](/History.md).
+8. [Let's get learning steps wrong!](/Learning_Steps.md) It's much easier than you think.
+9. [Should you lower your maximum interval?](/Max_Interval.md)
+10. [Mass adoption and the perfect UI](/Perfect_UI.md). Can FSRS be easy to use? Yes. But first, we'll need to change ~~some~~ a lot of things.
+
+A list of all implementations of FSRS in different programming languages, as well as apps that use FSRS (it's not just Anki!): [https://github.com/open-spaced-repetition/awesome-fsrs.](https://github.com/open-spaced-repetition/awesome-fsrs)
+
+Nothing that floats your boat? [Take a look at these articles and blogs then](/Resources_Dump.md).
From 7e66da6a9e184a51c558ec49198bd932725ebb85 Mon Sep 17 00:00:00 2001
From: Brian Wo <45139213+brainwo@users.noreply.github.com>
Date: Fri, 29 Nov 2024 04:59:40 +0800
Subject: [PATCH 6/8] Initial Mathjax support
---
Algorithm.md | 18 ++++++++++++------
_config.yml | 2 ++
_includes/head_custom.html | 6 ++++++
_includes/mathjax.html | 9 +++++++++
_layouts/mathjax.html | 12 ++++++++++++
assets/js/mathjax-script-type.js | 0
6 files changed, 41 insertions(+), 6 deletions(-)
create mode 100644 _includes/head_custom.html
create mode 100644 _includes/mathjax.html
create mode 100644 _layouts/mathjax.html
create mode 100644 assets/js/mathjax-script-type.js
diff --git a/Algorithm.md b/Algorithm.md
index 72d0537..3ee22d5 100644
--- a/Algorithm.md
+++ b/Algorithm.md
@@ -15,7 +15,11 @@ In this article, I'll explain how FSRS-4.5 works. The differences between FSRS-4
Let's start with the forgetting curve. In FSRS v3, an exponential function was used. In FSRS v4, the exponential function was replaced by a power function, which provided a better fit to the data. Then, in FSRS-4.5, it was replaced by a different power function which provided an even better fit. It is used in FSRS-5 as well.
-
+$$\LARGE R = 0.9^{\frac{t}{s}}$$
+
+$$\LARGE R = ( 1 + {\frac{t}{9S}})^{-1}$$
+
+$$\LARGE R = ( 1 + {\frac{19}{81}} \cdot {\frac{t}{S}})^{-0.5}$$
The main difference between them is how fast R declines when t>>S. Note that when t=S, R=90% for all three functions. This has to hold true because in FSRS, memory stability is defined as the amount of time required for R to decrease from 100% to 90%. You can play around with them here: [https://www.desmos.com/calculator/au54ecrpiz](https://www.desmos.com/calculator/au54ecrpiz).
@@ -38,27 +42,29 @@ Now let's take a look at the main formula of FSRS.

+$$\LARGE S'(D,S,R,G) = S \cdot (1 + w_{15} \cdot w_{16} \cdot c^{w_8}) \cdot (11 - D) \cdot S^{-w_9} \cdot (e^{w_{10} \cdot (1 - R)} - 1)$$
+
Here G is grade, it affects w15 and w16. R refers to retrievability at the time of the review.
Let's simplify this formula as much as possible.
-
+$$\LARGE S'(D,S,R) = S \cdot SInc$$
The new value of memory stability is equal to the previous value multiplied by some factor, which we will call SInc. SInc>=1, in other words, **memory stability cannot decrease if the review was successful**. Easy, Good and Hard all count as "success", Again counts as a memory "lapse". That's why you shouldn't use Hard as a failing grade, only as a passing grade.
SInc is equal to one plus the product of functions of three components of memory (I'll remove the part that depends on the grade for now).
-
+$$\LARGE SInc = 1 + f(D) \cdot f(S) \cdot f(R)$$
Now let's "unfold" each of them, starting with *f(D)*.
-
+$$\LARGE SInc = 1 + (11 - D) \cdot f(S) \cdot f(R)$$
**Important takeaway number two: the larger the value of D, the smaller the SInc value. This means that the increase in memory stability for difficult material is smaller than for easy material.**
Next, let's unfold *f(S)*.
-
+$$\LARGE SInc = 1 + (11 - D) \cdot S^{-w_9} \cdot f(R)$$
**Important takeaway number three: the larger the value of S, the smaller the SInc value. This means that the higher the stability of the memory, the harder it becomes to make the memory even more stable. Memory stability tends to saturate.**
@@ -66,7 +72,7 @@ This will likely surprise a lot of people, but the data supports it.
Finally, let's unfold *f(R)*.
-
+$$\LARGE SInc = 1 + (11 - D) \cdot S^{-w_9} \cdot (e^{w_{10} \cdot (1 - R)}- 1 )$$
**Important takeaway number four: the smaller the value of R, the larger the SInc value. This means that the best time to review your material is when you almost forgot it (provided that you succeeded in recalling it).**
diff --git a/_config.yml b/_config.yml
index edc70de..23af793 100644
--- a/_config.yml
+++ b/_config.yml
@@ -62,3 +62,5 @@ giscus:
last_edit_timestamp: true
gh_edit_link: true
+
+math: mathjax
diff --git a/_includes/head_custom.html b/_includes/head_custom.html
new file mode 100644
index 0000000..accc1f5
--- /dev/null
+++ b/_includes/head_custom.html
@@ -0,0 +1,6 @@
+{% assign math = page.math | default: layout.math | default: site.math %}
+
+{% case math %}
+ {% when "mathjax" %}
+ {% include mathjax.html %}
+{% endcase %}
diff --git a/_includes/mathjax.html b/_includes/mathjax.html
new file mode 100644
index 0000000..90c6db3
--- /dev/null
+++ b/_includes/mathjax.html
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/_layouts/mathjax.html b/_layouts/mathjax.html
new file mode 100644
index 0000000..a0c6c17
--- /dev/null
+++ b/_layouts/mathjax.html
@@ -0,0 +1,12 @@
+---
+layout: default
+math: mathjax
+---
+
+ \(
+
+ \)
+
+
+{{ content }}
diff --git a/assets/js/mathjax-script-type.js b/assets/js/mathjax-script-type.js
new file mode 100644
index 0000000..e69de29
From cde2d47184cbc948c928aee89dc6071550f8633c Mon Sep 17 00:00:00 2001
From: Brian Wo <45139213+brainwo@users.noreply.github.com>
Date: Sat, 22 Feb 2025 21:32:35 +0800
Subject: [PATCH 7/8] Update Ruby version
---
.github/workflows/jekyll.yml | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/jekyll.yml b/.github/workflows/jekyll.yml
index e2d248a..169c782 100644
--- a/.github/workflows/jekyll.yml
+++ b/.github/workflows/jekyll.yml
@@ -34,16 +34,15 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Ruby
- uses: ruby/setup-ruby@8575951200e472d5f2d95c625da0c7bec8217c42 # v1.161.0
+ uses: ruby/setup-ruby@v1
with:
- ruby-version: '3.1' # Not needed with a .ruby-version file
+ ruby-version: "3.3"
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
cache-version: 0 # Increment this number if you need to re-download cached gems
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
- name: Build with Jekyll
- # Outputs to the './_site' directory by default
run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}"
env:
JEKYLL_ENV: production
From 5290eb8766f751c5d637fa14f5e11c85c25d4678 Mon Sep 17 00:00:00 2001
From: Brian Wo <45139213+brainwo@users.noreply.github.com>
Date: Mon, 24 Feb 2025 23:52:50 +0800
Subject: [PATCH 8/8] Move posts around
---
Resources_Dump.md | 26 +++----
_config.yml | 18 ++---
.../2024-07-28-Benchmark.md | 76 ++++++++++---------
History.md => _posts/2024-08-02-History.md | 9 ++-
.../2024-08-04-Algorithm.md | 40 +++++-----
Buttons.md => _posts/2024-08-17-Buttons.md | 19 +++--
.../2024-08-17-Retention.md | 9 ++-
.../2024-08-20-Perfect_UI.md | 19 +++--
Addons.md => _posts/2024-09-04-Addons.md | 14 +++-
.../2024-10-25-Avoid_Pattern_Matching.md | 21 ++---
.../2024-10-25-Learning_Steps.md | 33 ++++----
.../2024-10-25-Max_Interval.md | 9 ++-
_posts/2024-11-08-welcome-to-jekyll.markdown | 29 -------
.../2024-11-19-RedditBot.md | 37 +++++----
.../2024-11-29-ScientistsAge.md | 15 +++-
.../2025-01-14-20reasons.md | 17 +++--
blog.md | 17 +++++
index.md | 27 +++++--
18 files changed, 259 insertions(+), 176 deletions(-)
rename Benchmark.md => _posts/2024-07-28-Benchmark.md (92%)
rename History.md => _posts/2024-08-02-History.md (96%)
rename Algorithm.md => _posts/2024-08-04-Algorithm.md (92%)
rename Buttons.md => _posts/2024-08-17-Buttons.md (87%)
rename Retention.md => _posts/2024-08-17-Retention.md (97%)
rename Perfect_UI.md => _posts/2024-08-20-Perfect_UI.md (70%)
rename Addons.md => _posts/2024-09-04-Addons.md (95%)
rename Avoid_Pattern_Matching.md => _posts/2024-10-25-Avoid_Pattern_Matching.md (95%)
rename Learning_Steps.md => _posts/2024-10-25-Learning_Steps.md (63%)
rename Max_Interval.md => _posts/2024-10-25-Max_Interval.md (94%)
delete mode 100644 _posts/2024-11-08-welcome-to-jekyll.markdown
rename RedditBot.md => _posts/2024-11-19-RedditBot.md (97%)
rename ScientistsAge.md => _posts/2024-11-29-ScientistsAge.md (94%)
rename 20reasons.md => _posts/2025-01-14-20reasons.md (90%)
create mode 100644 blog.md
diff --git a/Resources_Dump.md b/Resources_Dump.md
index f2f6e1d..528a7e3 100644
--- a/Resources_Dump.md
+++ b/Resources_Dump.md
@@ -1,29 +1,29 @@
# Resources Dump
-1. [https://augmentingcognition.com/ltm.html](https://augmentingcognition.com/ltm.html)
+1. [https://augmentingcognition.com/ltm.html](https://augmentingcognition.com/ltm.html)
-2. [https://gwern.net/spaced-repetition](https://gwern.net/spaced-repetition) (this one is more than a decade old)
+2. [https://gwern.net/spaced-repetition](https://gwern.net/spaced-repetition) (this one is more than a decade old)
-3. 20 rules for making good cards: [https://super-memory.com/articles/20rules.htm](https://super-memory.com/articles/20rules.htm)
+3. 20 rules for making good cards: [https://super-memory.com/articles/20rules.htm](https://super-memory.com/articles/20rules.htm)
-4. [https://cademcniven.com/](https://cademcniven.com/)
+4. [https://cademcniven.com/](https://cademcniven.com/)
-5. [https://supermemo.guru/wiki/SuperMemo_Guru](https://supermemo.guru/wiki/SuperMemo_Guru). This one has a metric crapton of articles: about spaced repetition, neuroscience, education, etc. Some are great, some...not so much.
+5. [https://supermemo.guru/wiki/SuperMemo_Guru](https://supermemo.guru/wiki/SuperMemo_Guru). This one has a metric crapton of articles: about spaced repetition, neuroscience, education, etc. Some are great, some...not so much.
-6. A great article about spaced repetition algorithms by Jarrett Ye, the creator of FSRS: [https://github.com/open-spaced-repetition/fsrs4anki/wiki/Spaced-Repetition-Algorithm:-A-Three%E2%80%90Day-Journey-from-Novice-to-Expert](https://github.com/open-spaced-repetition/fsrs4anki/wiki/Spaced-Repetition-Algorithm:-A-Three%E2%80%90Day-Journey-from-Novice-to-Expert)
+6. A great article about spaced repetition algorithms by Jarrett Ye, the creator of FSRS: [https://github.com/open-spaced-repetition/fsrs4anki/wiki/Spaced-Repetition-Algorithm:-A-Three%E2%80%90Day-Journey-from-Novice-to-Expert](https://github.com/open-spaced-repetition/fsrs4anki/wiki/Spaced-Repetition-Algorithm:-A-Three%E2%80%90Day-Journey-from-Novice-to-Expert)
-7. [https://andymatuschak.org/](https://andymatuschak.org/)
+7. [https://andymatuschak.org/](https://andymatuschak.org/)
-8. [https://eshapard.github.io/](https://eshapard.github.io/) (inactive since 2022)
+8. [https://eshapard.github.io/](https://eshapard.github.io/) (inactive since 2022)
-9. [https://controlaltbackspace.org/](https://controlaltbackspace.org/)
+9. [https://controlaltbackspace.org/](https://controlaltbackspace.org/)
-10. Learning techniques ranked based on effectiveness: [http://web.archive.org/web/20190711014620/http://tlcp.depaultla.org/wp-content/uploads/sites/2/2015/05/Dunlosky-et-al-2013-What-Works-What-Doesnt.pdf](http://web.archive.org/web/20190711014620/http://tlcp.depaultla.org/wp-content/uploads/sites/2/2015/05/Dunlosky-et-al-2013-What-Works-What-Doesnt.pdf)
+10. Learning techniques ranked based on effectiveness: [http://web.archive.org/web/20190711014620/http://tlcp.depaultla.org/wp-content/uploads/sites/2/2015/05/Dunlosky-et-al-2013-What-Works-What-Doesnt.pdf](http://web.archive.org/web/20190711014620/http://tlcp.depaultla.org/wp-content/uploads/sites/2/2015/05/Dunlosky-et-al-2013-What-Works-What-Doesnt.pdf)
-11. An interactive comic that explains spaced repetition in a beginner-friendly way: [https://ncase.me/remember/](https://ncase.me/remember/)
+11. An interactive comic that explains spaced repetition in a beginner-friendly way: [https://ncase.me/remember/](https://ncase.me/remember/)
-12. Spaced repetition for hierarchical knowledge, such as math and physics: [https://www.justinmath.com/individualized-spaced-repetition-in-hierarchical-knowledge-structures/](https://www.justinmath.com/individualized-spaced-repetition-in-hierarchical-knowledge-structures/)
+12. Spaced repetition for hierarchical knowledge, such as math and physics: [https://www.justinmath.com/individualized-spaced-repetition-in-hierarchical-knowledge-structures/](https://www.justinmath.com/individualized-spaced-repetition-in-hierarchical-knowledge-structures/)
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/_config.yml b/_config.yml
index 23af793..b88417f 100644
--- a/_config.yml
+++ b/_config.yml
@@ -21,7 +21,7 @@
title: Expertium's Blog
description: Spaced repetition stuff
baseurl: "" # the subpath of your site, e.g. /blog
-url: "" # the base hostname & protocol for your site, e.g. http://example.com
+url: "https://expertium.github.io/" # the base hostname & protocol for your site, e.g. http://example.com
# Build settings
theme: just-the-docs
@@ -50,14 +50,14 @@ plugins:
color_scheme: dark
giscus:
- repo: "brainwo/expertium.github.io"
- repo-id: "R_kgDOMxNzpA"
- category: "General"
- category-id: "DIC_kwDOMxNzpM4CkJZZ"
- mapping: "pathname"
- reaction-enabled: "1"
- theme: "dark"
- crossorigin: "anonymous"
+ repo: "brainwo/expertium.github.io"
+ repo-id: "R_kgDOMxNzpA"
+ category: "General"
+ category-id: "DIC_kwDOMxNzpM4CkJZZ"
+ mapping: "pathname"
+ reaction-enabled: "1"
+ theme: "dark"
+ crossorigin: "anonymous"
last_edit_timestamp: true
diff --git a/Benchmark.md b/_posts/2024-07-28-Benchmark.md
similarity index 92%
rename from Benchmark.md
rename to _posts/2024-07-28-Benchmark.md
index 5e0aff4..7b0bbd8 100644
--- a/Benchmark.md
+++ b/_posts/2024-07-28-Benchmark.md
@@ -1,6 +1,14 @@
+---
+layout: post
+title: "Benchmark of Spaced Repetition Algorithms"
+date: 2024-7-28 20:53:55 +0300
+categories: fsrs
+---
+
# Benchmark of Spaced Repetition Algorithms
# Table of contents
+
- [Intro](#intro)
- [Metrics](#metrics)
- [Algorithms](#algorithms)
@@ -13,23 +21,25 @@
- [References](#references)
## Intro
+
This is an extended version of my Reddit post. This article should take approximately 32–37 minutes to read, the Reddit post should take around 11–13 minutes. I tried to make this article suitable for both tech-savvy and casual readers, so I may have over-explained some things.
Side note: when I say "we", I'm referring to myself and [Jarrett Ye](https://github.com/L-M-Sherlock), the creator of [FSRS](https://github.com/open-spaced-repetition/fsrs4anki/wiki/ABC-of-FSRS).
-
## Metrics
+
First of all, every spaced repetition algorithm must be able to predict the **probability of recalling** a card at a given point in time, given the card's review history. Let's call that **R**. All three metrics that we use are related to the probability of recall.
If an algorithm doesn't calculate probabilities and just outputs an interval, it's still possible to convert that interval into a probability under certain assumptions. It's better than nothing, since it allows us to perform at least some sort of comparison. That's what we did for SM-2, the only algorithm in the entire benchmark that wasn't originally designed to predict probabilities. We decided not to include [Memrise](https://memrise.zendesk.com/hc/en-us/articles/360015889057-How-does-the-spaced-repetition-system-work) because we are unsure if the assumptions required to convert its intervals to probabilities hold. Well, it wouldn't perform great anyway, it's about as inflexible as possible.
Once we have an algorithm that predicts R, we can run it on some users' review histories to see how much predicted R deviates from measured R. If we do that using hundreds of millions of reviews, we will get a very good idea of which algorithm performs better on average. **RMSE**, or root mean square error, can be interpreted as "the average difference between predicted and measured probability of recall (R)". RMSE is a measure of **calibration**.
-Loosely speaking, if an algorithm predicts an X% chance of something happening, it should happen X% of the time. For example, if a weatherman says, "There is a 90% chance of rain today," it should rain on 90% of days when he says that. That's good calibration. If it rained only on 40% of those days, it means that the weatherman (or, well, his forecasting system) is poorly calibrated - his probabilities don't match observed frequencies. RMSE measures how well-calibrated an algorithm is.
+Loosely speaking, if an algorithm predicts an X% chance of something happening, it should happen X% of the time. For example, if a weatherman says, "There is a 90% chance of rain today," it should rain on 90% of days when he says that. That's good calibration. If it rained only on 40% of those days, it means that the weatherman (or, well, his forecasting system) is poorly calibrated - his probabilities don't match observed frequencies. RMSE measures how well-calibrated an algorithm is.
The calculation of RMSE has been reworked in the past to prevent cheating, aka algorithms achieving good numbers on paper without getting better at predicting R in reality. If you want to know the nitty-gritty mathematical details, you can read [this article by Jarrett and me](https://github.com/open-spaced-repetition/fsrs4anki/wiki/The-Metric). The new method is our own invention, and you won't find it in any academic paper. Anki >=24.04 uses the new method when "Evaluate" is used.
Here's what you need to know about RMSE:
-1. RMSE measures how close the predicted R is to reality. It puts reviews into bins and measures the difference between *average* actual retention and *average* predicted R within each bin.
+
+1. RMSE measures how close the predicted R is to reality. It puts reviews into bins and measures the difference between _average_ actual retention and _average_ predicted R within each bin.
2. RMSE ranges from 0 to 1, lower is better.
3. We calculate it by binning reviews in a way that is specific to spaced repetition, you won't find this in the literature. This isn't very nice for making the benchmark results accepted by other researchers, but we have other metrics for that.
4. It's not what the optimizer in Anki is minimizing. Log loss is what the FSRS optimizer is internally using for optimization, not RMSE. We can't use RMSE for that.
@@ -38,14 +48,16 @@ Next is log loss. It is calculated using the following formula:

-where *y* is a binary label (either 0 or 1), and *R* is the probability of recall (a real number between 0 and 1) predicted by some algorithm.
+where _y_ is a binary label (either 0 or 1), and _R_ is the probability of recall (a real number between 0 and 1) predicted by some algorithm.
Here's what you need to know about log loss:
+
1. Log loss measures how close the predicted probability of recall (R) is to reality, just like RMSE. However, unlike RMSE, it doesn't rely on binning reviews. RMSE is based on the difference between averages, whereas log loss is based on the difference between individual predictions and individual review outcomes.
2. Log loss ranges from 0 to infinity, lower is better.
3. Unlike RMSE, log loss never reaches 0, unless the algorithm only outputs ones and zeros. If an algorithm outputs numbers between 0 and 1, the minimum possible value of log loss that it can achieve is >0. This makes log loss less intuitive than RMSE. You might intuitively expect that if the distribution of predicted probabilities exactly matches the distribution of true probabilities, the loss would be zero, but no.
Next is AUC (Area Under the Curve). Unlike the previous two metrics, AUC is not a measure of **calibration** but of **discrimination**. Here's what you need to know about AUC:
+
1. AUC measures how well an algorithm can tell classes apart; in our case, classes are "recalled" and "forgotten." You can think of AUC as a measure of how well the algorithm can draw a boundary between two classes, such that all members of class 1 are on one side of the boundary and all members of class 2 are on the other side.
2. AUC score ranges from 0 to 1, but in practice it's almost always greater than 0.5. An AUC score less than 0.5 indicates that the algorithm is performing worse than random. Higher is better.
@@ -57,12 +69,10 @@ Below is a diagram that explains AUC.
For a more in-depth explanation of AUC, you can read [this article](https://www.geeksforgeeks.org/auc-roc-curve/). The important part is how to interpret it: in the context of spaced repetition, the AUC score can be interpreted as "a probability that the algorithm will assign a higher probability of recall to a recalled card than to a forgotten card". For example, AUC=0.7 means that there is a 70% chance that a recalled card has a higher probability of recall predicted by the algorithm than a forgotten card.
-
Here's a table comparing different metrics.

-
## Algorithms
Most of the algorithms are based on the Stability, Retrievability (alternatively Half-Life, Probability) model of memory, or it's extension, Difficulty, Stability, Retrievability (alternatively Difficulty, Half-Life, Probability). I will refer to the former as the SR model and to the latter as the DSR model.
@@ -89,7 +99,7 @@ Below is a diagram that should give you a better understanding of FSRS. If you w

-"Grade" refers to Again/Hard/Good/Easy. To calculate the loss, the grade is converted into a binary value: 0 if it's Again, 1 otherwise. This doesn't mean that FSRS *itself* treats grades as binary, of course it can tell the difference between Hard, Good and Easy.
+"Grade" refers to Again/Hard/Good/Easy. To calculate the loss, the grade is converted into a binary value: 0 if it's Again, 1 otherwise. This doesn't mean that FSRS _itself_ treats grades as binary, of course it can tell the difference between Hard, Good and Easy.
In order to calculate the probability of recall, FSRS requires the length of the previous interval and its own previous state, which is represented using three numbers: Difficulty, memory Stability, and Retrievability (DSR). Notice that horizontal arrows always point to the right, showing that past states can affect future states, but future states cannot affect past states.
@@ -109,13 +119,13 @@ GRU is also a recurrent algorithm, just like FSRS, even if the mathematical form
12. LSTM. This is also a recurrent neural network, but a more complex one than GRU. I won't make a diagram for it. This implementation calculates three different values of memory stability for three different forgetting curve and then combines them into one via weighted averaging (with learnable weights). It uses same-day reviews and, unlike most algorithms here, it uses fractional interval lengths. It also uses the answer time - how long the user spent on a card - as an input feature.
-13. [RWKV-7](https://github.com/BlinkDL/RWKV-LM) (pronounced "rʌkuv" in IPA, like "tho**rou**gh **k**ettle m**ove**"), a novel architecture that aims to combine the best of Transformers and recurrent neural nets. It uses all available information as input: fractional interval lengths, grades, answer time, deck ID, preset ID, and information about reviews of siblings (related cards). The way it's optimized is very different from the rest of the algorithms. All other algorithms are optimized on a per-user basis, meaning that the parameters are personalized for each user, and the algorithm is evaluated on the review history of *the same user* that it's trained on, just on a different, later part of that history. RWKV-7 is instead optimized on 5 thousand users and evaluated on the *other* 5 thousand users. This is then repeated twice to get full coverage of the entire dataset. This is explained in more detail in the [Superiority](#superiority) section. Huge thanks to [1DWalker](https://github.com/1DWalker) on Github for implementing it!
+13. [RWKV-7](https://github.com/BlinkDL/RWKV-LM) (pronounced "rʌkuv" in IPA, like "tho**rou**gh **k**ettle m**ove**"), a novel architecture that aims to combine the best of Transformers and recurrent neural nets. It uses all available information as input: fractional interval lengths, grades, answer time, deck ID, preset ID, and information about reviews of siblings (related cards). The way it's optimized is very different from the rest of the algorithms. All other algorithms are optimized on a per-user basis, meaning that the parameters are personalized for each user, and the algorithm is evaluated on the review history of _the same user_ that it's trained on, just on a different, later part of that history. RWKV-7 is instead optimized on 5 thousand users and evaluated on the _other_ 5 thousand users. This is then repeated twice to get full coverage of the entire dataset. This is explained in more detail in the [Superiority](#superiority) section. Huge thanks to [1DWalker](https://github.com/1DWalker) on Github for implementing it!
### DASH family
These algorithms are based on a different model, not SR or DSR.
-14. [DASH](https://scholar.colorado.edu/concern/graduate_thesis_or_dissertations/zp38wc97m), Difficulty, Ability and Study History. This is an actual *bona fide* model of human memory based on neuroscience. Well, kind of. The issue with it is that the forgetting curve looks like a step function.
+14. [DASH](https://scholar.colorado.edu/concern/graduate_thesis_or_dissertations/zp38wc97m), Difficulty, Ability and Study History. This is an actual _bona fide_ model of human memory based on neuroscience. Well, kind of. The issue with it is that the forgetting curve looks like a step function.
15. DASH[MCM]. A hybrid algorithm, it addresses some of the issues with DASH's forgetting curve.
@@ -131,7 +141,7 @@ DASH, DASH[MCM] and DASH[ACT-R] don't have state variables that are carried on b
### Other algorithms
-17. [ACT-R](http://act-r.psy.cmu.edu/wordpress/wp-content/themes/ACT-R/workshops/2003/proceedings/46.pdf), Adaptive Control of Thought - Rational (I've also seen "Character" instead of "Control" in some papers). It's based on a model of human memory that makes one very strange assumption: whether you have successfully recalled your material or not doesn't affect the magnitude of the spacing effect, only the interval length matters. Simply put, this algorithm doesn't differentiate between Again/Hard/Good/Easy. Notice that in the diagram below, grades are only used for calculating the loss function, but not used by the algorithm itself - no arrows come from "Grade".
+17. [ACT-R](http://act-r.psy.cmu.edu/wordpress/wp-content/themes/ACT-R/workshops/2003/proceedings/46.pdf), Adaptive Control of Thought - Rational (I've also seen "Character" instead of "Control" in some papers). It's based on a model of human memory that makes one very strange assumption: whether you have successfully recalled your material or not doesn't affect the magnitude of the spacing effect, only the interval length matters. Simply put, this algorithm doesn't differentiate between Again/Hard/Good/Easy. Notice that in the diagram below, grades are only used for calculating the loss function, but not used by the algorithm itself - no arrows come from "Grade".

@@ -186,7 +196,6 @@ It should be noted that some algorithms, such as SM-2, which were not designed t
Regarding invertibility: for some algorithms, such as DASH and GRU-P, probabilities can be calculated easily, but due to the quirks of their forgetting curves, it is not possible to determine interval lengths that correspond to specific probabilities via an exact formula. Though it can still be done approximately. Nonetheless, invertibility is desirable for practical purposes of scheduling.
-
## Dataset
The dataset used in the benchmark is ~~FSRS Anki 20k~~[Anki revlogs 10k](https://huggingface.co/datasets/open-spaced-repetition/anki-revlogs-10k), the largest in the world. It contains data about ~727 million flashcard reviews from 10 thousand users, which is approximately 3 times more reviews than in the [Maimemo dataset](https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/VAGUL0) and approximately 56 times more reviews than in [the Duolingo dataset](https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/N8XJME).
@@ -195,7 +204,6 @@ The data itself is also different. In Anki, each user makes their own flashcards
This benchmark is based on 9,999 collections and 349,923,850 reviews. Same-day reviews are excluded except when optimizing FSRS-5 and algorithms that have "-short" at the end of their names, which use same-day reviews for training but not for evaluation. Additionally, some reviews are filtered out, such as when the user manually changed the due date (which would count as a review) or when the user used what's called a "filtered deck" if "Reschedule cards based on my answers in this deck" was disabled. Finally, an outlier filter is applied. Because of all of that, the real number of reviews used for evaluation is around 350 million, much smaller than the 727 billion figure mentioned above.
-
## Results
### Log loss, RMSE and AUC
@@ -208,7 +216,7 @@ The tables also show the number of optimizable parameters of each algorithm. The

Lower is better. Black caps are 99% confidence intervals.
-Don't focus too much on absolute values, they depend on a lot of things: how we calculate RMSE (which involves somewhat arbitrary binning), whether the averages are weighted by the number of reviews or not, and how the outlier filter works. Instead, focus on the ranking - which algorithm is the best, which one is the second best, which one is the third best, etc.
+Don't focus too much on absolute values, they depend on a lot of things: how we calculate RMSE (which involves somewhat arbitrary binning), whether the averages are weighted by the number of reviews or not, and how the outlier filter works. Instead, focus on the ranking - which algorithm is the best, which one is the second best, which one is the third best, etc.
The bars corresponding to FSRS-5 and GRU-P (short-term) are colored differently to indicate that these algorithms have been trained on more reviews; all other algorithms were trained without using same-day reviews. However, the comparison is still fair because all algorithms are evaluated on the same data, even if the training data is different. Here's an analogy: one student did a lot of homework before the test, the other did less homework. After that, both students took the same test. Even though they did a different amount of homework, since the test is the same, it's still valid to compare the test scores of these two students.
@@ -227,10 +235,10 @@ Finally, let's look at AUC scores.

-Higher is better. Black caps are 99% confidence intervals.
+Higher is better. Black caps are 99% confidence intervals.
Now ranking is very different.
It's interesting that the AUC score of HLR is 0.631, much higher than 0.54, which is what Duolingo reported in their paper. Granted, 0.631 is not that impressive either. In fact, all spaced repetition algorithms have rather unimpressive AUC scores.
-Surprisingly, AVG has an AUC score slightly above 0.5. Since it always outputs a constant, it cannot differentiate between forgotten and recalled cards, so in theory, it should have an AUC score of *exactly* 0.5.
+Surprisingly, AVG has an AUC score slightly above 0.5. Since it always outputs a constant, it cannot differentiate between forgotten and recalled cards, so in theory, it should have an AUC score of _exactly_ 0.5.
Jarrett's implementation of Transformer doesn't perform well according to all 3 metrics, so if any neural network experts think, "I bet I can do better!" they are welcome.
Let's address GRU-P (doesn't matter whether we are talking about the -short version or not). As you can see, it outperforms all other algorithms by all three metrics. So you're probably wondering "If predicting R directly is better than predicting an intermediate value first, why not do that?". Here's what happens when you let an algorithm predict R directly.
@@ -238,7 +246,7 @@ Let's address GRU-P (doesn't matter whether we are talking about the -short vers

These are forgetting curves that GRU-P generated for different users. Only one of them makes sense.
-A curve that becomes flat (top left) not only makes no sense but is also unusable in practice, it could result in *infinitely* long intervals when used for scheduling.
+A curve that becomes flat (top left) not only makes no sense but is also unusable in practice, it could result in _infinitely_ long intervals when used for scheduling.
A curve with a maximum that is not at time=0 (bottom left) makes no sense either. A curve with a minimum (top right) implies that after some point in time, forgetting ends and some sort of anti-forgetting starts, which also makes no sense.
Only the bottom right is a proper forgetting curve. Well, minus the fact that it's wiggly. And minus the fact that it doesn't start at 100%.
So while GRU-P outperforms all other algorithms, it's not usable in practice as it could result in all kinds of strange behavior.
@@ -249,22 +257,22 @@ Notice that while GRU-P (short-term) outperforms GRU-P and while FSRS-5 outperfo
(work in progress)
-You may think that an algorithm that knows the exact value of the probability of recall (let's call such an algorithm "Oracle") would achieve a log loss of 0, an RMSE of 0%, and an AUC score of 1. But remember - forgetting is inherently random. It's possible - albeit unlikely - that a card with a 99% probability of recall will be forgotten, and a card with a 1% probability of recall will be recalled. Even after finding every single pattern in the data, there is still an inherent, irreducible amount of randomness.
+You may think that an algorithm that knows the exact value of the probability of recall (let's call such an algorithm "Oracle") would achieve a log loss of 0, an RMSE of 0%, and an AUC score of 1. But remember - forgetting is inherently random. It's possible - albeit unlikely - that a card with a 99% probability of recall will be forgotten, and a card with a 1% probability of recall will be recalled. Even after finding every single pattern in the data, there is still an inherent, irreducible amount of randomness.
Me and 1DWalker used two methods to estimate the lowest (highest in case of AUC) values of these three metrics that the Oracle would achieve. I will refer to them as "beta fit" and "scaling law".
The first method, beta fit, works like this:
-1) Use the most accurate algorithm available, in this case RWKV-7.
+1. Use the most accurate algorithm available, in this case RWKV-7.
-2) For each user predict the probability of recall for each review.
+2. For each user predict the probability of recall for each review.
-3) Do a correction to remove systematic errors.
+3. Do a correction to remove systematic errors.
-4) **Assume** that the shape of the distribution of predicted probabilities is close enough to the shape of the distribution of true underlying probabilities. More precisely, assume that alpha and beta of the
-[beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) of predicted probabilities are close enough to alpha and beta of the distribution of true probabilities.
+4. **Assume** that the shape of the distribution of predicted probabilities is close enough to the shape of the distribution of true underlying probabilities. More precisely, assume that alpha and beta of the
+ [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) of predicted probabilities are close enough to alpha and beta of the distribution of true probabilities.
-5) Run simulations to estimate how well an algorithm that knows the exact probability of recall - sampled from a beta distribution - performs.
+5. Run simulations to estimate how well an algorithm that knows the exact probability of recall - sampled from a beta distribution - performs.
This method works for log loss and AUC, but not for RMSE due to the binning method.
@@ -272,13 +280,13 @@ This method works for log loss and AUC, but not for RMSE due to the binning meth
The second method, scaling law, works like this:
-1) Use a neural network, in this case RWKV-7.
+1. Use a neural network, in this case RWKV-7.
-2) Train it with many different numbers of parameters. For example, from fifty thousand to fifty million. Record the values of the metrics.
+2. Train it with many different numbers of parameters. For example, from fifty thousand to fifty million. Record the values of the metrics.
-3) Do curve fitting using an equation of the form *L=a+b/(N^c)+d/(E^f)*, where *L* is the metric (log loss, RMSE, AUC), *N* is the number of trainable parameters of the neural network, *E* is the number of epochs that the neural network has been trained for; and *a*, *b*, *c*, *d* and *f* are curve fitting parameters.
+3. Do curve fitting using an equation of the form _L=a+b/(N^c)+d/(E^f)_, where _L_ is the metric (log loss, RMSE, AUC), _N_ is the number of trainable parameters of the neural network, _E_ is the number of epochs that the neural network has been trained for; and _a_, _b_, _c_, _d_ and _f_ are curve fitting parameters.
-Parameter *a* obtained this way is the irreducible amount of loss that would be left if one trained an infinitely large neural network for infinitely many epochs. This method works for all three metrics.
+Parameter _a_ obtained this way is the irreducible amount of loss that would be left if one trained an infinitely large neural network for infinitely many epochs. This method works for all three metrics.
### Superiority
@@ -316,7 +324,7 @@ If you want a more technical explanation, here:
This procedure is used for all algorithms. Thanks to this clever way of splitting data, no data is thrown away while at the same time the algorithm is trained on different data than it is evaluated on, so we get a realistic estimate of how it would perform on new, previously unseen data.
-By the way, this is not how "Evaluate" works in Anki. "Evaluate" uses a simplified procedure to avoid optimizing parameters every time the user wants to evaluate them - it just evaluates the specified parameters on the entire history, without optimizing them and without any splitting; training set=test set. "Evaluate" can only tell the user how well the parameters fit the *current* review history aka the training set. But the benchmark should evaluate the algorithm's ability to generalize beyond the training set data. Jarrett believes that it's fine that the benchmark and Anki don't use the same evaluation procedure.
+By the way, this is not how "Evaluate" works in Anki. "Evaluate" uses a simplified procedure to avoid optimizing parameters every time the user wants to evaluate them - it just evaluates the specified parameters on the entire history, without optimizing them and without any splitting; training set=test set. "Evaluate" can only tell the user how well the parameters fit the _current_ review history aka the training set. But the benchmark should evaluate the algorithm's ability to generalize beyond the training set data. Jarrett believes that it's fine that the benchmark and Anki don't use the same evaluation procedure.
I hope this diagram helps:
@@ -324,7 +332,6 @@ I hope this diagram helps:
A is not used for evaluation, E is not used for training.
-
## Discussion
Caveats:
@@ -341,13 +348,13 @@ Broadly speaking, machine learning algorithms are bound by the amount of computa
There are several ways to make FSRS more accurate, none of which are currently feasible:
-1. Consider the number of reviews done before a particular review and the time of day to estimate how fatigued the user was (perhaps some other factors could be taken into account when estimating fatigue as well). If someone is doing their first review at 4 PM, they are probably less fatigued than someone who is doing their 500th review at 4 AM, which affects retention. This is not possible with the way Anki currently works - FSRS cannot access datetime information - and would require major changes.
+1. Consider the number of reviews done before a particular review and the time of day to estimate how fatigued the user was (perhaps some other factors could be taken into account when estimating fatigue as well). If someone is doing their first review at 4 PM, they are probably less fatigued than someone who is doing their 500th review at 4 AM, which affects retention. This is not possible with the way Anki currently works - FSRS cannot access datetime information - and would require major changes.
2. Consider the content of the cards: text, sound, and images. It would require adding another machine learning algorithm (or even several algorithms) just for text/audio/image recognition, and we wouldn't be able to train it since Dae (the main Anki dev) can't give us a dataset that has all of the content of cards. That is against Anki's privacy policy, only scheduling data is available publicly.
-3. Consider the interference from sibling cards. This could also be extended to "conceptual siblings" - cards that don't come from the same note, but test you on similar material. Again, not possible due to how Anki works: when the user is reviewing a particular card, FSRS (or any other algorithm) cannot access the review history of any other card. So it cannot combine data from multiple cards. Even if it could, optimization would probably become a nightmare.
+3. Consider the interference from sibling cards. This could also be extended to "conceptual siblings" - cards that don't come from the same note, but test you on similar material. Again, not possible due to how Anki works: when the user is reviewing a particular card, FSRS (or any other algorithm) cannot access the review history of any other card. So it cannot combine data from multiple cards. Even if it could, optimization would probably become a nightmare.
-All three of these combined could greatly increase the efficiency of spaced repetition. 2 and 3 combined could be particularly effective if each pair of cards is assigned a "similarity score" (using some machine learning algorithm) based on their content, though doing that naively would be computationally intractable - the number of pairs is proportional to the number of cards squared; for example, 10,000 cards have 49,995,000 pairs. Still, I would expect great improvements from an algorithm that doesn't treat cards as independent, and a review of card A affects not only the memory stability of card A but also the memory stability of card B, albeit to a lesser extent.
+All three of these combined could greatly increase the efficiency of spaced repetition. 2 and 3 combined could be particularly effective if each pair of cards is assigned a "similarity score" (using some machine learning algorithm) based on their content, though doing that naively would be computationally intractable - the number of pairs is proportional to the number of cards squared; for example, 10,000 cards have 49,995,000 pairs. Still, I would expect great improvements from an algorithm that doesn't treat cards as independent, and a review of card A affects not only the memory stability of card A but also the memory stability of card B, albeit to a lesser extent.
**Anki is not designed for advanced spaced repetition algorithms.**
There are about 20 different ways to get learning steps wrong, and having two arbitrary stages ("learning" and "review") isn't necessary to begin with.
@@ -370,14 +377,13 @@ The app must be publicly available in AppStore, Google Play Store, or elsewhere,
Predictions were made at the end of July 2024 and revised in December 2024.
-The dataset has changed, the new dataset includes interval lengths *in seconds*, deck IDs, and preset IDs, as well as information about sibling cards, so predictions 2 and 3 are no longer valid. I have also changed the first prediction because now I'm less certain that there will be no major breakthrough.
+The dataset has changed, the new dataset includes interval lengths _in seconds_, deck IDs, and preset IDs, as well as information about sibling cards, so predictions 2 and 3 are no longer valid. I have also changed the first prediction because now I'm less certain that there will be no major breakthrough.
- Has FSRS plateaued?
- Yes, it's unlikely that future iterations of FSRS will get significantly better than FSRS-5 with recency weighting.
- Does that mean that neural networks are the future?
- Yes, but kind of no. Purely in terms of how accurately they can predict the probability of recall - yes. However, FSRS still has 2 important advantages: interpretability and being computationally cheap. With neural nets, it's hard to guarantee that there won't be any strange behavior, such as the interval for "Again" being longer than the interval for "Hard", or the interval decreasing after a successful review. And peeking at the parameters won't tell you much. With FSRS we can guarantee certain behavior and tell exactly what each parameter does. And since FSRS only has 19 parameters and doesn't do matrix multiplication with matrices with millions of entries, it doesn't need a GPU and can run on any modern CPU.
-
## References
References to academic papers:
@@ -401,6 +407,6 @@ References to things that aren't academic papers:
8. [https://www.justinmath.com/individualized-spaced-repetition-in-hierarchical-knowledge-structures/](https://www.justinmath.com/individualized-spaced-repetition-in-hierarchical-knowledge-structures/)
9. [https://github.com/BlinkDL/RWKV-LM](https://github.com/BlinkDL/RWKV-LM)
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/History.md b/_posts/2024-08-02-History.md
similarity index 96%
rename from History.md
rename to _posts/2024-08-02-History.md
index 2ed487a..2af1707 100644
--- a/History.md
+++ b/_posts/2024-08-02-History.md
@@ -1,3 +1,10 @@
+---
+layout: post
+title: "Abridged history of spaced repetition"
+date: 2024-8-2 21:03:07 +0300
+categories: fsrs
+---
+
# Abridged history of spaced repetition
1885: [Hermann Ebbinghaus plots the first forgetting curve](https://en.wikipedia.org/wiki/Forgetting_curve). Although it didn't have retention on the Y axis, and also, if you have ever seen one of the images below (or something similar), you should know that **his paper didn't have that serrated kind of curve. That is a common myth.**
@@ -24,6 +31,6 @@
2024: [RemNote implements FSRS-4.5](https://help.remnote.com/en/articles/9124137-the-fsrs-spaced-repetition-algorithm) (or FSRS v4? I'm not sure), [some chess moves learning app](https://x.com/chessbookcom/status/1805137108991946775) apparently does too.
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/Algorithm.md b/_posts/2024-08-04-Algorithm.md
similarity index 92%
rename from Algorithm.md
rename to _posts/2024-08-04-Algorithm.md
index 3ee22d5..455551c 100644
--- a/Algorithm.md
+++ b/_posts/2024-08-04-Algorithm.md
@@ -1,3 +1,10 @@
+---
+layout: post
+title: "A technical explanation of FSRS"
+date: 2024-8-4 16:26:57 +0300
+categories: fsrs
+---
+
# A technical explanation of FSRS
If you want a simple overview first, start here: [ABC of FSRS](https://github.com/open-spaced-repetition/fsrs4anki/wiki/ABC-of-FSRS).
@@ -5,6 +12,7 @@ If you want a simple overview first, start here: [ABC of FSRS](https://github.co
In this article, I'll explain how FSRS-4.5 works. The differences between FSRS-4.5 and FSRS-5 are outlined near the end.
# Table of contents
+
- [R, Retrievability](#r-retrievability)
- [S, Stability](#s-stability)
- [D, Difficulty](#d-difficulty)
@@ -23,7 +31,7 @@ $$\LARGE R = ( 1 + {\frac{19}{81}} \cdot {\frac{t}{S}})^{-0.5}$$
The main difference between them is how fast R declines when t>>S. Note that when t=S, R=90% for all three functions. This has to hold true because in FSRS, memory stability is defined as the amount of time required for R to decrease from 100% to 90%. You can play around with them here: [https://www.desmos.com/calculator/au54ecrpiz](https://www.desmos.com/calculator/au54ecrpiz).
-So why does a power function provide a better fit than the exponential function if forgetting is (in theory) exponential? Let's take two exponential curves, with S=0.2 and S=3. And then let's take the average of the two resulting values of R. We will have 3 functions: R_1=0.9^(t/0.2), R_1=0.9^(t/3) and R=0.5*(0.9^(t/0.2)+0.9^(t/3)).
+So why does a power function provide a better fit than the exponential function if forgetting is (in theory) exponential? Let's take two exponential curves, with S=0.2 and S=3. And then let's take the average of the two resulting values of R. We will have 3 functions: R_1=0.9^(t/0.2), R_1=0.9^(t/3) and R=0.5\*(0.9^(t/0.2)+0.9^(t/3)).

@@ -35,7 +43,6 @@ Note that I displayed R^2 on the graph, but you can use any other measure to det
**Important takeaway number one: a superposition of two exponential functions is better approximated by a power function.**
-
## S, Stability
Now let's take a look at the main formula of FSRS.
@@ -56,13 +63,13 @@ SInc is equal to one plus the product of functions of three components of memory
$$\LARGE SInc = 1 + f(D) \cdot f(S) \cdot f(R)$$
-Now let's "unfold" each of them, starting with *f(D)*.
+Now let's "unfold" each of them, starting with _f(D)_.
$$\LARGE SInc = 1 + (11 - D) \cdot f(S) \cdot f(R)$$
**Important takeaway number two: the larger the value of D, the smaller the SInc value. This means that the increase in memory stability for difficult material is smaller than for easy material.**
-Next, let's unfold *f(S)*.
+Next, let's unfold _f(S)_.
$$\LARGE SInc = 1 + (11 - D) \cdot S^{-w_9} \cdot f(R)$$
@@ -70,7 +77,7 @@ $$\LARGE SInc = 1 + (11 - D) \cdot S^{-w_9} \cdot f(R)$$
This will likely surprise a lot of people, but the data supports it.
-Finally, let's unfold *f(R)*.
+Finally, let's unfold _f(R)_.
$$\LARGE SInc = 1 + (11 - D) \cdot S^{-w_9} \cdot (e^{w_{10} \cdot (1 - R)}- 1 )$$
@@ -90,7 +97,7 @@ The formula for the next value of S is different if the user pressed "Again".
min(..., S) is necessary to ensure that post-lapse stability can never be greater than stability before the lapse. w11 serves a similar purpose to e^w8 in the main formula: it just scales the whole product by some factor to provide a better fit.
-An interesting detail: in the main formula, the function of D is linear: f(D)=(11-D). Here, however, *f(D)* is nonlinear. Me and LMSherlock have tried different formulas, and surprisingly, these provide the best fit.
+An interesting detail: in the main formula, the function of D is linear: f(D)=(11-D). Here, however, _f(D)_ is nonlinear. Me and LMSherlock have tried different formulas, and surprisingly, these provide the best fit.
There is one problem with these formulas, though. Since both formulas require the previous value of S to calculate the next value of S, they cannot be used to estimate initial stability after the first review since there is no such thing as a "zeroth review". So initial stability has to be estimated in a completely different way.
@@ -108,7 +115,6 @@ The first four parameters that you see in the "FSRS parameters" window are the i

-
## D, Difficulty
Unlike S and R, D has no precise definition and is just a crude heuristic. Here is the formula for initial D, after the first review.
@@ -153,9 +159,9 @@ However, a more in-depth analysis reveals that the current formula works reasona

-On the x axis, we have D, and on the y axis, we have predicted and measured S. Blue dots are values of memory stability that have been measured from my review history, and the orange line is the predicted value of memory stability. Of course, both are *averages* that require thousands of reviews to estimate accurately.
+On the x axis, we have D, and on the y axis, we have predicted and measured S. Blue dots are values of memory stability that have been measured from my review history, and the orange line is the predicted value of memory stability. Of course, both are _averages_ that require thousands of reviews to estimate accurately.
-As you can see, the orange line is close to the blue dots, meaning that, *on average*, predicted stability is close to actual stability. Though the fit is worse for low values of D, they are also based on fewer reviews. This is based on one of my own decks. Also, I say "close", but [mean absolute percentage error (MAPE)](https://en.wikipedia.org/wiki/Mean_absolute_percentage_error) is around 33% for my collection here, meaning that, on average, FSRS is off my 33% when predicting the value of S. Note that this depends on what you have on the X axis. For example, below is a similar graph, but for S as a function of it's own previous value. Here, MAPE is 12%. Also, both graphs are specifically for when the user presses "Good".
+As you can see, the orange line is close to the blue dots, meaning that, _on average_, predicted stability is close to actual stability. Though the fit is worse for low values of D, they are also based on fewer reviews. This is based on one of my own decks. Also, I say "close", but [mean absolute percentage error (MAPE)](https://en.wikipedia.org/wiki/Mean_absolute_percentage_error) is around 33% for my collection here, meaning that, on average, FSRS is off my 33% when predicting the value of S. Note that this depends on what you have on the X axis. For example, below is a similar graph, but for S as a function of it's own previous value. Here, MAPE is 12%. Also, both graphs are specifically for when the user presses "Good".

@@ -163,18 +169,17 @@ Side note: D ranges from 1 to 10, but in the built-in version of FSRS, D is disp
It's important to mention that me and Sherlock have tried to incorporate R into the formulas for D, but it didn't improve the accuracy. Even though we know that in theory D should depend on R, we don't know how to actually add R to D in a way that is useful.
-
## Changes in FSRS-5
-1) The formula for initial D was changed.
+1. The formula for initial D was changed.

-Again=1, Hard=2, Good=3, Easy=4. This formula provides a *slightly* better fit. Because difficulty is clamped between 1 and 10, negative values of D are not a problem, they will simply be replaced with 1. Remember that any difficulty value <1 is set to 1 and any value >10 is set to 10.
+Again=1, Hard=2, Good=3, Easy=4. This formula provides a _slightly_ better fit. Because difficulty is clamped between 1 and 10, negative values of D are not a problem, they will simply be replaced with 1. Remember that any difficulty value <1 is set to 1 and any value >10 is set to 10.
-2) "Mean reversion" now reverses the difficulty to that of D0(4), rather than D0(3). Also, while normally D is clamped between 1 and 10, when using mean reversion, *unclamped* initial D is used. This was originally a bug, but then it turned out that it actually slightly improves the results as opposed to using a clamped D0 for mean reversion.
+2. "Mean reversion" now reverses the difficulty to that of D0(4), rather than D0(3). Also, while normally D is clamped between 1 and 10, when using mean reversion, _unclamped_ initial D is used. This was originally a bug, but then it turned out that it actually slightly improves the results as opposed to using a clamped D0 for mean reversion.
-3) A new term has been added. Thanks to that term, when the user presses "Again" or "Hard", difficulty will approach 10 *asymptotically*, meaning that it will never be precisely 10.
+3. A new term has been added. Thanks to that term, when the user presses "Again" or "Hard", difficulty will approach 10 _asymptotically_, meaning that it will never be precisely 10.
Here is the new formula:
@@ -184,14 +189,13 @@ Here is the new formula:
(10-D)/9 is the linear damping term. The closer D is to 10, the smaller this term, the smaller the change in difficulty.
-4) FSRS-5 updates D and S after same-day reviews, which previously were unused. D is updated using the formula described above. S is updated using the following formula:
+4. FSRS-5 updates D and S after same-day reviews, which previously were unused. D is updated using the formula described above. S is updated using the following formula:

In Anki, FSRS cannot get access to the real interval lengths of same-day reviews, so it has to rely solely on grades. w17 and w18 are two new parameters.
-5) Previously, the first 4 parameters - values of initial stability - were optimized without using gradient descent, using a curve-fitting method that is specific to spaced repetition. After that, they remained "frozen". Now, after they are calculated, they can be adjusted by gradient descent, just like the other parameters. This results in a slightly better fit.
-
+5. Previously, the first 4 parameters - values of initial stability - were optimized without using gradient descent, using a curve-fitting method that is specific to spaced repetition. After that, they remained "frozen". Now, after they are calculated, they can be adjusted by gradient descent, just like the other parameters. This results in a slightly better fit.
## Optimization aka training
@@ -209,6 +213,6 @@ I won't go too into detail about this, instead you can watch [this video about g
Of course, it's a lot more nuanced than that, but if you want to learn about gradient descent, there are hundreds of videos and articles on the Internet, since this is how almost every machine learning algorithm in the world is trained.
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/Buttons.md b/_posts/2024-08-17-Buttons.md
similarity index 87%
rename from Buttons.md
rename to _posts/2024-08-17-Buttons.md
index 476f23e..6c57b4f 100644
--- a/Buttons.md
+++ b/_posts/2024-08-17-Buttons.md
@@ -1,8 +1,15 @@
+---
+layout: post
+title: "Button usage and review time of Anki users"
+date: 2025-1-14 17:36:37 +0300
+categories: anki
+---
+
# Button usage and review time of Anki users
Apart from being great for benchmarking algorithms on it, the [Anki 20k dataset](https://huggingface.co/datasets/open-spaced-repetition/FSRS-Anki-20k) also provides a definitive answer to an age-old question: is the amount of time spent reviewing a card correlated with which answer button (Again/Hard/Good/Easy) the user will press?
-Here's the answer:
+Here's the answer:

@@ -18,17 +25,15 @@ In case you are confused: for example, Again > Hard > Good > Easy means "Average
I hope nobody will interpret this article as "It's ok to use review time to automatically select the answer button for the user".
-1) Time to answer varies not only between different people but also between different types of material. So Anki will have to estimate what time corresponds to Again-Hard-Good-Easy for this specific user and for this specific material.
-
-2) average_t(Again) > average_t(Hard) > average_t(Good) > average_t(Easy) is true only for 40% of users.
+1. Time to answer varies not only between different people but also between different types of material. So Anki will have to estimate what time corresponds to Again-Hard-Good-Easy for this specific user and for this specific material.
+2. average_t(Again) > average_t(Hard) > average_t(Good) > average_t(Easy) is true only for 40% of users.
-3) There will be outliers if the user went to the toilet or got distracted by a phone call or something.
+3. There will be outliers if the user went to the toilet or got distracted by a phone call or something.
It's **WAY** easier to just use self-reported grades. There are a lot of arguments about using 2 vs 4 buttons, and those arguments will likely last as long as Anki itself, but using time as a proxy for the answer button will be worse than either of those options. Using time as a proxy will work reliably only for about 40% of users, will be prone to outliers, and the exact cutoffs will have to be adjusted for each user individually and for different decks.
Compare that to just asking the user to click a button.
+---
-
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/Retention.md b/_posts/2024-08-17-Retention.md
similarity index 97%
rename from Retention.md
rename to _posts/2024-08-17-Retention.md
index 681c459..21f894c 100644
--- a/Retention.md
+++ b/_posts/2024-08-17-Retention.md
@@ -1,3 +1,10 @@
+---
+layout: post
+title: "Understanding retention in FSRS"
+date: 2024-8-17 13:17:13 +0300
+categories: fsrs
+---
+
# Understanding retention in FSRS
TLDR: desired retention is "I will recall this % of cards **WHEN THEY ARE DUE**". Average retention is "I will recall this % of **ALL** my cards **TODAY**".
@@ -40,6 +47,6 @@ This graph shows you how average retrievability depends on desired retention, in
Again, just to make it clear in case you are lost: desired retention is "I will recall this % of cards **WHEN THEY ARE DUE**". Average retrievability is "I will recall this % of **ALL** my cards **TODAY**".
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/Perfect_UI.md b/_posts/2024-08-20-Perfect_UI.md
similarity index 70%
rename from Perfect_UI.md
rename to _posts/2024-08-20-Perfect_UI.md
index f2a3a85..34c89fe 100644
--- a/Perfect_UI.md
+++ b/_posts/2024-08-20-Perfect_UI.md
@@ -1,3 +1,10 @@
+---
+layout: post
+title: "The Perfect UI and the future of FSRS"
+date: 2024-8-20 16:01:51 +0300
+categories: anki
+---
+
# The Perfect UI and the future of FSRS
As you (hopefully) realize, the average person doesn't want to spend time to understand 20 different settings, especially if they involve math. With that in mind, I propose the following redesign of deck options:
@@ -8,18 +15,18 @@ It doesn't get any simpler than this!
In all seriousness, though, I don't think that FSRS (or any similar algorithm) can come anywhere close to mass adoption without:
-1) Making FSRS the default algorithm.
+1. Making FSRS the default algorithm.
-2) Hiding the field with parameters, as well as anything that has the word "parameter" or "optimize" in it.
+2. Hiding the field with parameters, as well as anything that has the word "parameter" or "optimize" in it.
-3) Hiding any numbers other than desired retention, which should be the only number that the user can see.
+3. Hiding any numbers other than desired retention, which should be the only number that the user can see.
-4) Automatically suggesting the optimal value of desired retention so that the user can turn their brain off and just go along with the suggestion.
+4. Automatically suggesting the optimal value of desired retention so that the user can turn their brain off and just go along with the suggestion.
-5) Automatically, periodically optimizing parameters without notifying the user.
+5. Automatically, periodically optimizing parameters without notifying the user.
This is what it takes to even begin reaching mass adoption (of course, other elements of the UI that aren't related to the algorithm would also have to be redesigned). In its current state, FSRS is difficult to use, even for advanced users.
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/Addons.md b/_posts/2024-09-04-Addons.md
similarity index 95%
rename from Addons.md
rename to _posts/2024-09-04-Addons.md
index bd36dc6..15d230b 100644
--- a/Addons.md
+++ b/_posts/2024-09-04-Addons.md
@@ -1,16 +1,26 @@
+---
+layout: post
+title: "Add-ons that I use"
+date: 2024-9-4 03:09:22 +0300
+categories: anki
+---
+
# Add-ons that I use
## FSRS Helper
+
[https://ankiweb.net/shared/info/759844606](https://ankiweb.net/shared/info/759844606).
It's not essential if you want to use FSRS, but it offers a lot of nice quality-of-life features. [I have an entire post dedicated to them](https://www.reddit.com/r/Anki/comments/1attbo1/explaining_fsrs_helper_addon_features/).
## Review Heatmap
+
[https://ankiweb.net/shared/info/1771074083](https://ankiweb.net/shared/info/1771074083).
It is the highest rated add-on on AnkiWeb, so while I doubt that it needs an introduction, I just thought the list wouldn't be complete without it.

## Advanced Review Bottom Bar
+
[https://ankiweb.net/shared/info/1136455830](https://ankiweb.net/shared/info/1136455830).
Do you want to customize your answer buttons? Do you want to change their colors? Make them wider? Or change the font size? Hide Hard? Hide Easy? Add new shortcuts? Rename "Again" to "Fail"? You can do all of that and more with this add-on.
@@ -19,16 +29,18 @@ Btw, here's what my buttons look like:

## Simple Forvo Audio Downloader
+
[https://ankiweb.net/shared/info/560814150](https://ankiweb.net/shared/info/560814150).
It is indispensable for language learners. It allows you to select a word and find an audio file with a native speaker pronouncing that word. It's simple to use, and it's better than TTS...unless the word is really obscure and there is no audio.
Still, this has been very helpful in my language studies, and it's my personal favorite on this list.
(gif)
## Randomize Fonts
+
[https://ankiweb.net/shared/info/82628558](https://ankiweb.net/shared/info/82628558).
This one might raise some eyebrows, but I think it's very useful for Japanese (or Chinese). It forces you to recognize kanji in different fonts, including highly stylized ones.
(gif)
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/Avoid_Pattern_Matching.md b/_posts/2024-10-25-Avoid_Pattern_Matching.md
similarity index 95%
rename from Avoid_Pattern_Matching.md
rename to _posts/2024-10-25-Avoid_Pattern_Matching.md
index 1811350..6424579 100644
--- a/Avoid_Pattern_Matching.md
+++ b/_posts/2024-10-25-Avoid_Pattern_Matching.md
@@ -1,19 +1,26 @@
+---
+layout: post
+title: "Note Types to Avoid Pattern Matching"
+date: 2024-10-25 21:30:02 +0300
+categories: anki
+---
+
# Note Types to Avoid Pattern Matching
-One of the big issues that Anki users face is memorizing what the answer *looks* like rather than the actual information, which is sometimes called "pattern matching". This can lead to situations where someone can "recall" the answer in Anki, but not in real life. The new note types that I wrote about in this article aim to solve this problem as well as allow you to memorize the same amount of information while making fewer cards.
+One of the big issues that Anki users face is memorizing what the answer _looks_ like rather than the actual information, which is sometimes called "pattern matching". This can lead to situations where someone can "recall" the answer in Anki, but not in real life. The new note types that I wrote about in this article aim to solve this problem as well as allow you to memorize the same amount of information while making fewer cards.
[https://ankiweb.net/shared/info/171015247](https://ankiweb.net/shared/info/171015247). The deck has examples of 5 new note types: Match Pairs, Randomized Cloze, Randomized Basic, Randomized Basic with Multiple Answers, and Click Words. Once you download it, you'll be able to make cards based on these note types on your own, **no add-ons needed**. Huge thanks to [Vilhelm Ian](https://github.com/Vilhelm-Ian) (aka Yoko in the [Anki Discord server](https://discord.gg/qjzcRTx), aka [AnkiQueen](https://forums.ankiweb.net/u/ankiqueen/summary) on the forum) for making these note types!
They work on all platforms: on desktop Anki, on AnkiDroid and on AnkiMobile.
Table of contents:
+
- [Match Pairs](#match-pairs)
- [Randomized Cloze](#randomized-cloze)
- [Randomized Basic](#randomized-basic)
- [Randomized Basic with Multiple Answers](#randomized-basic-with-multiple-answers)
- [Click Words](#click-words)
-
## Match Pairs
Have you ever had cards like this? There are 2 pieces of knowledge, and you can't remember which is which, so you make a Cloze.
@@ -35,7 +42,7 @@ And if you think that this is too easy and therefore would make active recall in

Here you have 2 countries and 3 capitals, so you need to think harder.
-Make sure that the extra answer is wrong, but not *obviously* wrong. In this example, I won't benefit from adding Jakarta to the second list, since it's obviously wrong. Which is why I added Amsterdam - Amsterdam makes me pause and think, Jakarta doesn't.
+Make sure that the extra answer is wrong, but not _obviously_ wrong. In this example, I won't benefit from adding Jakarta to the second list, since it's obviously wrong. Which is why I added Amsterdam - Amsterdam makes me pause and think, Jakarta doesn't.
Still not hard enough? You can add 2 wrong answers. The number of wrong answers displayed is at most equal to the number of correct answers. The card below will never show "Poopville", because there are 2 correct answers, which means that there can only be 0, 1 or 2 incorrect answers.
@@ -45,7 +52,7 @@ Btw, you don't necessarily have to drag answers - you can click on them. When yo
`|` is the separator that you should put between items, **this is all you have to remember to create these cards**. Don't worry about leading/trailing spaces, they are stripped away automatically: `Answer1 | Answer2` will produce the same result as `Answer1|Answer2`.
-In all examples above, I used two pairs, but you can add more. However, stuffing too much information into a single card is a bad practice. I recommend having 2-3 pairs, *maaaaaaaaaaaybe* 4, but not more.
+In all examples above, I used two pairs, but you can add more. However, stuffing too much information into a single card is a bad practice. I recommend having 2-3 pairs, _maaaaaaaaaaaybe_ 4, but not more.
Match Pairs also supports images.
@@ -57,7 +64,6 @@ https://github.com/user-attachments/assets/6f65fb06-322b-4745-8ee9-101b126e2df5
Of course, how useful this note type is for you depends on how often you encounter what I call "negative interference", where card A makes it harder to remember card B, and card B makes it harder to remember card A. Personally, I've been able to replace dozens of unnecessary clozes with this note type, and I think it would be cool if this note type would become built-in in the future.
-
## Randomized Cloze
This is another note type that aims to solve the pattern matching problem.
@@ -72,7 +78,6 @@ One thing that you should keep in mind: the numbers in curly brackets have to be
The `|` separator is the same.
-
## Randomized Basic
It's exactly what it sounds like. And the separator is the same.
@@ -83,7 +88,6 @@ It's exactly what it sounds like. And the separator is the same.
Keep in mind that this isn't Match Pairs, the back can only have **one** item. The `|` separator won't work in the "Back" field.
-
## Randomized Basic with Multiple Answers
This is just 2/3/n notes in one. You may be wondering, "Why not just *actually* make several notes?". For the most part that's true, but there is (at least) one situation where this is useful: practicing math concepts.
@@ -98,7 +102,6 @@ Here's a little diagram to help you understand the difference between this and R

-
## Click Words

@@ -123,6 +126,6 @@ As it says, don't delete it. It is necessary for some stuff related to playing a
# If you find any bugs or if you have any feature requests, here: [https://github.com/Vilhelm-Ian/Interactive_And_Randomize_Anki_Note_Types/issues/new](https://github.com/Vilhelm-Ian/Interactive_And_Randomize_Anki_Note_Types/issues/new)
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/Learning_Steps.md b/_posts/2024-10-25-Learning_Steps.md
similarity index 63%
rename from Learning_Steps.md
rename to _posts/2024-10-25-Learning_Steps.md
index ebbb06c..e8631ef 100644
--- a/Learning_Steps.md
+++ b/_posts/2024-10-25-Learning_Steps.md
@@ -1,31 +1,38 @@
+---
+layout: post
+title: "Let's get learning steps wrong! (it's very easy)"
+date: 2024-10-25 21:37:03 +0300
+categories: anki
+---
+
# Let's get learning steps wrong! (it's very easy)
Let's just preface this by saying that **15m**, **20m** or **30m** is ideal both with FSRS and with the old algorithm too. But who cares about what is "ideal" or "optimal"? We're here to get things WRONG! Here are 12 ways to get the learning steps in Anki wrong:
-1) **2d**. This can cause the interval for Hard to be longer than the interval for Good.
+1. **2d**. This can cause the interval for Hard to be longer than the interval for Good.
-2) **1d**. Believe it or not, this also can cause the same problem as above, because it can somehow turn Hard into 2d, don't ask how.
+2. **1d**. Believe it or not, this also can cause the same problem as above, because it can somehow turn Hard into 2d, don't ask how.
-3) **12h**. This can cause Hard and Good to be equal. It's not as bad as Hard > Good, but still undesirable.
+3. **12h**. This can cause Hard and Good to be equal. It's not as bad as Hard > Good, but still undesirable.
-4) **18h**. This can cause Again, Hard and Good to be equal to each other.
+4. **18h**. This can cause Again, Hard and Good to be equal to each other.
-5) **10m 10m**. This also can cause Again, Hard and Good to be equal to each other.
+5. **10m 10m**. This also can cause Again, Hard and Good to be equal to each other.
-6) **1m 15m**. This will make you review a new card twice per day. FSRS doesn't take same-day reviews into account (FSRS-5 does, though), so the extra step is just a waste of time. The more short steps you have, the more time you waste, since FSRS won't use those reviews, and a year from now on it won't matter whether you reviewed this card 1 or 2 or 3 times on your first day of seeing it, regardless of which algorithm you use. This is the least wrong way of using learning steps out of all the wrong ways listed in this article, though it's still suboptimal.
+6. **1m 15m**. This will make you review a new card twice per day. FSRS doesn't take same-day reviews into account (FSRS-5 does, though), so the extra step is just a waste of time. The more short steps you have, the more time you waste, since FSRS won't use those reviews, and a year from now on it won't matter whether you reviewed this card 1 or 2 or 3 times on your first day of seeing it, regardless of which algorithm you use. This is the least wrong way of using learning steps out of all the wrong ways listed in this article, though it's still suboptimal.
-7) **30m 15m**. This will cause Again to be longer than Hard, which in turn will be longer than Good aka Again > Hard > Good.
+7. **30m 15m**. This will cause Again to be longer than Hard, which in turn will be longer than Good aka Again > Hard > Good.
-8) **15m 1d**. This will cause your first interval after you press Good to be one day long instead of allowing FSRS to choose the best first interval for you. The same consideration applies to the old algorithm too, though it's more important for FSRS.
+8. **15m 1d**. This will cause your first interval after you press Good to be one day long instead of allowing FSRS to choose the best first interval for you. The same consideration applies to the old algorithm too, though it's more important for FSRS.
-9) **12h 1d**. This will combine the problems of number 3 and number 8 together.
+9. **12h 1d**. This will combine the problems of number 3 and number 8 together.
-10) **18h 1d**. This will combine the problems of number 4 and number 8 together.
+10. **18h 1d**. This will combine the problems of number 4 and number 8 together.
-11) **1m 15m 1d**. This will combine the problems of number 6 and number 8 together.
+11. **1m 15m 1d**. This will combine the problems of number 6 and number 8 together.
-12) A special award goes to the learning steps of a certain user: **1m 10m 1d 2d 4d 8d 16d 32d 64d 99d**. At this point it doesn't matter whether you are using FSRS or the old algorithm, your learning steps are basically your own new algorithm now, and an extremely inflexible one.
+12. A special award goes to the learning steps of a certain user: **1m 10m 1d 2d 4d 8d 16d 32d 64d 99d**. At this point it doesn't matter whether you are using FSRS or the old algorithm, your learning steps are basically your own new algorithm now, and an extremely inflexible one.
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/Max_Interval.md b/_posts/2024-10-25-Max_Interval.md
similarity index 94%
rename from Max_Interval.md
rename to _posts/2024-10-25-Max_Interval.md
index 729f278..ebf4e38 100644
--- a/Max_Interval.md
+++ b/_posts/2024-10-25-Max_Interval.md
@@ -1,3 +1,10 @@
+---
+layout: post
+title: "Should You Lower Your Max. Interval?"
+date: 2024-10-25 21:37:12 +0300
+categories: anki
+---
+
# Should You Lower Your Max. Interval?
The lower your max. interval, the more frequently you will have to see your card. This, in turn, increases your daily workload, in minutes of studying. So at first glance, it may seem like keeping it as high as possible is good.
@@ -19,6 +26,6 @@ Perhaps one day I'll come up with a way to precisely determine the optimal value
Until then, I set it to 5 years for most of my decks, except for decks with very hard material, where I keep the max. interval at 365 days. I think it's a reasonable compromise.
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/_posts/2024-11-08-welcome-to-jekyll.markdown b/_posts/2024-11-08-welcome-to-jekyll.markdown
deleted file mode 100644
index 18232d0..0000000
--- a/_posts/2024-11-08-welcome-to-jekyll.markdown
+++ /dev/null
@@ -1,29 +0,0 @@
----
-layout: post
-title: "Welcome to Jekyll!"
-date: 2024-11-08 20:59:08 +0800
-categories: jekyll update
----
-You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated.
-
-Jekyll requires blog post files to be named according to the following format:
-
-`YEAR-MONTH-DAY-title.MARKUP`
-
-Where `YEAR` is a four-digit number, `MONTH` and `DAY` are both two-digit numbers, and `MARKUP` is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works.
-
-Jekyll also offers powerful support for code snippets:
-
-{% highlight ruby %}
-def print_hi(name)
- puts "Hi, #{name}"
-end
-print_hi('Tom')
-#=> prints 'Hi, Tom' to STDOUT.
-{% endhighlight %}
-
-Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll’s GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekyll Talk][jekyll-talk].
-
-[jekyll-docs]: https://jekyllrb.com/docs/home
-[jekyll-gh]: https://github.com/jekyll/jekyll
-[jekyll-talk]: https://talk.jekyllrb.com/
diff --git a/RedditBot.md b/_posts/2024-11-19-RedditBot.md
similarity index 97%
rename from RedditBot.md
rename to _posts/2024-11-19-RedditBot.md
index 8fe919d..e4106fd 100644
--- a/RedditBot.md
+++ b/_posts/2024-11-19-RedditBot.md
@@ -1,3 +1,10 @@
+---
+layout: post
+title: "Reddit Bot"
+date: 2024-11-19 13:54:45 +0300
+categories: other
+---
+
# Reddit Bot
I made [u/FSRS_bot](https://www.reddit.com/user/FSRS_bot/) on Reddit, it helps people on [r/Anki](https://www.reddit.com/r/Anki) and [r/medicalschoolanki](https://www.reddit.com/r/medicalschoolanki) with FSRS-related questions.
@@ -53,7 +60,7 @@ My initial idea was to just check if the post contains "FSRS", or one of its mis
10) Disperse Siblings. A post about the Disperse Siblings feature of the add-on.
-11) Fuzz. A post about fuzz *and* FSRS, not just fuzz. One of the rarest types of posts.
+11) Fuzz. A post about fuzz _and_ FSRS, not just fuzz. One of the rarest types of posts.
12) SM-2 Retention. A post about SM-2 retention (renamed to "Historical retention" at some point). One of the rarest types of posts.
@@ -63,7 +70,7 @@ My initial idea was to just check if the post contains "FSRS", or one of its mis
15) Should. A post where hte person has doubts about switching to FSRS.
-16) AO (automatic optimization). A post about *automatic* optimization of parameters and why it's not implemented yet. One of the rarest types of posts. One of the rarest types of posts.
+16) AO (automatic optimization). A post about _automatic_ optimization of parameters and why it's not implemented yet. One of the rarest types of posts. One of the rarest types of posts.
17) ETK (estimated total knowldge). A post about the new stat: [estimated total knowledge](https://docs.ankiweb.net/stats.html#the-graphs). One of the rarest types of posts.
@@ -133,7 +140,7 @@ On the left we are trying to use a straight line to fit clearly non-linear data.
The problem is that the model on the right won't **generalize** well. Generalization is the model's ability to perform well on previously unseen data aka data that it wasn't trained on. If the model performs great on training data, but outputs garbage when you give it new data, then it's a terrible model. How do you make sure that your model isn't overfitting?
-1) Ensure that the number of parameters is many times smaller than the number of datapoints. For example, if your model only has 3 parameters, it's *probably* ok to train it on 20-30 datapoints. However, when it comes to neural networks, it's not uncommon to train gigantic models on relatively small (compared to the number of datapoints) datasets.
+1) Ensure that the number of parameters is many times smaller than the number of datapoints. For example, if your model only has 3 parameters, it's _probably_ ok to train it on 20-30 datapoints. However, when it comes to neural networks, it's not uncommon to train gigantic models on relatively small (compared to the number of datapoints) datasets.
2) Early stopping. It's perfectly simple - train the model on the trainining dataset (I will call it "train set") and keep an eye out for its performance on the testing dataset (test set). 
@@ -205,7 +212,7 @@ Result:
`Hey everoyne, I have a problem with FSRS. I can't optimize my parameetrs. akf92j56kcvjk. Screenshot: `
-Now we need to split it into **tokens**. A token is not necessarily a word, it could be a period, a comma, a semicolon, a number, etc. Thankfully, we can use the greatest Python technique known as *Import That One Library That Does Exactly What I Want*, or "ITOLTDEWIW".
+Now we need to split it into **tokens**. A token is not necessarily a word, it could be a period, a comma, a semicolon, a number, etc. Thankfully, we can use the greatest Python technique known as _Import That One Library That Does Exactly What I Want_, or "ITOLTDEWIW".

@@ -314,7 +321,7 @@ Now all that's left is to assign an integer to every word. It doesn't really mat
3) If a token appears <4 times in the entire dataset + "GPT'ed" dataset (more about that later), it will be assigned a special integer reserved for obscure crap and typos ("unk"). A token must appear at least 4 times across three variations of the dataset to warrant having it's own index.
-The overall vocabulary size of my Transformer is currently 6448 unique tokens. For ~~magical~~ programming reasons, I made it a multiple of 8 (as well as a few of other things, like text length and some hyperparameters). Minus 0 because it's for padding, minus 6511 because it's for obscure crap and typos.
+The overall vocabulary size of my Transformer is currently 6448 unique tokens. For ~~magical~~ programming reasons, I made it a multiple of 8 (as well as a few of other things, like text length and some hyperparameters). Minus 0 because it's for padding, minus 6511 because it's for obscure crap and typos.
## Part Six: Can I Get More Data?
@@ -332,7 +339,7 @@ Can I get more data?
I guess it's time to scrape comments now. However, most comments aren't useful since there are too many comments where the person is explaining FSRS rather than asking a question about FSRS. I need questions, not answers. So I only labeled 92 comments out of several thousands.
-*Can I get more data?*
+_Can I get more data?_
I can't get any more data...or can I? It's time to learn about another important concept: **data augmentation**. By taking the original data and tweaking it, we can create more training examples and make the neural net robust to relatively small differences that wouldn't throw a human off. Here are some examples of what is used in computer vision tasks:
@@ -342,7 +349,7 @@ Of course, the techniques used for text are different from those used for images

-I will be using 50% of the dataset for training, so only 0.5*1519=1,063 texts will be used for training.
+I will be using 50% of the dataset for training, so only 0.5\*1519=1,063 texts will be used for training.
Rephrasing trippled the size of the training set, from 1,063 texts to 3,189 texts.
@@ -354,7 +361,7 @@ From a human perspective, this can result in posts where it looks like the first
This doesn't work on posts that are too long to fit into the Transformer's context window after being fused with other posts, and also on posts that have 2-3 labels and this combination of labels is unique and doesn't occur anywhere else in the dataset. Because of all that, the overall increase in the number of training examples is less than 2.
-Fusing texts increased the size of the training set by roughly x1.92, from texts to texts. Note that unlike in the example with the kitten that I showed above, I apply multiple augmentation techniques sequentially to get even more data, so that the size of the dataset increases exponentially as I add more techniques.
+Fusing texts increased the size of the training set by roughly x1.92, from texts to texts. Note that unlike in the example with the kitten that I showed above, I apply multiple augmentation techniques sequentially to get even more data, so that the size of the dataset increases exponentially as I add more techniques.
**Can I get more data?!**
@@ -372,16 +379,15 @@ list_of_sentences = [(x + ' ') if (x != list_of_sentences[-1]) else x for x in l
I made it so that if a text has 2-5 sentences, two randomly chosen adjacent sentences would be swapped. If the text has >5 sentences, four sentences (two pairs) will be swapped.
-
Sentence swapping doubled the size of the dataset, from 4,400 texts to 8,800 texts. Sure, short texts with just one sentence are duplicated, by meh, whatever.
-***Can I get more data?!***
+**_Can I get more data?!_**
-This next technique is my own invention, I haven't seen it in literature. I call it "filler sentence injection". First, I write down a bunch of filler sentences, such as "Hello everyone", "Hi", "EDIT: added screenshots", "P.S. English is not my native language", "Help would be appreciated", "What are your thoughts, fellow Anki users?", "I would like to hear from experts", "I'm not 100% sure", etc. These sentences don't change what the text is about. If a text is about learning steps, it will be about learning steps with or without these sentences. If a text is about Easy Days, it will be about Easy Days with or without these sentences, etc. Then I randomly inject one of these sentences inbetween two other sentences, or before the first sentence, or after the last sentence. For the sake of keeping it similar to a text actually written by a human, some filler sentences like "P.S. I love this community!" are only appended at the end, and some, like "Greetings, everyone!" are inserted only in the beginning. Obviously, nobody *starts* their post with P.S.
+This next technique is my own invention, I haven't seen it in literature. I call it "filler sentence injection". First, I write down a bunch of filler sentences, such as "Hello everyone", "Hi", "EDIT: added screenshots", "P.S. English is not my native language", "Help would be appreciated", "What are your thoughts, fellow Anki users?", "I would like to hear from experts", "I'm not 100% sure", etc. These sentences don't change what the text is about. If a text is about learning steps, it will be about learning steps with or without these sentences. If a text is about Easy Days, it will be about Easy Days with or without these sentences, etc. Then I randomly inject one of these sentences inbetween two other sentences, or before the first sentence, or after the last sentence. For the sake of keeping it similar to a text actually written by a human, some filler sentences like "P.S. I love this community!" are only appended at the end, and some, like "Greetings, everyone!" are inserted only in the beginning. Obviously, nobody _starts_ their post with P.S.
I did three rounds of filler injection to obtain three more variations of the dataset and it quadrupled the size of the dataset, from 8,800 texts to 35,200 texts.
-***CAN I GET MORE DATA?!***
+**_CAN I GET MORE DATA?!_**
Ok, it's time for the final technique. What if instead of modifying the text, we modified the indices? Here's how exactly:
@@ -394,7 +400,7 @@ Ok, it's time for the final technique. What if instead of modifying the text, we
Then for each word in the dataset I measured its distance to each other word to find its nearest neighbor, like "interval" -> "internal". This way we can simulate a different kind of typo, the kind that a spellchecker can't possibly catch.
Then I assigned a 4.8% probability to 'index of a valid token -> index of "unk"' and a 1.7% probability to 'index of a valid token -> index of a valid token'.
-That's a total 6.5% probability of a typo *per token*, or approximately 99.88% probability of at least one typo per 100 tokens.
+That's a total 6.5% probability of a typo _per token_, or approximately 99.88% probability of at least one typo per 100 tokens.
Then all I had to do was just run the randomizer 4 times to create 4 more variations of the train set. This brought the total number of texts in the training set to **140,800**, 133 times more than without data augmentation!
@@ -410,11 +416,10 @@ Comparison of different data augmentation methods that I used:
By "diversity" I mean "variation between the original and augmented data".
-
Oh, and I also added some completely made-up texts for very rare classes, such as "Automatic Optimization". If you don't have enough real data, add half-fake data. If even that is not enough, add fake data. As long as you can manually make high-quality examples, it's fine.
-
**IMPORTANT**: when doing data augmentation, make sure that the test set doesn't have any variations of texts that are in the train set, or else the model will display unrealistically good results on the test set only to shit itself in real life. It's called data leaking. In other words, if there are N variations of text X, make sure that **all** N variations stay in the train set and **none** of them are in the test set.
-___
+---
+
### [←Return to homepage](https://expertium.github.io/)
diff --git a/ScientistsAge.md b/_posts/2024-11-29-ScientistsAge.md
similarity index 94%
rename from ScientistsAge.md
rename to _posts/2024-11-29-ScientistsAge.md
index 540ab58..1e71b34 100644
--- a/ScientistsAge.md
+++ b/_posts/2024-11-29-ScientistsAge.md
@@ -1,3 +1,10 @@
+---
+layout: post
+title: "At What Age Do Great Scientists Make Great Discoveries?"
+date: 2024-8-17 13:17:13 +0300
+categories: other
+---
+
# At What Age Do Great Scientists Make Great Discoveries?
If you ask someone, "How do you envision a genius scientist?" most people will probably imagine an old man with gray hair. But how close to reality is that image?
@@ -10,7 +17,7 @@ The first one is easy. The second can be tricky, especially for people like Leon
The full list can be found [here](https://docs.google.com/spreadsheets/d/1mPnYsYydydhAcNebVCPkUYtrOPRzTl1A/edit?usp=sharing&ouid=112204483776265915673&rtpof=true&sd=true). I admit, I was quite sloppy when writing down contributions.
-I won't go over every single person on the list since that would take too long, so let's use Einstein as an example and then get to the main point of this article. Einstein developed the theory of special relativity in 1905 and the theory of general relativity in 1915.
+I won't go over every single person on the list since that would take too long, so let's use Einstein as an example and then get to the main point of this article. Einstein developed the theory of special relativity in 1905 and the theory of general relativity in 1915.
Averaging the two gives us 1910. Einstein was born in 1879, which means he was 31 years old in 1910.
Here's what the distribution of ages at the time of the greatest discovery looks like:
@@ -23,7 +30,7 @@ Here's what the distribution of ages at the time of the greatest discovery looks
**99% percentile: 57 years.**
-Overall, I am somewhat surprised by the results. I was expecting that ages will be concentrated in a narrow range, for example, 20-30.
+Overall, I am somewhat surprised by the results. I was expecting that ages will be concentrated in a narrow range, for example, 20-30.
According to cognitive scientists, there are two types of intelligence: fluid and crystallized, which is just a fancy was of saying "how good someone is at reasoning" and "how much information they know". And the way these two types of intelligence change as we age is not the same:
@@ -31,9 +38,9 @@ According to cognitive scientists, there are two types of intelligence: fluid an
Fluid intelligence peaks around 20, while crystallized intelligence either stagnates or keeps growing (for example, if that person uses spaced repetition 😉) but doesn't decline in the absence of neurodegenerative diseases.
-Intuitively, I expect that fluid intelligence matters a lot more than crystallized when it comes to inventing/discovering something new, which is why I said that I was expecting ages to fall within the 20-30 range.
+Intuitively, I expect that fluid intelligence matters a lot more than crystallized when it comes to inventing/discovering something new, which is why I said that I was expecting ages to fall within the 20-30 range.
Perhaps the relationship between the fluid intelligence and making a great discovery is more tenuous than I thought. Or perhaps crystallized intelligence plays a more significant role than I think.
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/20reasons.md b/_posts/2025-01-14-20reasons.md
similarity index 90%
rename from 20reasons.md
rename to _posts/2025-01-14-20reasons.md
index 1a13361..67d9a2f 100644
--- a/20reasons.md
+++ b/_posts/2025-01-14-20reasons.md
@@ -1,3 +1,10 @@
+---
+layout: post
+title: "20 reasons why Anki isn't popular"
+date: 2025-1-14 17:36:37 +0300
+categories: anki
+---
+
# 20 reasons why Anki isn't popular
I decided to put together every single reason that I could think of, or that I had heard from someone else. If a reason is not on this list, you are probably the first person who has ever thought of it.
@@ -10,13 +17,13 @@ I decided to put together every single reason that I could think of, or that I h
4) Spaced repetition is great for lifelong learning, but most people are not lifelong learners.
-5) Anki is far more complex than, say, Duolingo, so it could never compete with Duolingo in terms of the number of active users. An app that is easier to use has a tremendous advantage when it comes to attracting users, *regardless of its effectiveness*. An app that has a 200 pages manual has lost the popularity race before the it even made it to the starting line.
+5) Anki is far more complex than, say, Duolingo, so it could never compete with Duolingo in terms of the number of active users. An app that is easier to use has a tremendous advantage when it comes to attracting users, _regardless of its effectiveness_. An app that has a 200 pages manual has lost the popularity race before the it even made it to the starting line.
6) A lot of people want to "pause" Anki to prevent due cards from piling up, but that contradicts the simple fact that even if you can pause an app, you can't pause forgetting inside your head. So there is a conflict between optimal scheduling and user satisfaction.
7) Reviewing every day requires consistency that a lot of people lack.
-8) If you don't know the difference between recognition (*"Have you watched the Terminator with Arnold Schwarzenegger?"*) and recall (*"Name a movie with Arnold Schwarzenegger"*), it's easy to delude yourself into thinking that you know this material better than you actually do.
+8) If you don't know the difference between recognition (_"Have you watched the Terminator with Arnold Schwarzenegger?"_) and recall (_"Name a movie with Arnold Schwarzenegger"_), it's easy to delude yourself into thinking that you know this material better than you actually do.
9) A lot of people think "If I don't remember something, I can just Google it". And it's common even among very intelligent people.
@@ -28,9 +35,9 @@ I decided to put together every single reason that I could think of, or that I h
13) Making your own cards instead of using pre-made cards can itself be an entry barrier.
-14) Even if someone is consistent *initially*, if they keep learning tons of new cards, after a few months they will have to do so many reviews that it will become overwhelming, making them quit.
+14) Even if someone is consistent _initially_, if they keep learning tons of new cards, after a few months they will have to do so many reviews that it will become overwhelming, making them quit.
-15) Any reasonably good SR algorithm has some measure of difficulty, and easy cards will be sent further into the future than hard cards. While this is good for efficiency, it means that the user can develop a false sense of "All my material is super mega difficult", because he sees hard cards much more frequently. So there is a conflict between optimal scheduling and user satisfaction. *Again*. And the more leeches the user has, the worse this gets.
+15) Any reasonably good SR algorithm has some measure of difficulty, and easy cards will be sent further into the future than hard cards. While this is good for efficiency, it means that the user can develop a false sense of "All my material is super mega difficult", because he sees hard cards much more frequently. So there is a conflict between optimal scheduling and user satisfaction. _Again_. And the more leeches the user has, the worse this gets.
16) A lot of people feel like flashcards actually **dis**connect them from the big picture.
@@ -42,6 +49,6 @@ I decided to put together every single reason that I could think of, or that I h
20) Customizability vs user friendliness. Sadly, Anki devs, and especially Dae, favor power users over the new users. Figuratively speaking, devs are "selling" user friendliness to "buy" customizability. At a very shitty exchange rate. This tradeoff exists everywhere in software engineering, btw. You can't make software both highly customizable and user friendly at the same time, so you have to find some middle ground. Swing too far in one direction and you'll end up with [The Tyranny of the Marginal User](https://nothinghuman.substack.com/p/the-tyranny-of-the-marginal-user). Swing too far in the other direction and you'll end up with software so complicated that it needs a 200 pages manual. Aka Anki.
+---
-___
### [←Return to homepage](https://expertium.github.io/)
diff --git a/blog.md b/blog.md
new file mode 100644
index 0000000..66b5f71
--- /dev/null
+++ b/blog.md
@@ -0,0 +1,17 @@
+---
+layout: default
+title: Blog
+permalink: /blog
+nav_order: 1
+---
+
+If you use a feed reader, you can subscribe to posts via our
+[Atom feed]({{ site.baseurl }}{% link feed.xml %}).
+
+
diff --git a/index.md b/index.md
index 0b9efb6..e2e3432 100644
--- a/index.md
+++ b/index.md
@@ -1,14 +1,25 @@
+Recent posts
+
+
+ {% assign recent_posts = site.posts | where: "published", true | sort: "date" | reverse | limit: 3 %}
+ {% for post in recent_posts %}
+ -
+ {{ post.title }}
+
+ {% endfor %}
+
+
I write articles about spaced repetition and especially about [FSRS](https://github.com/open-spaced-repetition/fsrs4anki/wiki/ABC-of-FSRS). That's all, end of the intro. Here are the articles, (kinda) sorted from most important to least important:
1. (unfinished)[Benchmark of spaced repetition algorithms](/Benchmark.md). In this article, I analyze results from the [open spaced repetition benchmark repository](https://github.com/open-spaced-repetition/srs-benchmark?tab=readme-ov-file#result), where many modern spaced repetition algorithms are compared based on their ability to predict the probability of recall. This is the most high-effort piece I've ever written. It will be finished when the next major release of Anki comes out.
-3. [A technical explanation of FSRS](/Algorithm.md), where I explain the formulas that are used to calculate the probability of recall.
-4. [Note types to avoid pattern matching](/Avoid_Pattern_Matching.md). In this article, I go over some note types that can help you avoid the "I memorized what the answer *looks* like rather than the actual information" phenomenon as well as allow you to memorize the same amount of information with fewer cards.
-5. [Understanding what retention means in FSRS](/Retention.md). I recommend reading this article if you are confused by terms like "desired retention", "true retention" and "average predicted retention", the latter two can be found in Stats if you have the [FSRS Helper add-on](https://ankiweb.net/shared/info/759844606) installed and press Shift + Left Mouse Click on the Stats button.
-6. [A short analysis of how review time is related to answer buttons](/Buttons.md). Some wonder, "Do people tend to think longer before pressing Again than before pressing Good?". In this article, I answer that question. Spoiler: yes.
I rank this as relatively important simply because you won't find this information anywhere else.
-7. [Abridged history of spaced repetition](/History.md).
-8. [Let's get learning steps wrong!](/Learning_Steps.md) It's much easier than you think.
-9. [Should you lower your maximum interval?](/Max_Interval.md)
-10. [Mass adoption and the perfect UI](/Perfect_UI.md). Can FSRS be easy to use? Yes. But first, we'll need to change ~~some~~ a lot of things.
+2. [A technical explanation of FSRS](/Algorithm.md), where I explain the formulas that are used to calculate the probability of recall.
+3. [Note types to avoid pattern matching](/Avoid_Pattern_Matching.md). In this article, I go over some note types that can help you avoid the "I memorized what the answer _looks_ like rather than the actual information" phenomenon as well as allow you to memorize the same amount of information with fewer cards.
+4. [Understanding what retention means in FSRS](/Retention.md). I recommend reading this article if you are confused by terms like "desired retention", "true retention" and "average predicted retention", the latter two can be found in Stats if you have the [FSRS Helper add-on](https://ankiweb.net/shared/info/759844606) installed and press Shift + Left Mouse Click on the Stats button.
+5. [A short analysis of how review time is related to answer buttons](/Buttons.md). Some wonder, "Do people tend to think longer before pressing Again than before pressing Good?". In this article, I answer that question. Spoiler: yes.
I rank this as relatively important simply because you won't find this information anywhere else.
+6. [Abridged history of spaced repetition](/History.md).
+7. [Let's get learning steps wrong!](/Learning_Steps.md) It's much easier than you think.
+8. [Should you lower your maximum interval?](/Max_Interval.md)
+9. [Mass adoption and the perfect UI](/Perfect_UI.md). Can FSRS be easy to use? Yes. But first, we'll need to change ~~some~~ a lot of things.
A list of all implementations of FSRS in different programming languages, as well as apps that use FSRS (it's not just Anki!): [https://github.com/open-spaced-repetition/awesome-fsrs.](https://github.com/open-spaced-repetition/awesome-fsrs)