{"id":477,"date":"2016-08-02T20:34:10","date_gmt":"2016-08-03T02:34:10","guid":{"rendered":"http:\/\/www.blueraja.com\/blog\/?p=477"},"modified":"2021-05-25T16:25:16","modified_gmt":"2021-05-25T22:25:16","slug":"a-better-spaced-repetition-learning-algorithm-sm2","status":"publish","type":"post","link":"https:\/\/www.blueraja.com\/blog\/477\/a-better-spaced-repetition-learning-algorithm-sm2","title":{"rendered":"A Better Spaced Repetition Learning Algorithm: SM2+"},"content":{"rendered":"<p>By far the most popular algorithm for <a href=\"https:\/\/en.wikipedia.org\/wiki\/Spaced_repetition\">Spaced Repetition<\/a> is <a href=\"https:\/\/www.supermemo.com\/english\/ol\/sm2.htm\">SM2<\/a>.\u00a0 Sites like Anki, Duolingo, Memrise, and Wanikani all chose SM2 over later SM-iterations <em>(eg. <a href=\"https:\/\/www.supermemo.com\/help\/smalg.htm#Algorithm_SM-15\">SM15<\/a>)<\/em> because it is extremely simple, yet effective.\u00a0 Despite that, it still has a number of glaring issues.\u00a0 In this article I explain those issues, and provide a simple way to resolve them.<\/p>\n<h2>Original SM2 Algorithm<\/h2>\n<p>The algorithm determines which items the user must review every day.\u00a0 To do that, it attaches the following data to every review-item:<\/p>\n<ul>\n<li><code>easiness:float<\/code> &#8211; A number\u00a0<span class=\"_Tgc\">\u2265<\/span> 1.3 representing how easy the item is, with 1.3 being the hardest.\u00a0 Defaults to 2.5<\/li>\n<li><code>consecutiveCorrectAnswers:int<\/code> &#8211; How many times in a row the user has correctly answered this item<\/li>\n<li><code>nextDueDate:datetime<\/code> &#8211; The next time this item needs to be reviewed<\/li>\n<\/ul>\n<p>When the user wants to review, every item past its <code>nextDueDate<\/code> is queued.\u00a0 After the user reviews an item, they <em>(or the software)<\/em> give themselves a <code>performanceRating<\/code> on a scale from 0-5 <em>(0=worst, 5=best)<\/em>.\u00a0 Set a cutoff for an answer being &#8220;correct&#8221; <em>(defaults to 3)<\/em>. Then make the following changes to that item:<\/p>\n<p><code>easiness<\/code> += <img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.blueraja.com\/blog\/wp-content\/ql-cache\/quicklatex.com-25272c1ac42c4c87d616dd8171a4a727_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#45;&#48;&#46;&#56;&#32;&#43;&#32;&#48;&#46;&#50;&#56;&#42;&#112;&#101;&#114;&#102;&#111;&#114;&#109;&#97;&#110;&#99;&#101;&#82;&#97;&#116;&#105;&#110;&#103;&#32;&#43;&#32;&#48;&#46;&#48;&#50;&#42;&#112;&#101;&#114;&#102;&#111;&#114;&#109;&#97;&#110;&#99;&#101;&#82;&#97;&#116;&#105;&#110;&#103;&#94;&#50;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"502\" style=\"vertical-align: -4px;\"\/><\/p>\n<p><code>consecutiveCorrectAnswers<\/code> = <img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.blueraja.com\/blog\/wp-content\/ql-cache\/quicklatex.com-605e149e89d7874f9a6de514007a7a1d_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#99;&#97;&#115;&#101;&#115;&#125; &#99;&#111;&#110;&#115;&#101;&#99;&#117;&#116;&#105;&#118;&#101;&#67;&#111;&#114;&#114;&#101;&#99;&#116;&#65;&#110;&#115;&#119;&#101;&#114;&#115;&#43;&#49;&#44;&#32;&#92;&#116;&#101;&#120;&#116;&#123;&#32;&#32;&#32;&#105;&#102;&#32;&#99;&#111;&#114;&#114;&#101;&#99;&#116;&#125;&#32;&#92;&#92; &#48;&#44;&#32;&#92;&#116;&#101;&#120;&#116;&#123;&#32;&#32;&#32;&#105;&#102;&#32;&#105;&#110;&#99;&#111;&#114;&#114;&#101;&#99;&#116;&#125; &#92;&#101;&#110;&#100;&#123;&#99;&#97;&#115;&#101;&#115;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"54\" width=\"349\" style=\"vertical-align: -23px;\"\/><\/p>\n<p><code>nextDueDate<\/code> = <img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.blueraja.com\/blog\/wp-content\/ql-cache\/quicklatex.com-cd970a9579b79d8e1f48c5c7ed23c311_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#99;&#97;&#115;&#101;&#115;&#125; &#92;&#116;&#101;&#120;&#116;&#123;&#110;&#111;&#119;&#32;&#43;&#32;&#36;&#40;&#54;&#42;&#101;&#97;&#115;&#105;&#110;&#101;&#115;&#115;&#94;&#123;&#99;&#111;&#110;&#115;&#101;&#99;&#117;&#116;&#105;&#118;&#101;&#67;&#111;&#114;&#114;&#101;&#99;&#116;&#65;&#110;&#115;&#119;&#101;&#114;&#115;&#45;&#49;&#125;&#41;&#36;&#32;&#100;&#97;&#121;&#115;&#125;&#44;&#32;&#92;&#116;&#101;&#120;&#116;&#123;&#32;&#32;&#32;&#105;&#102;&#32;&#99;&#111;&#114;&#114;&#101;&#99;&#116;&#125;&#32;&#92;&#92; &#92;&#116;&#101;&#120;&#116;&#123;&#110;&#111;&#119;&#32;&#43;&#32;&#49;&#32;&#100;&#97;&#121;&#125;&#44;&#32;&#92;&#116;&#101;&#120;&#116;&#123;&#32;&#32;&#32;&#105;&#102;&#32;&#105;&#110;&#99;&#111;&#114;&#114;&#101;&#99;&#116;&#125; &#92;&#101;&#110;&#100;&#123;&#99;&#97;&#115;&#101;&#115;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"54\" width=\"491\" style=\"vertical-align: -23px;\"\/><\/p>\n<h2>Problems with SM2<\/h2>\n<p>SM2 has a number of issues that limit its usefulness\/effectiveness:<\/p>\n<h4>Problem: Non-generic variable ranges<\/h4>\n<p>The variable ranges are very specific to the original software, Supermemo.\u00a0 <code>easiness<\/code> is a number\u00a0<span class=\"_Tgc\">\u2265<\/span> 1.3, while <code>performanceRating<\/code> is an integer from [0,5]<\/p>\n<h4>Solution<\/h4>\n<p>Normalize <code>easiness<\/code> and <code>performanceRating<\/code> to [0,1].<\/p>\n<p>This requires setting a max value for <code>easiness<\/code>, which I set to 3.0.\u00a0 I also replaced <code>easiness<\/code> with <code>difficulty<\/code>, because it&#8217;s the more natural thing to measure.<\/p>\n<h4>Problem: Too many items per day<\/h4>\n<p>Because every day we do <em>all<\/em> the overdue items, it&#8217;s easy to encounter situations where one day you have only 5 items to review, and the next you have 50.<\/p>\n<h4>Solution<\/h4>\n<p>Only require doing the items that are <em>the most<\/em> overdue.\u00a0 Use &#8220;percentage&#8221; of due-date, rather than number of days, so that 3 days overdue is severe if the review cooldown was 1 day, but not severe if it was 6 months.<\/p>\n<p>This allows review sessions to be small and quick.\u00a0 If the user has time, they can do multiple review sessions in a row.\u00a0 As a bonus, this allows &#8220;almost overdue&#8221; items to be reviewed, if the user has time.<\/p>\n<h4>Problem: Overdue items all treated equally<\/h4>\n<p>If the user completes a month-overdue item correctly, it&#8217;s likely they know it pretty well, so showing it again in 6 days is not helpful.\u00a0 They should get a bonus for correctly getting such overdue items correct.<\/p>\n<p>Additionally, the above problem\/solution allows almost-overdue items to be reviewed.\u00a0 These items should not be given full credit.<\/p>\n<h4>Solution<\/h4>\n<p>Weight the changes in due-date and difficulty by the item&#8217;s percentage overdue.<\/p>\n<h4>Problem: Items learned together are reviewed together<\/h4>\n<p>Items that are learned together and always correctly answered will always be reviewed together at the same time, in the same order.\u00a0 This hinders learning if they&#8217;re related.<\/p>\n<h4>Solution<\/h4>\n<p>Add a small amount of randomness to the algorithm.<\/p>\n<h4>Other adjustments<\/h4>\n<ul>\n<li>The quadratic term in the <code>difficulty<\/code> equation is so small it can be replaced with a simpler linear equation without adversely affecting the algorithm<\/li>\n<li>Anki, Memrise, and others prefer an initial 3 days between due-dates, instead of 6.\u00a0 I&#8217;ve adjusted the equations to use that preference.<\/li>\n<\/ul>\n<h2>The Modified &#8220;SM2+&#8221; Algorithm<\/h2>\n<p>Here is the new algorithm, with all the above improvements in place.<\/p>\n<p>For each review-item, store the following data:<\/p>\n<ul>\n<li><code>difficulty:float<\/code> &#8211; How difficult the item is, from [0.0, 1.0].\u00a0 Defaults to 0.3 <em>(if the software has no way of determining a better default for an item)<\/em><\/li>\n<li><code>daysBetweenReviews:float<\/code> &#8211; How many days should occur between review attempts for this item<\/li>\n<li><code>dateLastReviewed:datetime<\/code> &#8211; The last time this item was reviewed<\/li>\n<\/ul>\n<p>When the user wants to review items, choose the top 10~20 items, ordered descending by <code>percentageOverdue<\/code> <em>(defined below)<\/em>, discarding items reviewed in the past 8 or so hours.<\/p>\n<p>After an item is attempted, choose a <code>performanceRating<\/code> from [0.0, 1.0], with 1.0 being the best.\u00a0 Set a cutoff point for the answer being &#8220;correct&#8221; <em>(default is 0.6)<\/em>. Then set<\/p>\n<p><code>percentOverdue<\/code> = <img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.blueraja.com\/blog\/wp-content\/ql-cache\/quicklatex.com-63a76d9b0cff98d58b099dd1caaa3ac4_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#99;&#97;&#115;&#101;&#115;&#125; &#77;&#105;&#110;&#40;&#50;&#44;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#100;&#97;&#121;&#115;&#40;&#100;&#97;&#116;&#101;&#78;&#111;&#119;&#32;&#45;&#32;&#100;&#97;&#116;&#101;&#76;&#97;&#115;&#116;&#82;&#101;&#118;&#105;&#101;&#119;&#101;&#100;&#41;&#125;&#123;&#100;&#97;&#121;&#115;&#66;&#101;&#116;&#119;&#101;&#101;&#110;&#82;&#101;&#118;&#105;&#101;&#119;&#115;&#125;&#41;&#44;&#32;&#92;&#116;&#101;&#120;&#116;&#123;&#32;&#32;&#32;&#105;&#102;&#32;&#99;&#111;&#114;&#114;&#101;&#99;&#116;&#125;&#92;&#92; &#49;&#44;&#32;&#92;&#116;&#101;&#120;&#116;&#123;&#32;&#32;&#32;&#105;&#102;&#32;&#105;&#110;&#99;&#111;&#114;&#114;&#101;&#99;&#116;&#125; &#92;&#101;&#110;&#100;&#123;&#99;&#97;&#115;&#101;&#115;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"54\" width=\"382\" style=\"vertical-align: -23px;\"\/><\/p>\n<p><code>difficulty<\/code> += <img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.blueraja.com\/blog\/wp-content\/ql-cache\/quicklatex.com-1a2f2b592e3fad4d2d9e04f536f33b2c_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#112;&#101;&#114;&#99;&#101;&#110;&#116;&#79;&#118;&#101;&#114;&#100;&#117;&#101;&#42;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#49;&#55;&#125;&#40;&#56;&#45;&#57;&#42;&#112;&#101;&#114;&#102;&#111;&#114;&#109;&#97;&#110;&#99;&#101;&#82;&#97;&#116;&#105;&#110;&#103;&#41;&#92;&#116;&#101;&#120;&#116;&#123;&#44;&#32;&#99;&#108;&#97;&#109;&#112;&#32;&#116;&#111;&#32;&#91;&#48;&#44;&#49;&#93;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"23\" width=\"507\" style=\"vertical-align: -7px;\"\/><\/p>\n<p><code>difficultyWeight<\/code> = <img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.blueraja.com\/blog\/wp-content\/ql-cache\/quicklatex.com-0f334b6e95df6a6ab362f463b36fa9cd_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#51;&#45;&#49;&#46;&#55;&#42;&#100;&#105;&#102;&#102;&#105;&#99;&#117;&#108;&#116;&#121;\" title=\"Rendered by QuickLaTeX.com\" height=\"17\" width=\"151\" style=\"vertical-align: -4px;\"\/><\/p>\n<p><code>daysBetweenReviews<\/code> *= <img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.blueraja.com\/blog\/wp-content\/ql-cache\/quicklatex.com-e6f1cfa542446b2a7657bd4d43bf4d23_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#99;&#97;&#115;&#101;&#115;&#125; &#49;&#43;&#40;&#100;&#105;&#102;&#102;&#105;&#99;&#117;&#108;&#116;&#121;&#87;&#101;&#105;&#103;&#104;&#116;&#45;&#49;&#41;&#42;&#112;&#101;&#114;&#99;&#101;&#110;&#116;&#79;&#118;&#101;&#114;&#100;&#117;&#101;&#42;&#114;&#97;&#110;&#100;&#40;&#48;&#46;&#57;&#53;&#44;&#49;&#46;&#48;&#53;&#41;&#44;&#32;&#92;&#116;&#101;&#120;&#116;&#123;&#32;&#32;&#32;&#105;&#102;&#32;&#99;&#111;&#114;&#114;&#101;&#99;&#116;&#125;&#92;&#92; &#49;&#47;&#40;&#49;&#43;&#51;&#42;&#100;&#105;&#102;&#102;&#105;&#99;&#117;&#108;&#116;&#121;&#41;&#44;&#32;&#92;&#116;&#101;&#120;&#116;&#123;&#32;&#32;&#32;&#105;&#102;&#32;&#105;&#110;&#99;&#111;&#114;&#114;&#101;&#99;&#116;&#32;&#40;&#109;&#97;&#120;&#32;&#100;&#97;&#121;&#115;&#32;&#61;&#32;&#49;&#41;&#125; &#92;&#101;&#110;&#100;&#123;&#99;&#97;&#115;&#101;&#115;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"54\" width=\"593\" style=\"vertical-align: -23px;\"\/><\/p>\n<h2>Daily Review Sessions<\/h2>\n<p>The above algorithm determines which items to review, but how should you handle the actual review?<\/p>\n<p>That&#8217;s the topic for my next post &#8211; stay tuned!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>By far the most popular algorithm for Spaced Repetition is SM2.\u00a0 Sites like Anki, Duolingo, Memrise, and Wanikani all chose SM2 over later SM-iterations (eg. SM15) because it is extremely simple, yet effective.\u00a0 Despite that, it still has a number of glaring issues.\u00a0 In this article I explain those issues, and provide a simple way [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/posts\/477"}],"collection":[{"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/comments?post=477"}],"version-history":[{"count":62,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/posts\/477\/revisions"}],"predecessor-version":[{"id":560,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/posts\/477\/revisions\/560"}],"wp:attachment":[{"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/media?parent=477"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/categories?post=477"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/tags?post=477"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}