mirror of
https://github.com/ankitects/anki.git
synced 2026-01-13 22:13:58 -05:00
Adjusted loss values
This commit is contained in:
parent
89bafdb47e
commit
e642eb535e
4 changed files with 35 additions and 13 deletions
|
|
@ -360,7 +360,7 @@ message ComputeFsrsParamsRequest {
|
||||||
message ComputeFsrsParamsResponse {
|
message ComputeFsrsParamsResponse {
|
||||||
repeated float params = 1;
|
repeated float params = 1;
|
||||||
uint32 fsrs_items = 2;
|
uint32 fsrs_items = 2;
|
||||||
optional float log_loss = 3;
|
optional bool health_check_passed = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ComputeFsrsParamsFromItemsRequest {
|
message ComputeFsrsParamsFromItemsRequest {
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,18 @@ pub(crate) fn ignore_revlogs_before_ms_from_config(config: &DeckConfig) -> Resul
|
||||||
ignore_revlogs_before_date_to_ms(&config.inner.ignore_revlogs_before_date)
|
ignore_revlogs_before_date_to_ms(&config.inner.ignore_revlogs_before_date)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// r: retention
|
||||||
|
fn log_loss_adjustment(r: f32) -> f32 {
|
||||||
|
0.621 * (4. * r * (1. - r)).powf(0.739)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// r: retention
|
||||||
|
///
|
||||||
|
/// c: review count
|
||||||
|
fn rmse_adjustment(r: f32, c: u32) -> f32 {
|
||||||
|
0.0417 / (r.powf(1.63) - 1.41) + 0.125 / ((c as f32 / 1000.).powf(0.655) + 1.22) + 0.102
|
||||||
|
}
|
||||||
|
|
||||||
impl Collection {
|
impl Collection {
|
||||||
/// Note this does not return an error if there are less than 400 items -
|
/// Note this does not return an error if there are less than 400 items -
|
||||||
/// the caller should instead check the fsrs_items count in the return
|
/// the caller should instead check the fsrs_items count in the return
|
||||||
|
|
@ -77,7 +89,7 @@ impl Collection {
|
||||||
return Ok(ComputeFsrsParamsResponse {
|
return Ok(ComputeFsrsParamsResponse {
|
||||||
params: current_params.to_vec(),
|
params: current_params.to_vec(),
|
||||||
fsrs_items,
|
fsrs_items,
|
||||||
log_loss: None,
|
health_check_passed: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// adapt the progress handler to our built-in progress handling
|
// adapt the progress handler to our built-in progress handling
|
||||||
|
|
@ -149,11 +161,25 @@ impl Collection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let log_loss = if health_check {
|
let health_check_passed = if health_check {
|
||||||
let fsrs = FSRS::new(None)?;
|
let fsrs = FSRS::new(None)?;
|
||||||
fsrs.evaluate_with_time_series_splits(input, |_| true)
|
fsrs.evaluate_with_time_series_splits(input, |_| true)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|eval| eval.log_loss)
|
.map(|eval| {
|
||||||
|
let r = items.iter().fold(0, |p, item| {
|
||||||
|
p + (item
|
||||||
|
.reviews
|
||||||
|
.last()
|
||||||
|
.map(|reviews| reviews.rating)
|
||||||
|
.unwrap_or(0)
|
||||||
|
> 1) as u32
|
||||||
|
}) as f32
|
||||||
|
/ fsrs_items as f32;
|
||||||
|
let adjusted_log_loss = eval.log_loss / log_loss_adjustment(r);
|
||||||
|
let adjusted_rmse = eval.rmse_bins / rmse_adjustment(r, fsrs_items);
|
||||||
|
|
||||||
|
adjusted_log_loss < 1.10 && adjusted_rmse < 1.58
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
@ -161,7 +187,7 @@ impl Collection {
|
||||||
Ok(ComputeFsrsParamsResponse {
|
Ok(ComputeFsrsParamsResponse {
|
||||||
params,
|
params,
|
||||||
fsrs_items,
|
fsrs_items,
|
||||||
log_loss,
|
health_check_passed,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -376,7 +376,7 @@ impl crate::services::BackendSchedulerService for Backend {
|
||||||
Ok(ComputeFsrsParamsResponse {
|
Ok(ComputeFsrsParamsResponse {
|
||||||
params,
|
params,
|
||||||
fsrs_items,
|
fsrs_items,
|
||||||
log_loss: None,
|
health_check_passed: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
const defaults = state.defaults;
|
const defaults = state.defaults;
|
||||||
const fsrsReschedule = state.fsrsReschedule;
|
const fsrsReschedule = state.fsrsReschedule;
|
||||||
const daysSinceLastOptimization = state.daysSinceLastOptimization;
|
const daysSinceLastOptimization = state.daysSinceLastOptimization;
|
||||||
const logLossBadThreshold = 0.5;
|
|
||||||
|
|
||||||
$: lastOptimizationWarning =
|
$: lastOptimizationWarning =
|
||||||
$daysSinceLastOptimization > 30 ? tr.deckConfigTimeToOptimize() : "";
|
$daysSinceLastOptimization > 30 ? tr.deckConfigTimeToOptimize() : "";
|
||||||
|
|
@ -191,13 +190,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
)) ||
|
)) ||
|
||||||
resp.params.length === 0;
|
resp.params.length === 0;
|
||||||
|
|
||||||
const highLogLoss =
|
const health_check_passed =
|
||||||
resp.logLoss && resp.logLoss > logLossBadThreshold;
|
resp.healthCheckPassed && !resp.healthCheckPassed;
|
||||||
|
|
||||||
if (resp.logLoss) {
|
if (health_check_passed) {
|
||||||
console.log(`FSRS-test-train-split-log-loss = ${resp.logLoss}`);
|
|
||||||
}
|
|
||||||
if (highLogLoss) {
|
|
||||||
setTimeout(() => alert(tr.deckConfigFsrsBadFitWarning()));
|
setTimeout(() => alert(tr.deckConfigFsrsBadFitWarning()));
|
||||||
} else if (already_optimal) {
|
} else if (already_optimal) {
|
||||||
const msg = resp.fsrsItems
|
const msg = resp.fsrsItems
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue