Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set mean reversion target to D0(4) #124

Merged
merged 6 commits into from
Jul 27, 2024

Conversation

user1823
Copy link
Contributor

Supersedes and closes #123

Coding it like this will allow tweaking the formula further without needing to change the code at two places.

@user1823
Copy link
Contributor Author

By the way, shouldn't the simulator import the definitions from fsrs_optimizer.py instead of defining them again?

def stability_after_success(s, r, d, rating):
hard_penalty = np.where(rating == 2, w[15], 1)
easy_bonus = np.where(rating == 4, w[16], 1)
return np.maximum(
0.01,
s
* (
1
+ np.exp(w[8])
* (11 - d)
* np.power(s, -w[9])
* (np.exp((1 - r) * w[10]) - 1)
* hard_penalty
* easy_bonus
),
)
def stability_after_failure(s, r, d):
return np.maximum(
0.01,
np.minimum(
w[11]
* np.power(d, -w[12])
* (np.power(s + 1, w[13]) - 1)
* np.exp((1 - r) * w[14]),
s,
),
)
def stability_short_term(s, init_rating=None):
if init_rating is not None:
rating_offset = np.choose(init_rating - 1, first_rating_offset)
session_len = np.choose(init_rating - 1, first_session_len)
else:
rating_offset = forget_rating_offset
session_len = forget_session_len
new_s = s * np.exp(w[17] * (rating_offset + session_len * w[18]))
return new_s
def init_d(rating):
new_d = w[4] - np.exp(w[5] * (rating - 1)) + 1
rating_offset = np.choose(rating - 1, first_rating_offset)
new_d -= w[6] * rating_offset
return np.clip(new_d, 1, 10)
def next_d(d, rating):
new_d = d - w[6] * (rating - 3)
new_d = mean_reversion(w[4], new_d)
return np.clip(new_d, 1, 10)
def mean_reversion(init, current):
return w[7] * init + (1 - w[7]) * current

@L-M-Sherlock
Copy link
Member

Due to type inference problem, it's hard to reuse this function between optimizer and simulator.

By the way, you forget to call the member function as self.init_d.

@user1823
Copy link
Contributor Author

By the way, you forget to call the member function as self.init_d.

Thanks. If you don't mind, can you briefly explain what is the difference between self.init_d and init_d?

@user1823
Copy link
Contributor Author

Due to type inference problem, it's hard to reuse this function between optimizer and simulator.

Then, should I make the corrections in the simulator too?

@L-M-Sherlock
Copy link
Member

Thanks. If you don't mind, can you briefly explain what is the difference between self.init_d and init_d?

The init_d function is defined under the class FSRS, so it's the member method. It's a concept from object-oriented programming.

Then, should I make the corrections in the simulator too?

Sure, please. I will check it later.

@user1823
Copy link
Contributor Author

user1823 commented Jul 26, 2024

I have edited the simulator too.

But, I don't really understand what is rating_offset.

def init_d(rating):
new_d = w[4] - np.exp(w[5] * (rating - 1)) + 1
rating_offset = np.choose(rating - 1, first_rating_offset)
new_d -= w[6] * rating_offset
return np.clip(new_d, 1, 10)

Also, there is one inconsistency. In the optimizer, mean reversion is using the unclamped value of D0(4). But, in the simulator, mean reversion is using the clamped value of D0(4). Which one do you think is more appropriate?

@L-M-Sherlock
Copy link
Member

I make them consistent in the last commit. rating_offset is hard to explain. In short, it's used to simulate the effect of short-term reviews.

@Expertium
Copy link
Contributor

Expertium commented Jul 26, 2024

Rating offset is basically "average grade of same-day reviews, minus 3".
For example, if you pressed Again and Hard, that's 1 and 2. (1+2)/2 = 1.5. So the average is 1.5. 1.5-3=-1.5. -1.5 is the offset.
EDIT: I'm confused, seems like in this case it's not minus 3, but minus 1 instead. Well, hopefully LMSherlock can explain it better.

@user1823
Copy link
Contributor Author

OK, LGTM.

Note that this PR doesn't include updates to the default parameters from #123.

@L-M-Sherlock
Copy link
Member

EDIT: I'm confused, seems like in this case it's not minus 3, but minus 1 instead. Well, hopefully LMSherlock can explain it better.

image

Any problem?

@user1823 user1823 changed the title Fix/set mean reversion target to D0(4) Set mean reversion target to D0(4) Jul 26, 2024
@user1823
Copy link
Contributor Author

user1823 commented Jul 26, 2024

I just realized that this is not a bug fix and you deliberately used D0(1) for mean reversion previously (Found out by reading the Wiki page).

So, have you tried using D0(3) to see if it gives better results?

@Expertium
Copy link
Contributor

We recently tried D0(1) vs D0(3) vs D0(4), and they all give almost the same results. RMSE differs in the 4 digit after the decimal point. So LMSherlock decided to go with D0(4)

Copy link
Member

@L-M-Sherlock L-M-Sherlock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@L-M-Sherlock L-M-Sherlock added this pull request to the merge queue Jul 27, 2024
Merged via the queue into open-spaced-repetition:main with commit 66d4695 Jul 27, 2024
1 check passed
L-M-Sherlock added a commit to open-spaced-repetition/srs-benchmark that referenced this pull request Jul 27, 2024
ishiko732 added a commit to open-spaced-repetition/ts-fsrs that referenced this pull request Jul 27, 2024
@user1823 user1823 deleted the patch-1 branch July 27, 2024 07:00
L-M-Sherlock pushed a commit to open-spaced-repetition/ts-fsrs that referenced this pull request Jul 27, 2024
* Set mean reversion target to D0(4)

open-spaced-repetition/fsrs-optimizer#124

* test/update test

* update default parameters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants