Spaces:
Running on Zero
Running on Zero
| import pandas as pd | |
| import numpy as np | |
| import joblib | |
| df = pd.read_parquet('data/processed/dataset_b_features.parquet') | |
| test = df[df['split'] == 'test'].copy() | |
| feats = [ | |
| 'rolling_txn_15m','baseline_txn_15m','velocity_ratio', | |
| 'estimated_fraud_rate_15m','baseline_fraud_rate','estimated_fraud_rate_deviation', | |
| 'amount_deviation','fraud_signal_ratio','estimated_fraud_count_15m', | |
| 'expected_fraud_count_15m','fraud_excess_ratio','volume_deviation', | |
| 'fraud_excess_minus_velocity','amount_shift_indicator' | |
| ] | |
| model = joblib.load('models/spike_model/xgboost_spike_model_v2.joblib') | |
| probs = model.predict_proba(test[feats].values)[:, 1] | |
| test['prob'] = probs | |
| print('Test set threshold sweep:') | |
| for t in [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]: | |
| vol = test[test['scenario_type'] == 'volume_only_spike'] | |
| vol_fpr = np.mean(vol['prob'] >= t) | |
| spk = test[(test['scenario_type'] == 'fraud_spike') & (test['fraud_spike'] == 1)] | |
| spk_rec = np.mean(spk['prob'] >= t) | |
| preds = test[test['prob'] >= t] | |
| prec = np.mean(preds['fraud_spike']) if len(preds) > 0 else 0.0 | |
| f1 = 2 * prec * spk_rec / (prec + spk_rec) if (prec + spk_rec) > 0 else 0.0 | |
| print(f'T={t:.2f} | Vol-only FPR={vol_fpr*100:6.2f}% | Fraud Spike Recall={spk_rec*100:6.2f}% | Precision={prec:6.4f} | F1={f1:6.4f}') | |