File size: 6,603 Bytes
4e766eb
aaa8848
4e766eb
 
 
 
 
 
 
 
 
 
 
 
 
 
1b9d3c8
4e766eb
 
 
76e875b
4e766eb
76e875b
4e766eb
 
 
 
 
da04603
 
 
4e766eb
1b9d3c8
da04603
 
4e766eb
 
da04603
4e766eb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
da04603
4e766eb
 
 
 
76e875b
4e766eb
 
 
 
 
 
 
 
 
 
 
 
 
 
da04603
4e766eb
 
 
 
 
 
 
 
 
da04603
4e766eb
 
 
 
 
 
da04603
 
 
 
 
 
 
 
4e766eb
 
 
 
 
 
 
 
76e875b
da04603
76e875b
4e766eb
76e875b
4e766eb
 
 
 
 
 
 
ba0817b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
---
license: apache-2.0
library_name: pytorch
tags:
  - cti
  - attack-classification
  - mitre-attack
  - cybersecurity
  - text-classification
  - multi-label-classification
  - asymmetric-loss
language:
  - en
base_model: ibm-research/CTI-BERT
---

# CASSANDRA — ASL configuration on TRAM2

Fine-tuned CTI-BERT models for extracting MITRE ATT&CK techniques from cyber threat intelligence (CTI) reports. This repository contains the **ASL configuration** of the CASSANDRA recipe trained on **TRAM2** (50 ATT&CK sub-techniques), comprising **6 ensemble members** trained with seeds {42, 123, 456, 789, 2024, 3141}.

