faizhuda commited on
Commit
653f249
·
verified ·
1 Parent(s): a4cab5c

Publish phishing v1.0

Browse files
v1.0/config.json ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_cross_attention": false,
3
+ "architectures": [
4
+ "BertForSequenceClassification"
5
+ ],
6
+ "attention_probs_dropout_prob": 0.1,
7
+ "bos_token_id": null,
8
+ "classifier_dropout": null,
9
+ "directionality": "bidi",
10
+ "dtype": "float32",
11
+ "eos_token_id": null,
12
+ "hidden_act": "gelu",
13
+ "hidden_dropout_prob": 0.1,
14
+ "hidden_size": 768,
15
+ "id2label": {
16
+ "0": "legit",
17
+ "1": "phishing"
18
+ },
19
+ "initializer_range": 0.02,
20
+ "intermediate_size": 3072,
21
+ "is_decoder": false,
22
+ "label2id": {
23
+ "legit": 0,
24
+ "phishing": 1
25
+ },
26
+ "layer_norm_eps": 1e-12,
27
+ "max_position_embeddings": 512,
28
+ "model_type": "bert",
29
+ "num_attention_heads": 12,
30
+ "num_hidden_layers": 12,
31
+ "pad_token_id": 0,
32
+ "pooler_fc_size": 768,
33
+ "pooler_num_attention_heads": 12,
34
+ "pooler_num_fc_layers": 3,
35
+ "pooler_size_per_head": 128,
36
+ "pooler_type": "first_token_transform",
37
+ "tie_word_embeddings": true,
38
+ "transformers_version": "5.0.0",
39
+ "type_vocab_size": 2,
40
+ "use_cache": false,
41
+ "vocab_size": 119547
42
+ }
v1.0/eval_report.json ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "checkpoint": "checkpoints\\phishing_v1",
3
+ "test_split": "data\\processed\\phishing\\test",
4
+ "metrics": {
5
+ "recall_phishing": 0.9695238095238096,
6
+ "precision_phishing": 0.9279854147675478,
7
+ "f1_phishing": 0.9482999534233815,
8
+ "confusion_matrix": [
9
+ [
10
+ 4593,
11
+ 79
12
+ ],
13
+ [
14
+ 32,
15
+ 1018
16
+ ]
17
+ ],
18
+ "threshold": 0.95,
19
+ "n_test": 5722,
20
+ "n_phishing_test": 1050,
21
+ "n_legit_test": 4672,
22
+ "p95_ms": 434.70457002258627,
23
+ "latency": {
24
+ "mean_ms": 239.72067400012747,
25
+ "p50_ms": 220.47114999440964,
26
+ "p95_ms": 434.70457002258627,
27
+ "n": 200.0
28
+ }
29
+ },
30
+ "gates": {
31
+ "recall": true,
32
+ "precision": true,
33
+ "latency_p95": true
34
+ },
35
+ "all_passed": true
36
+ }
v1.0/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3833500e476c2272e55bf008849e8afad126520073c308297c4af742a656fde5
3
+ size 711443432
v1.0/model_card.md ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model Card — PriorMail Phishing Detector v1.0
2
+
3
+ **Model ID:** `phishing/v1.0`
4
+ **Owner:** Faiz (PJK-GM095)
5
+ **Date:** 2026-06-13
6
+ **Status:** Eval gates passed — pending export approval from Insan + Syafiq
7
+
8
+ ---
9
+
10
+ ## What This Model Does
11
+
12
+ Binary email classifier: **legit (0)** vs **phishing (1)**.
13
+
14
+ Used by `prior-mail-backend` to flag potentially malicious emails before they reach the user's inbox. Runs at inference time on every incoming email.
15
+
16
+ ---
17
+
18
+ ## Base Model
19
+
20
+ `bert-base-multilingual-cased` (Google, 178M params)
21
+
22
+ Chosen over IndoBERT because the primary training data is English-dominant (~98% EN). mBERT handles English well and retains multilingual capability for future Indonesian phishing data.
23
+
24
+ ---
25
+
26
+ ## Training Data
27
+
28
+ | Source | Role | Rows (after dedup) |
29
+ |---|---|---|
30
+ | `ealvaradob/phishing-dataset` subset `texts` | Phishing + some legit | ~20,137 |
31
+ | Enron corpus (`emails.csv`) | Legit negative class | ~20,000 sampled |
32
+
33
+ **Total after deduplication:** ~38,000 rows
34
+ **Train / Val / Test split:** 75 / 12.5 / 12.5 (stratified by label)
35
+
36
+ Deduplication applied on the first 200 chars of body before splitting to prevent leakage.
37
+
38
+ **Note:** Dataset is almost entirely English. Indonesian phishing emails are not well-represented. Performance on Indonesian-language phishing may be lower — to be addressed in v1.1 with internal labeled data.
39
+
40
+ ---
41
+
42
+ ## Training Config
43
+
44
+ See [`configs/phishing_v1.yaml`](../configs/phishing_v1.yaml) for the full reproducible config.
45
+
46
+ Key hyperparameters:
47
+
48
+ | Parameter | Value |
49
+ |---|---|
50
+ | Learning rate | 2e-5 |
51
+ | Batch size | 16 per device |
52
+ | Max sequence length | 512 |
53
+ | Epochs | 4 (early stopped at 3) |
54
+ | Warmup ratio | 0.10 |
55
+ | Loss | Weighted cross-entropy (phishing_class_multiplier=3.0) |
56
+ | Early stopping metric | `recall_phishing` (patience=2) |
57
+ | Mixed precision | bf16 |
58
+ | Seed | 42 |
59
+
60
+ ---
61
+
62
+ ## Evaluation Results
63
+
64
+ ### Threshold Selection (Validation Set)
65
+
66
+ Threshold selected on val set to maximize precision while keeping recall ≥ 0.95.
67
+
68
+ **Threshold: 0.95**
69
+
70
+ | Metric | Val Set |
71
+ |---|---|
72
+ | Recall | 0.981 |
73
+ | Precision | 0.933 |
74
+
75
+ ### Final Results (Test Set, n=5,722)
76
+
77
+ | Metric | Result | Gate | Status |
78
+ |---|---|---|---|
79
+ | Recall | **0.970** | ≥ 0.95 | PASS ✅ |
80
+ | Precision | **0.928** | ≥ 0.80 | PASS ✅ |
81
+ | Latency p95 (CPU) | **435 ms** | < 500 ms | PASS ✅ |
82
+ | F1 | 0.948 | — | — |
83
+
84
+ ### Confusion Matrix (Test Set)
85
+
86
+ | | Predicted Legit | Predicted Phishing |
87
+ |---|---|---|
88
+ | **Actual Legit** | 4,593 (TN) | 79 (FP) |
89
+ | **Actual Phishing** | 32 (FN) | 1,018 (TP) |
90
+
91
+ False negatives (missed phishing): **32 out of 1,050** — 3.0% miss rate.
92
+ False positives (false alarms): **79 out of 4,672** — 1.7% false alarm rate.
93
+
94
+ ---
95
+
96
+ ## Input / Output Format
97
+
98
+ **Input** (assembled by `src/data/preprocess.build_phishing_input()`):
99
+ ```
100
+ FROM: {sender_email} [SEP] SUBJECT: {subject} [SEP] BODY: {body}
101
+ ```
102
+
103
+ If sender or subject are unavailable (e.g. plain-body-only sources), those fields are empty strings. The model still performs well on body-only input — the HF training data was ~98% body-only.
104
+
105
+ **Output:**
106
+ - Raw: softmax probability for class 1 (phishing), range [0, 1]
107
+ - Final label: `phishing` if probability ≥ 0.95, else `legit`
108
+ - Threshold stored in `threshold.json` alongside the checkpoint
109
+
110
+ ---
111
+
112
+ ## Known Limitations
113
+
114
+ - **Language:** Trained primarily on English data. Lower recall expected on Indonesian-language phishing. Mitigated by mBERT's multilingual pretraining, but not validated.
115
+ - **Sender signal weak:** ~98% of HF phishing training samples had no RFC 2822 headers — sender email is not a reliable feature for this version. Enron legit samples do have sender headers, which may introduce a small asymmetry.
116
+ - **Adversarial robustness:** Not evaluated against adversarial phishing (obfuscated URLs, lookalike domains, Unicode tricks). Planned for v1.1.
117
+ - **Domain shift:** Trained on public phishing corpora. Real-world phishing targeting Indonesian corporate users may have different patterns.
118
+
119
+ ---
120
+
121
+ ## Artifacts
122
+
123
+ | File | Description |
124
+ |---|---|
125
+ | `model.safetensors` | Fine-tuned weights (best checkpoint, step 835 / epoch 1) |
126
+ | `config.json` | HuggingFace model config |
127
+ | `tokenizer.json`, `tokenizer_config.json` | Tokenizer (bert-base-multilingual-cased) |
128
+ | `threshold.json` | `{"threshold": 0.95}` |
129
+ | `training_config.yaml` | Full training config + git SHA |
130
+ | `val_metrics.json` | Val set metrics at end of training |
131
+
132
+ Eval artifacts (in `eval/results/phishing/`):
133
+ | File | Description |
134
+ |---|---|
135
+ | `eval_report.json` | Full test set metrics + confusion matrix + latency |
136
+
137
+ ---
138
+
139
+ ## Changelog
140
+
141
+ | Version | Date | Notes |
142
+ |---|---|---|
143
+ | v1.0 | 2026-06-13 | Initial release. All eval gates passed. English-only training data. |
v1.0/threshold.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "threshold": 0.95
3
+ }
v1.0/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
v1.0/tokenizer_config.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "cls_token": "[CLS]",
4
+ "do_lower_case": false,
5
+ "is_local": false,
6
+ "mask_token": "[MASK]",
7
+ "model_max_length": 512,
8
+ "pad_token": "[PAD]",
9
+ "sep_token": "[SEP]",
10
+ "strip_accents": null,
11
+ "tokenize_chinese_chars": true,
12
+ "tokenizer_class": "BertTokenizer",
13
+ "unk_token": "[UNK]"
14
+ }
v1.0/training_config.yaml ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Phishing detector — v1 baseline config.
2
+ # Decision log (feat/phishing-model, 2026-06-09):
3
+ # Base model : bert-base-multilingual-cased — English-capable (§11 decision,
4
+ # approved by Insan; diverges from priority's IndoBERT because
5
+ # ealvaradob/phishing-dataset is English-heavy).
6
+ # Legit class : Enron corporate email corpus (emails.csv, 20 K sampled).
7
+ # Imbalance : weighted cross-entropy + 3× multiplier on phishing class.
8
+ #
9
+ # Run via:
10
+ # make data-phishing
11
+ # make train-phishing config=configs/phishing_v1.yaml
12
+
13
+ model_type: phishing
14
+ model_name: bert-base-multilingual-cased # §11 decision: English-capable base
15
+
16
+ dataset: ealvaradob/phishing-dataset # primary phishing training data (HF)
17
+ legit_source: emails.csv # Enron corpus — negative class source
18
+
19
+ num_labels: 2 # legit (0) | phishing (1) — matches PHISHING_LABELS in constants.py
20
+
21
+ hyperparameters:
22
+ learning_rate: 2.0e-5 # AdamW (mirrors priority protocol, ML_PIPELINE.md §3)
23
+ weight_decay: 0.01
24
+ batch_size: 16
25
+ gradient_accumulation_steps: 1
26
+ num_epochs: 4 # 3–5 with early stopping
27
+ warmup_ratio: 0.10
28
+ lr_scheduler_type: linear
29
+ max_seq_length: 512
30
+ # Early stopping on RECALL, not macro F1 — false negatives are worst case (§3).
31
+ early_stopping_metric: recall_phishing
32
+ early_stopping_patience: 2
33
+ class_weights: balanced # inverse-frequency base weights from train dist
34
+ phishing_class_multiplier: 3.0 # extra multiplier on phishing class weight
35
+ mixed_precision: bf16 # falls back to fp16 / none as needed
36
+
37
+ seed: 42
38
+
39
+ output_dir: checkpoints/phishing_v1
40
+
41
+ wandb:
42
+ project: priormail
43
+ tags:
44
+ - model:phishing
45
+ - stage:baseline
46
+
47
+ # --- run provenance (auto-recorded) ---
48
+ _git_sha: 94013c0
49
+ _git_dirty: True
50
+ _trained_at: 2026-06-13T10:59:03