pub struct LabelShift {
pub overlap_ratio: f64,
pub familiarity: f64,
pub true_zero_shot_types: Vec<String>,
pub transfer_difficulty: String,
}Expand description
Label shift between training and evaluation entity types.
§Why This Matters
Imagine you trained a model on {PER, ORG, LOC} and then evaluate on
{PERSON, COMPANY, CITY}. Is that zero-shot? Technically yes (new labels).
Practically no (same concepts).
┌─────────────────────────────────────────────────────────────────────────┐
│ THE LABEL SHIFT PROBLEM │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ TRAINING LABELS EVAL LABELS ARE THEY THE SAME? │
│ ─────────────── ─────────── ────────────────── │
│ │
│ PER ───────────────────── PERSON ✓ Obviously (renamed) │
│ ORG ───────────────────── COMPANY ✓ Subset relationship │
│ LOC ───────────────────── CITY ✓ Subset relationship │
│ │
│ ??? ←─────────────────── DISEASE ✗ TRUE ZERO-SHOT! │
│ ??? ←─────────────────── DRUG ✗ TRUE ZERO-SHOT! │
│ │
│ If 80% of eval types have training equivalents, your F1 is inflated. │
└─────────────────────────────────────────────────────────────────────────┘§Embedding Space View
Labels that seem different can be close in embedding space:
EMBEDDING SPACE (2D projection)
───────────────────────────────
PER ●───────────────● PERSON
│
very close in
embedding space
ORG ●─────● COMPANY
LOC ●─────────● CITY
● DISEASE ← Far from all
training types!
● DRUG ← This is TRUE
zero-shot.
F1 on {PERSON, COMPANY, CITY}: 85% (but model "knew" these)
F1 on {DISEASE, DRUG}: 45% (honest zero-shot)§Research Context (arXiv:2412.10121 “Familiarity”)
Key findings from Golde et al. (2024):
- 80%+ label overlap in NuNER/PileNER → inflated F1 scores
- True zero-shot: evaluate only on types NOT in training
- Familiarity = semantic similarity × frequency weighting
§Example
use anno_eval::eval::LabelShift;
let shift = LabelShift {
overlap_ratio: 0.85, // 85% of eval types in train
familiarity: 0.72, // Semantic similarity score
true_zero_shot_types: vec!["DISEASE".into(), "DRUG".into()],
transfer_difficulty: "low".into(),
};
// High overlap = easy transfer, but NOT true zero-shot
assert!(shift.is_inflated());Fields§
§overlap_ratio: f64Fraction of eval types found in training data (exact string match).
familiarity: f64Familiarity score: semantic similarity weighted by frequency. Range: [0, 1]. Higher = more similar training/eval types.
true_zero_shot_types: Vec<String>Entity types in eval NOT present in training (true zero-shot).
transfer_difficulty: StringQualitative difficulty: “low”, “medium”, “high”.
Implementations§
Source§impl LabelShift
impl LabelShift
Sourcepub fn is_inflated(&self) -> bool
pub fn is_inflated(&self) -> bool
Check if F1 scores are likely inflated due to high label overlap.
Threshold from Familiarity paper: >0.8 overlap is concernoing.
Sourcepub fn true_zero_shot_count(&self) -> usize
pub fn true_zero_shot_count(&self) -> usize
Get count of true zero-shot types.
Sourcepub fn from_type_sets(train_types: &[String], eval_types: &[String]) -> Self
pub fn from_type_sets(train_types: &[String], eval_types: &[String]) -> Self
Compute label shift from training and eval type sets.
§Arguments
train_types- Entity types seen during trainingeval_types- Entity types in evaluation benchmark
§Note
This computes both string-match overlap and semantic similarity-based familiarity.
For true semantic similarity, use from_type_sets_with_embeddings() if embeddings are available.
See arXiv:2412.10121 for details.
Sourcepub fn from_type_sets_with_embeddings<F>(
train_types: &[String],
eval_types: &[String],
embedding_fn: F,
) -> Self
pub fn from_type_sets_with_embeddings<F>( train_types: &[String], eval_types: &[String], embedding_fn: F, ) -> Self
Compute label shift with embedding-based familiarity.
§Arguments
train_types- Entity types seen during trainingeval_types- Entity types in evaluation benchmarkembedding_fn- Function that computes embedding for a label name
§Note
This computes true semantic similarity using embeddings, as recommended in the Familiarity paper (arXiv:2412.10121). Familiarity = semantic similarity × frequency weighting.
The embedding function should return a normalized vector (unit length) for cosine similarity.
Trait Implementations§
Source§impl Clone for LabelShift
impl Clone for LabelShift
Source§fn clone(&self) -> LabelShift
fn clone(&self) -> LabelShift
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for LabelShift
impl Debug for LabelShift
Source§impl<'de> Deserialize<'de> for LabelShift
impl<'de> Deserialize<'de> for LabelShift
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl Display for LabelShift
impl Display for LabelShift
Auto Trait Implementations§
impl Freeze for LabelShift
impl RefUnwindSafe for LabelShift
impl Send for LabelShift
impl Sync for LabelShift
impl Unpin for LabelShift
impl UnsafeUnpin for LabelShift
impl UnwindSafe for LabelShift
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> ToCompactString for Twhere
T: Display,
impl<T> ToCompactString for Twhere
T: Display,
Source§fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
ToCompactString::to_compact_string() Read moreSource§fn to_compact_string(&self) -> CompactString
fn to_compact_string(&self) -> CompactString
CompactString. Read moreSource§impl<T> ToStringFallible for Twhere
T: Display,
impl<T> ToStringFallible for Twhere
T: Display,
Source§fn try_to_string(&self) -> Result<String, TryReserveError>
fn try_to_string(&self) -> Result<String, TryReserveError>
ToString::to_string, but without panic on OOM.