ExistedYear's picture
scamshield slim - code only, weights via model repo
77c5607
Raw History Blame Contribute Delete
4.18 kB
import torch
import os
import sys
from sklearn.metrics import classification_report, confusion_matrix, f1_score, accuracy_score
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from utils.data_loader import load_dataset, split_dataset
from predictor import SmishingPredictor
from adversarial.evasion import run_adversarial_evaluation
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
CHECKPOINT = "best_model.pt"
def main():
if not os.path.exists(CHECKPOINT):
print(f"Error: Model checkpoint '{CHECKPOINT}' not found. Run train.py first.")
return
print("Loading dataset...")
df = load_dataset()
train_df, val_df, test_df = split_dataset(df)
print("Loading model...")
predictor = SmishingPredictor(CHECKPOINT)
print("Evaluating on test set...")
test_messages = test_df['message'].tolist()
test_labels = test_df['label'].tolist()
predictions = []
for msg in test_messages:
result = predictor.predict(msg)
predictions.append(1 if result['label'] == 'spam' else 0)
print("\n" + "="*60)
print("TEST SET RESULTS β€” SmishingDetector (XLM-RoBERTa + URL Fusion)")
print("="*60)
print("\nClassification Report:")
print(classification_report(test_labels, predictions, target_names=['ham', 'spam']))
cm = confusion_matrix(test_labels, predictions)
print("Confusion Matrix:")
print(cm)
fpr = cm[0][1] / (cm[0][0] + cm[0][1]) if (cm[0][0] + cm[0][1]) > 0 else 0
fnr = cm[1][0] / (cm[1][0] + cm[1][1]) if (cm[1][0] + cm[1][1]) > 0 else 0
print(f"False Positive Rate: {fpr:.4f} (ham flagged as spam)")
print(f"False Negative Rate: {fnr:.4f} (spam missed)")
test_acc = (sum(1 for p, t in zip(predictions, test_labels) if p == t) / len(test_labels))
test_f1 = f1_score(test_labels, predictions, zero_division=0)
print("\n" + "="*60)
print("RESULTS SUMMARY")
print("="*60)
print(f"{'Metric':<25} {'Value':<20}")
print("-"*45)
print(f"{'Accuracy':<25} {f'{test_acc*100:.2f}%':<20}")
print(f"{'F1 (spam)':<25} {f'{test_f1:.4f}':<20}")
print(f"{'False Positive Rate':<25} {f'{fpr*100:.2f}%':<20}")
print("\n" + "="*60)
print("ADVERSARIAL ROBUSTNESS")
print("="*60)
adversarial_results = run_adversarial_evaluation(predictor, test_df, spam_only=True)
print(f"{'Attack':<15} {'Original F1':<15} {'Attacked F1':<15} {'Drop':<10}")
print("-"*55)
for _, row in adversarial_results.iterrows():
print(f"{row['attack_type']:<15} {row['original_f1']:<15.2f} {row['attacked_f1']:<15.2f} {row['accuracy_drop']:<10.2f}")
# ── Multilingual evaluation ───────────────────────────────────────────────
print("\n" + "="*60)
print("MULTILINGUAL EVALUATION")
print("="*60)
print("Evaluating model on Hindi/Hinglish held-out test data...")
try:
from utils.multilingual_loader import load_all_multilingual_test_data
lang_data = load_all_multilingual_test_data()
print(f"\n{'Language':<12} {'Accuracy':<12} {'F1':<10} {'FPR':<10}")
print("-"*45)
for lang_name, lang_df in lang_data.items():
if len(lang_df) == 0:
continue
lang_messages = lang_df['message'].tolist()
lang_labels = lang_df['label'].tolist()
lang_preds = [1 if predictor.predict(m)['label'] == 'spam' else 0
for m in lang_messages]
lang_acc = accuracy_score(lang_labels, lang_preds)
lang_f1 = f1_score(lang_labels, lang_preds, zero_division=0)
lang_cm = confusion_matrix(lang_labels, lang_preds)
lang_fpr = lang_cm[0][1] / (lang_cm[0][0] + lang_cm[0][1]) \
if (lang_cm[0][0] + lang_cm[0][1]) > 0 else 0
print(f"{lang_name:<12} {lang_acc*100:<12.2f} {lang_f1:<10.4f} {lang_fpr*100:<10.2f}")
except Exception as e:
print(f"Multilingual evaluation failed: {e}")
print("\nEvaluation complete!")
if __name__ == "__main__":
main()