From 9a3494c11b32e3dc38f3eb0491e2e8e75fa23951 Mon Sep 17 00:00:00 2001 From: user1823 <92206575+user1823@users.noreply.github.com> Date: Fri, 26 Jul 2024 17:21:42 +0530 Subject: [PATCH 1/6] Fix/set mean reversion target to D0(4) Supersedes and closes https://github.com/open-spaced-repetition/fsrs-optimizer/pull/123 --- src/fsrs_optimizer/fsrs_optimizer.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/fsrs_optimizer/fsrs_optimizer.py b/src/fsrs_optimizer/fsrs_optimizer.py index 3c13096..7ad7b1f 100644 --- a/src/fsrs_optimizer/fsrs_optimizer.py +++ b/src/fsrs_optimizer/fsrs_optimizer.py @@ -95,9 +95,13 @@ def stability_short_term(self, state: Tensor, rating: Tensor) -> Tensor: new_s = state[:, 0] * torch.exp(self.w[17] * (rating - 3 + self.w[18])) return new_s + def init_d(self, rating: Tensor) -> Tensor: + new_d = self.w[4] - torch.exp(self.w[5] * (X[:, 1] - 1)) + 1 + return new_d + def next_d(self, state: Tensor, rating: Tensor) -> Tensor: new_d = state[:, 1] - self.w[6] * (rating - 3) - new_d = self.mean_reversion(self.w[4], new_d) + new_d = self.mean_reversion(init_d(4), new_d) return new_d def step(self, X: Tensor, state: Tensor) -> Tensor: @@ -113,7 +117,7 @@ def step(self, X: Tensor, state: Tensor) -> Tensor: # first learn, init memory states new_s = torch.ones_like(state[:, 0]) new_s[index[0]] = self.w[index[1]] - new_d = self.w[4] - torch.exp(self.w[5] * (X[:, 1] - 1)) + 1 + new_d = init_d(X[:, 1]) new_d = new_d.clamp(1, 10) else: r = power_forgetting_curve(X[:, 0], state[:, 0]) From 281b071908070cb6ef348e33176ee384b0d48f68 Mon Sep 17 00:00:00 2001 From: user1823 <92206575+user1823@users.noreply.github.com> Date: Fri, 26 Jul 2024 18:18:57 +0530 Subject: [PATCH 2/6] Update fsrs_optimizer.py --- src/fsrs_optimizer/fsrs_optimizer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsrs_optimizer/fsrs_optimizer.py b/src/fsrs_optimizer/fsrs_optimizer.py index 7ad7b1f..f054444 100644 --- a/src/fsrs_optimizer/fsrs_optimizer.py +++ b/src/fsrs_optimizer/fsrs_optimizer.py @@ -101,7 +101,7 @@ def init_d(self, rating: Tensor) -> Tensor: def next_d(self, state: Tensor, rating: Tensor) -> Tensor: new_d = state[:, 1] - self.w[6] * (rating - 3) - new_d = self.mean_reversion(init_d(4), new_d) + new_d = self.mean_reversion(self.init_d(4), new_d) return new_d def step(self, X: Tensor, state: Tensor) -> Tensor: @@ -117,7 +117,7 @@ def step(self, X: Tensor, state: Tensor) -> Tensor: # first learn, init memory states new_s = torch.ones_like(state[:, 0]) new_s[index[0]] = self.w[index[1]] - new_d = init_d(X[:, 1]) + new_d = self.init_d(X[:, 1]) new_d = new_d.clamp(1, 10) else: r = power_forgetting_curve(X[:, 0], state[:, 0]) From 40376ed1bdafa9cb2884825cae15ca917ef9fb8e Mon Sep 17 00:00:00 2001 From: Jarrett Ye Date: Fri, 26 Jul 2024 21:28:56 +0800 Subject: [PATCH 3/6] fix X not defined --- src/fsrs_optimizer/fsrs_optimizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsrs_optimizer/fsrs_optimizer.py b/src/fsrs_optimizer/fsrs_optimizer.py index f054444..fc2d83b 100644 --- a/src/fsrs_optimizer/fsrs_optimizer.py +++ b/src/fsrs_optimizer/fsrs_optimizer.py @@ -96,7 +96,7 @@ def stability_short_term(self, state: Tensor, rating: Tensor) -> Tensor: return new_s def init_d(self, rating: Tensor) -> Tensor: - new_d = self.w[4] - torch.exp(self.w[5] * (X[:, 1] - 1)) + 1 + new_d = self.w[4] - torch.exp(self.w[5] * (rating - 1)) + 1 return new_d def next_d(self, state: Tensor, rating: Tensor) -> Tensor: From 491c95c430c77e80e3ed826c79b04eed398a9642 Mon Sep 17 00:00:00 2001 From: user1823 <92206575+user1823@users.noreply.github.com> Date: Fri, 26 Jul 2024 20:05:52 +0530 Subject: [PATCH 4/6] Update fsrs_simulator.py --- src/fsrs_optimizer/fsrs_simulator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsrs_optimizer/fsrs_simulator.py b/src/fsrs_optimizer/fsrs_simulator.py index 20d410c..aee5035 100644 --- a/src/fsrs_optimizer/fsrs_simulator.py +++ b/src/fsrs_optimizer/fsrs_simulator.py @@ -124,7 +124,7 @@ def init_d(rating): def next_d(d, rating): new_d = d - w[6] * (rating - 3) - new_d = mean_reversion(w[4], new_d) + new_d = mean_reversion(init_d(4), new_d) return np.clip(new_d, 1, 10) def mean_reversion(init, current): From fc2dad8e5a6f5cbd29f8fbf743a4d41f0d7d6194 Mon Sep 17 00:00:00 2001 From: Jarrett Ye Date: Fri, 26 Jul 2024 22:50:50 +0800 Subject: [PATCH 5/6] decouple init_d_with_short_term --- src/fsrs_optimizer/fsrs_simulator.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/fsrs_optimizer/fsrs_simulator.py b/src/fsrs_optimizer/fsrs_simulator.py index aee5035..e0454c4 100644 --- a/src/fsrs_optimizer/fsrs_simulator.py +++ b/src/fsrs_optimizer/fsrs_simulator.py @@ -117,9 +117,11 @@ def stability_short_term(s, init_rating=None): return new_s def init_d(rating): - new_d = w[4] - np.exp(w[5] * (rating - 1)) + 1 + return w[4] - np.exp(w[5] * (rating - 1)) + 1 + + def init_d_with_short_term(rating): rating_offset = np.choose(rating - 1, first_rating_offset) - new_d -= w[6] * rating_offset + new_d = init_d(rating) - w[6] * rating_offset return np.clip(new_d, 1, 10) def next_d(d, rating): @@ -202,7 +204,7 @@ def mean_reversion(init, current): card_table[col["stability"]][true_learn], init_rating=card_table[col["rating"]][true_learn].astype(int), ) - card_table[col["difficulty"]][true_learn] = init_d( + card_table[col["difficulty"]][true_learn] = init_d_with_short_term( card_table[col["rating"]][true_learn].astype(int) ) From b756a4587476f92bc27e511f1a254959882aad6b Mon Sep 17 00:00:00 2001 From: Jarrett Ye Date: Fri, 26 Jul 2024 22:58:38 +0800 Subject: [PATCH 6/6] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index da1ce20..5e160be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "FSRS-Optimizer" -version = "5.0.2" +version = "5.0.3" readme = "README.md" dependencies = [ "matplotlib>=3.7.0",