feat: seeded transcription-error injection + Recall@k
This commit is contained in:
+39
-1
@@ -1 +1,39 @@
|
||||
// implemented in a later task
|
||||
use rand::rngs::StdRng;
|
||||
use rand::{Rng, SeedableRng};
|
||||
|
||||
/// Inject realistic transcription errors deterministically (seeded):
|
||||
/// char drop, adjacent swap, umlaut flattening, digit transposition.
|
||||
pub fn inject_errors(text: &str, rate: f64, seed: u64) -> String {
|
||||
let mut rng = StdRng::seed_from_u64(seed);
|
||||
let mut chars: Vec<char> = text.chars().collect();
|
||||
let n = chars.len();
|
||||
let mut i = 0;
|
||||
while i < chars.len() {
|
||||
if rng.gen::<f64>() < rate {
|
||||
match rng.gen_range(0..4) {
|
||||
0 => { chars.remove(i); continue; } // drop
|
||||
1 => { if i + 1 < chars.len() { chars.swap(i, i + 1); } } // swap
|
||||
2 => { // flatten umlaut
|
||||
chars[i] = match chars[i] {
|
||||
'ä' => 'a', 'ö' => 'o', 'ü' => 'u', 'ß' => 's',
|
||||
other => other,
|
||||
};
|
||||
}
|
||||
_ => { // digit transpose
|
||||
if chars[i].is_ascii_digit() && i + 1 < chars.len()
|
||||
&& chars[i + 1].is_ascii_digit() {
|
||||
chars.swap(i, i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
let _ = n;
|
||||
chars.into_iter().collect()
|
||||
}
|
||||
|
||||
/// 1.0 if `expected` appears in the first k predictions, else 0.0.
|
||||
pub fn recall_at_k(predicted: &[String], expected: &str, k: usize) -> f64 {
|
||||
if predicted.iter().take(k).any(|p| p == expected) { 1.0 } else { 0.0 }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
use alpha_id::eval::{inject_errors, recall_at_k};
|
||||
|
||||
#[test]
|
||||
fn injection_is_deterministic_for_seed() {
|
||||
let a = inject_errors("Diabetes mellitus Typ 2", 0.3, 42);
|
||||
let b = inject_errors("Diabetes mellitus Typ 2", 0.3, 42);
|
||||
assert_eq!(a, b);
|
||||
assert_ne!(a, "Diabetes mellitus Typ 2"); // some corruption at rate 0.3
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recall_counts_hit_within_k() {
|
||||
let predicted = vec!["E11.9".to_string(), "I10.90".to_string(), "J45.0".to_string()];
|
||||
assert_eq!(recall_at_k(&predicted, "I10.90", 5), 1.0);
|
||||
assert_eq!(recall_at_k(&predicted, "I10.90", 1), 0.0);
|
||||
assert_eq!(recall_at_k(&predicted, "Z99.9", 5), 0.0);
|
||||
}
|
||||
Reference in New Issue
Block a user