Given the card’s history, we can either store or re-calculate the probability of recall predicted by FSRS, and then use the Poisson binomial distribution to calculate the probability of a given number of successes.
I am not even going to try to understand the math with complex numbers, but the usage is actually fairly simple. You just give it a list of probabilities for each trial and the number of successes, and then you can calculate the probability of this many successes or even fewer.
Example:p = np.asarray([0.9, 0.85, 0.95, 0.92, 0.87])
n_succ = 2
This gives me a p-value of 0.836%. So if a card has been reviewed 5 times with these probabilities (note that the order doesn’t matter) there is a 0.836% chance that 2 or fewer reviews will be successful.
We can identify leeches with as few as two or three reviews!
For example, if the probabilities of recall are 90%, 92% and 93%, then the probability of getting the card right zero times is 0.056%. The probability of getting the card correct once or zero times is 1.948%.
The higher desired retention, the higher the probabilities, the faster we can identify leeches. At DR=95% we can identify leeches with merely 2 reviews! Btw, the probability of 0 successes if both reviews had a 95% of success is 0.5%.
Btw, I think 1% is a reasonable cutoff. If a card has been failed so much that the chances of it happening (or having even more fails) normally are <1%, I think it’s most likely a leech.
EDIT: I came up with a good way to correct the threshold to ensure that we don’t tag too many cards, but that is beyond the scope of this topic.
There are 2 challenges:
- Implementing this mathematical function in Rust.
- Storing or re-calculating R for every review.
Then we can add a “Automatic leech detection” button here as an alternative to “Leech threshold” when FSRS is enabled.
Now the big question is: do we want a “Recalculate leeches” button if automatic leech detection is enabled?
Since changing FSRS parameters will change retrievability at the time of the review, which in turn can change whether the card counts as a leech or no.
Also, I asked Claude 3.7 Thinking to re-write it in Rust and remove the calculation of p-values (I calculate them from the PMF) and CDF, leaving only PMF. Idk if it’s any good, but so far Claude 3.7 Thinking has been really freaking good, at least for Python.
Btw, this repo uses Fast Fourier Transform to calculate the probabilities approxiamtely, but me and Alex tested using the exact (combinatorics) method and found that for n=64 reviews it’s fast enough that we don’t need FFT, so the Rust code uses the exact approach.