This is the highest-F1 configuration in the CASSANDRA paper on TRAM2. The asymmetric loss + 6-seed ensemble adds +3.30 F1 over the BCE 3-seed configuration ([`cassandra-bce-tram2`](https://huggingface.co/cassandra-anon/cassandra-bce-tram2)).

> Anonymous artifact for double-blind peer review. Author information will be added after the review period.

## Headline result

On the **TRAM2** test set (30 scored documents):

- **6-seed ensemble per-document F1 at dev-tuned τ=0.59: 77.17%**
- 6-seed ensemble per-document F1 at uniform τ=0.5: 76.87%
- Bootstrap 95% CI (2000 resamples over the 30 test documents): **[70.72%, 82.42%]**

Comparison numbers from Buchel et al. (2025) on the same protocol:
- Llama 3.1 8B (generative): 72.50% — this configuration: 77.17% (+4.67 F1, 73× smaller)
- CySecBERT 110M: 69.74%
- CTI-BERT 110M (SoK baseline): 69.07%

The per-seed table below shows the live artifact's individual seed F1s and ensemble F1; small variance from the headline (≤0.5 F1) reflects inference-time floating-point ordering on different hardware. Full per-seed and ensemble metrics are in [`results.json`](./results.json).

## Architecture

`LabelAttentionClassifier` with asymmetric loss training:

- Encoder: [`ibm-research/CTI-BERT`](https://huggingface.co/ibm-research/CTI-BERT) (110M params, 768 hidden)
- Head: 50 learned 768-dim label queries that attend over the encoder's `last_hidden_state`, followed by a shared 1-output linear layer applied per-label
- Loss: **Asymmetric Loss** (Ridnik et al. 2021) with γ_neg=4, γ_pos=0, clip=0.05 — designed for long-tail multi-label classification, suppresses easy negatives so the model can attend to rare-class signal
- Regularization / training tricks: layer-wise learning rate decay (α=0.85), exponential moving average (β=0.999), **stochastic weight averaging** (last 25% of epochs), per-seed best-of-{base, EMA, SWA} selection on validation macro-F1, multi-seed probability averaging at inference

The architecture is custom (not derived from `transformers.PreTrainedModel`), so loading requires the [`modeling.py`](./modeling.py) file shipped with this repo.

## Training data

- **TRAM2** (Threat Report ATT&CK Mapping v2): 151 reports, 19,178 sentences, 50 ATT&CK sub-techniques. Mean of ~82 positive examples per class.
- **Splits**: report-level train/test split from Buchel et al. (2025) (120 train reports, 31 test reports — one test report excluded from per-document F1 due to empty in-vocabulary ground truth).
- **Validation**: 80:20 sentence-level random split within the training reports for early stopping and threshold selection.

## Intended use

Map free-text CTI sentences to ATT&CK techniques. The model takes a single sentence and outputs a probability for each of 50 techniques.

**Aggregation to document level:** per-sentence inference, take the per-class max across a document's sentences, threshold, report the union of predicted techniques per document.

**Threshold note:** the headline 77.17% uses a dev-tuned global threshold τ=0.59 selected on the held-out validation split (NOT on test). Using τ=0.5 uniform yields 76.87% on the same test set. See `results.json` for the full threshold-sweep curve.

**Limitations:**
- Trained on English-language CTI; behavior on other languages is not characterized.
- 50 TRAM2 sub-techniques only; sentences describing techniques outside this set produce all-zero predictions.
- The asymmetric loss is tuned for label-dense problems (mean ~82 samples/technique). For sparser benchmarks like AnnoCTR (mean 15.5/technique), the BCE configuration is preferable — see [`cassandra-bce-annoctr`](https://huggingface.co/cassandra-anon/cassandra-bce-annoctr) and the paper §3.2 (RQ4 results) for the label-density transfer analysis.

## How to load and run

```python
from modeling import load_ensemble, predict_ensemble
import os, glob

seed_dirs = sorted(glob.glob(os.path.join(os.path.dirname(__file__), "seeds", "seed-*")))
seeds = load_ensemble(seed_dirs, device="cuda")

sentences = [
    "The malware uses Windows Command Shell to execute encoded scripts.",
    "After initial access, persistence was established via Registry Run Keys.",
]
# τ=0.5 is the simplest threshold; for the headline 77.17% use τ=0.59
results = predict_ensemble(seeds, sentences, threshold=0.5)
for sentence, techniques in results:
    print(sentence, "->", techniques)
```

A complete CLI example is in [`inference_example.py`](./inference_example.py):

```bash
pip install -r requirements.txt
python inference_example.py --threshold 0.59
```

## Per-seed members

| Seed | Tag | Per-document F1 (τ=0.5) | Selected weights |
|---|---|---|---|
| 42   | orig | 72.33% | SWA |
| 123  | orig | 74.72% | EMA |
| 456  | orig | 73.51% | base |
| 789  | repl | 71.31% | SWA |
| 2024 | repl | 70.35% | SWA |
| 3141 | repl | 69.81% | EMA |
| **6-seed ensemble (τ=0.5)** | — | **76.87%** | — |
| **6-seed ensemble (dev-τ=0.59)** | — | **77.17%** | — |

The "orig" / "repl" tag distinguishes the two 3-seed runs reported in the paper (originals and replication seeds for the per-seed variance study). For the headline 6-seed ensemble F1 they are pooled by averaging sigmoid probabilities.

For verification without re-running the model, each seed directory contains a `seed_probs.npz` file with the model's per-sentence sigmoid probabilities — sufficient to recompute every F1 number in the model card and reproduce the bootstrap CI.

## Citation

```bibtex
@misc{cassandra2026,
  title  = {CASSANDRA: How Many Parameters Suffice to Automate TTP Extractions from CTI Reports---Pushing Towards the Lower Bound},
  author = {{Anonymous Authors}},
  year   = {2026},
  note   = {Anonymous submission under review}
}
```

Please also cite TRAM2, the CTI-BERT encoder, and the asymmetric-loss work (Ridnik et al. 2021).

## License

Apache-2.0. These fine-tuned weights are derived from [`ibm-research/CTI-BERT`](https://huggingface.co/ibm-research/CTI-BERT).