Text Classification
Transformers
Safetensors
English
modernbert
cyber-threat-intelligence
mitre-attack
multi-label-classification
defensive-security
blue-team
threat-intelligence
text-embeddings-inference
Instructions to use ctokx/cti-attack-mapper-modernbert with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use ctokx/cti-attack-mapper-modernbert with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="ctokx/cti-attack-mapper-modernbert")# Load model directly from transformers import AutoTokenizer, AutoModelForSequenceClassification tokenizer = AutoTokenizer.from_pretrained("ctokx/cti-attack-mapper-modernbert") model = AutoModelForSequenceClassification.from_pretrained("ctokx/cti-attack-mapper-modernbert", device_map="auto") - Notebooks
- Google Colab
- Kaggle
| """Run the non-neural baselines on both split schemes. | |
| python scripts/02_run_baselines.py | |
| """ | |
| import sys | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) | |
| import numpy as np # noqa: E402 | |
| from cti_attack import baselines, data, evaluate # noqa: E402 | |
| def run_scheme(scheme: str, labels: list[str]) -> dict: | |
| print(f"\n{'=' * 62}\n split scheme: {scheme}\n{'=' * 62}") | |
| tr = data.load_split(scheme, "train") | |
| dv = data.load_split(scheme, "dev") | |
| te = data.load_split(scheme, "test") | |
| Ytr, Ydv, Yte = (evaluate.to_matrix(x, labels) for x in (tr, dv, te)) | |
| txt_tr = [r["sentence"] for r in tr] | |
| txt_dv = [r["sentence"] for r in dv] | |
| txt_te = [r["sentence"] for r in te] | |
| results = {} | |
| # ---- frequency prior ------------------------------------------------- | |
| dev_s = baselines.frequency_scores(Ytr, len(dv)) | |
| test_s = baselines.frequency_scores(Ytr, len(te)) | |
| results["frequency"] = _score("frequency", Ydv, dev_s, Yte, test_s, labels) | |
| # ---- ATT&CK keyword match ------------------------------------------- | |
| dev_s = baselines.keyword_scores(txt_dv, labels) | |
| test_s = baselines.keyword_scores(txt_te, labels) | |
| results["keyword"] = _score("keyword", Ydv, dev_s, Yte, test_s, labels) | |
| # ---- TF-IDF + one-vs-rest logistic regression ------------------------ | |
| print(" fitting tfidf_lr (49 one-vs-rest classifiers) …") | |
| s = baselines.tfidf_lr_scores(txt_tr, Ytr, {"dev": txt_dv, "test": txt_te}) | |
| results["tfidf_lr"] = _score("tfidf_lr", Ydv, s["dev"], Yte, s["test"], labels) | |
| return results | |
| def _score(name, Ydv, dev_scores, Yte, test_scores, labels) -> dict: | |
| gt, _ = evaluate.tune_global_threshold(Ydv, dev_scores) | |
| pct = evaluate.tune_per_class_thresholds(Ydv, dev_scores) | |
| rep_g = evaluate.evaluate(Yte, evaluate.apply_thresholds(test_scores, gt), labels) | |
| rep_p = evaluate.evaluate(Yte, evaluate.apply_thresholds(test_scores, pct), labels) | |
| print(f" {name:11} global t={gt:<5} macro-F1={rep_g.macro_f1:.4f} " | |
| f"micro-F1={rep_g.micro_f1:.4f} | per-class macro-F1={rep_p.macro_f1:.4f} " | |
| f"micro-F1={rep_p.micro_f1:.4f}") | |
| return { | |
| "global_threshold": {"threshold": gt, **rep_g.as_dict()}, | |
| "per_class_threshold": { | |
| "thresholds": {l: float(t) for l, t in zip(labels, pct)}, | |
| **rep_p.as_dict(), | |
| }, | |
| } | |
| def main() -> None: | |
| labels = data.load_labels() | |
| all_results = {} | |
| for scheme in ("document", "random"): | |
| all_results[scheme] = run_scheme(scheme, labels) | |
| evaluate.save_report("baselines", scheme, all_results[scheme]) | |
| print(f"\n{'=' * 62}\n leakage gap (test macro-F1, per-class thresholds)\n{'=' * 62}") | |
| for name in ("frequency", "keyword", "tfidf_lr"): | |
| d = all_results["document"][name]["per_class_threshold"]["macro_f1"] | |
| r = all_results["random"][name]["per_class_threshold"]["macro_f1"] | |
| print(f" {name:11} document={d:.4f} random={r:.4f} " | |
| f"inflation={r - d:+.4f} ({(r / d - 1) * 100 if d else float('nan'):+.1f}%)") | |
| if __name__ == "__main__": | |
| main() | |