fingerprint
Concept Overview
Section titled “Concept Overview”Model fingerprinting decomposes a fitted model’s behaviour into a linear effect, a non-linear effect and pairwise interaction effects per feature, by sweeping each feature across a grid and measuring how the prediction moves. The result describes what the model learned rather than how well it scored — two models with identical accuracy can have entirely different fingerprints, and only one of them may be relying on something that will still be there next quarter.
When to Use
Section titled “When to Use”Use it after fitting and before deploying, and again on every retrain: comparing fingerprints across retrains is a drift signal that accuracy metrics do not give you. Use the pairwise effects to find interaction risk, since a large pairwise term means the model’s response to one feature depends on another, which makes its extrapolation fragile. It works with any model — implement RegressionPredictor or ClassificationPredictor and pass it to fit.
Mathematical Foundations
Section titled “Mathematical Foundations”Partial Effect
Section titled “Partial Effect”
Pairwise Interaction
Section titled “Pairwise Interaction”
Usage Examples
Section titled “Usage Examples”Create regression fingerprint
Section titled “Create regression fingerprint”use openquant::fingerprint::{RegressionModelFingerprint, RegressionPredictor};
// Fingerprinting is model-agnostic: anything that can predict will do.struct LinearModel { beta: Vec<f64>,}impl RegressionPredictor for LinearModel { fn predict(&self, x: &[Vec<f64>]) -> Vec<f64> { x.iter() .map(|row| row.iter().zip(self.beta.iter()).map(|(v, b)| v * b).sum()) .collect() }}
let model = LinearModel { beta: vec![1.5, -0.5] };let x: Vec<Vec<f64>> = (0..50).map(|i| vec![i as f64 / 50.0, ((i % 5) as f64) / 5.0]).collect();
// new() takes no arguments; the model and data go to fit(), which needs &mut self.// num_values is the partial-dependence grid resolution.let mut fingerprint = RegressionModelFingerprint::new();fingerprint.fit(&model, &x, 10, Some(&[(0, 1)]))?;
// The accessor is get_effects(), returning (linear, non-linear, optional pairwise).let (linear, non_linear, pairwise) = fingerprint.get_effects()?;println!("linear={:?}", linear.norm);println!("non_linear={:?}", non_linear.norm);println!("pairwise={:?}", pairwise.map(|p| p.norm.clone()));API Reference
Section titled “API Reference”Rust API
Section titled “Rust API”RegressionModelFingerprintClassificationModelFingerprintEffectPairwiseEffect
Risk Notes and Caveats
Section titled “Risk Notes and Caveats”- Compare fingerprints across retrains for drift detection.
- Use pairwise effects to detect hidden interaction risk.