Views
No views yet
csebuetnlp/banglabert
(a Bangla ELECTRA-based encoder), it jointly predicts six structured outputs from
a single article (headline + body).BanglaBERT (ELECTRA encoder, hidden=768)
│
├── [CLS] token → Dropout(0.1)
│ ├── crime_head Linear(768 → 2) is_crime
│ ├── event_head Linear(768 → 49) event type
│ ├── direct_head Linear(768 → 2) is_direct
│ └── origin_head Linear(768 → 3) origin
│
└── All tokens → Dropout(0.1)
├── loc_ner_head Linear(768 → 3) location BIO tags
└── time_ner_head Linear(768 → 3) time-span BIO tags[CLS] headline [SEP] article content [SEP], max 256 tokens.| Head | Task type | Output |
|---|---|---|
is_crime | Binary classification | True / False |
event | Multi-class (49 classes) | event type string or null |
is_direct | Binary classification | True / False |
origin | 3-class classification | local / international / null |
loc_ner | Token classification (BIO) | O, B-LOC, I-LOC |
time_ner | Token classification (BIO) | O, B-TIME, I-TIME |
| Parameter | Value |
|---|---|
| Base model | csebuetnlp/banglabert |
| Max sequence length | 256 |
| Batch size | 16 |
| Learning rate | 2e-5 |
| Warmup ratio | 0.1 |
| Weight decay | 0.01 |
| Loss (event head) | Focal loss (γ=2.0) |
| Loss (other heads) | Class-weighted cross-entropy |
| Best val avg-F1 | N/A |
| Early-stop epoch | N/A |
| Precision | Recall | F1 | Support | |
|---|---|---|---|---|
| not-crime | — | — | — | — |
| crime | — | — | — | — |
| Class | Precision | Recall | F1 | Support |
|---|---|---|---|---|
| none | 0.90 | 0.82 | 0.86 | 907 |
| international | 0.80 | 0.91 | 0.85 | 338 |
| local | 0.94 | 0.95 | 0.94 | 1873 |
| macro avg | 0.88 | 0.89 | 0.88 | 3118 |
| weighted avg | 0.91 | 0.91 | 0.91 | 3118 |
| Event | Precision | Recall | F1 | Support |
|---|---|---|---|---|
| none | 0.91 | 0.79 | 0.85 | 724 |
| armed_attack | 0.60 | 0.60 | 0.60 | 40 |
| arms_trafficking | 0.75 | 0.55 | 0.63 | 11 |
| arrest | 0.80 | 0.84 | 0.82 | 187 |
| arson | 0.79 | 0.93 | 0.86 | 29 |
| assault | 0.80 | 0.81 | 0.80 | 122 |
| attempted_murder | 1.00 | 0.80 | 0.89 | 5 |
| blockade | 0.80 | 0.88 | 0.84 | 32 |
| bribery | 0.43 | 0.75 | 0.55 | 4 |
| burglary | 0.50 | 0.50 | 0.50 | 2 |
| child_abuse | 0.83 | 0.71 | 0.77 | 7 |
| corruption | 0.74 | 0.82 | 0.78 | 131 |
| cybercrime | 0.71 | 0.75 | 0.73 | 61 |
| data_breach | 0.71 | 0.71 | 0.71 | 7 |
| drug_trafficking | 0.71 | 0.77 | 0.74 | 31 |
| fraud | 0.76 | 0.73 | 0.75 | 119 |
| gang_crime | 0.80 | 0.50 | 0.62 | 16 |
| hacking | 0.25 | 0.20 | 0.22 | 5 |
| human_chain | 0.62 | 0.89 | 0.73 | 9 |
| human_trafficking | 0.88 | 0.70 | 0.78 | 20 |
| identity_theft | 0.00 | 0.00 | 0.00 | 0 |
| kidnapping | 0.86 | 0.86 | 0.86 | 21 |
| legal_proceedings | 0.80 | 0.79 | 0.79 | 200 |
| looting | 0.62 | 0.57 | 0.59 | 14 |
| movement | 0.23 | 1.00 | 0.38 | 3 |
| murder | 0.84 | 0.81 | 0.82 | 228 |
| online_scam | 0.29 | 0.25 | 0.27 | 8 |
| organized_crime | 0.00 | 0.00 | 0.00 | 0 |
| other_crime | 0.44 | 0.55 | 0.49 | 128 |
| phishing | 0.83 | 1.00 | 0.91 | 5 |
| police_action | 0.66 | 0.68 | 0.67 | 164 |
| procession | 0.75 | 0.67 | 0.71 | 9 |
| protest_unrest | 0.79 | 0.79 | 0.79 | 276 |
| raid | 0.83 | 0.91 | 0.87 | 22 |
| rally | 0.67 | 0.62 | 0.65 | 16 |
| ransomware | 1.00 | 0.50 | 0.67 | 2 |
| rape | 0.80 | 0.96 | 0.87 | 47 |
| riot | 0.41 | 0.47 | 0.44 | 15 |
| robbery | 0.80 | 0.88 | 0.84 | 58 |
| sexual_harassment | 0.70 | 0.83 | 0.76 | 52 |
| shooting | 0.65 | 0.85 | 0.74 | 41 |
| sit_in | 0.00 | 0.00 | 0.00 | 0 |
| smuggling | 0.83 | 0.94 | 0.88 | 36 |
| snatching | 0.85 | 0.85 | 0.85 | 33 |
| stabbing | 0.77 | 0.86 | 0.81 | 28 |
| strike | 0.92 | 0.96 | 0.94 | 25 |
| terrorism | 1.00 | 0.40 | 0.57 | 5 |
| theft | 0.78 | 0.84 | 0.81 | 45 |
| vandalism | 0.85 | 0.75 | 0.79 | 75 |
| macro avg | 0.68 | 0.69 | 0.67 | 3118 |
| weighted avg | 0.79 | 0.78 | 0.78 | 3118 |
| Tag | Precision | Recall | F1 | Support |
|---|---|---|---|---|
| O | 1.00 | 0.99 | 0.99 | 164,441 |
| B-LOC | 0.61 | 0.90 | 0.72 | 1,691 |
| I-LOC | 0.49 | 0.79 | 0.60 | 661 |
| macro avg | 0.70 | 0.89 | 0.77 | 166,793 |
| weighted avg | 0.99 | 0.99 | 0.99 | 166,793 |
| Tag | Precision | Recall | F1 | Support |
|---|---|---|---|---|
| O | 1.00 | 1.00 | 1.00 | 164,825 |
| B-TIME | 0.67 | 0.90 | 0.77 | 795 |
| I-TIME | 0.69 | 0.90 | 0.78 | 1,173 |
| macro avg | 0.79 | 0.93 | 0.85 | 166,793 |
| weighted avg | 1.00 | 0.99 | 0.99 | 166,793 |
1[
2 "none",
3 "armed_attack",
4 "arms_trafficking",
5 "arrest",
6 "arson",
7 "assault",
8 "attempted_murder",
9 "blockade",
10 "bribery",
11 "burglary",
12 "child_abuse",
13 "corruption",
14 "cybercrime",
15 "data_breach",
16 "drug_trafficking",
17 "fraud",
18 "gang_crime",
19 "hacking",
20 "human_chain",
21 "human_trafficking",
22 "identity_theft",
23 "kidnapping",
24 "legal_proceedings",
25 "looting",
26 "movement",
27 "murder",
28 "online_scam",
29 "organized_crime",
30 "other_crime",
31 "phishing",
32 "police_action",
33 "procession",
34 "protest_unrest",
35 "raid",
36 "rally",
37 "ransomware",
38 "rape",
39 "riot",
40 "robbery",
41 "sexual_harassment",
42 "shooting",
43 "sit_in",
44 "smuggling",
45 "snatching",
46 "stabbing",
47 "strike",
48 "terrorism",
49 "theft",
50 "vandalism"
51]1[
2 "none",
3 "international",
4 "local"
5]pip install torch transformers huggingface_hub1from huggingface_hub import hf_hub_download
2
3# Download the checkpoint (contains all head weights + label metadata)
4ckpt_path = hf_hub_download(repo_id="arafatfahim/crime-event-detection", filename="checkpoint.pt")1import torch
2import torch.nn as nn
3import torch.nn.functional as F
4from transformers import AutoTokenizer, AutoModel
5from huggingface_hub import hf_hub_download
6
7REPO_ID = "arafatfahim/crime-event-detection"
8DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
9MAX_LEN = 256
10
11
12# ── 1. Recreate the model class ──────────────────────────────────────────────
13class BanglaBertMultiTask(nn.Module):
14 def __init__(self, bert, num_events, num_origins):
15 super().__init__()
16 self.bert = bert
17 hidden = self.bert.config.hidden_size
18 self.dropout = nn.Dropout(0.1)
19 self.crime_head = nn.Linear(hidden, 2)
20 self.event_head = nn.Linear(hidden, num_events)
21 self.direct_head = nn.Linear(hidden, 2)
22 self.origin_head = nn.Linear(hidden, num_origins)
23 self.loc_ner_head = nn.Linear(hidden, 3)
24 self.time_ner_head = nn.Linear(hidden, 3)
25
26 def forward(self, input_ids, attention_mask):
27 out = self.bert(input_ids=input_ids, attention_mask=attention_mask)
28 seq_out = self.dropout(out.last_hidden_state)
29 cls = seq_out[:, 0, :]
30 return {
31 "is_crime" : self.crime_head(cls),
32 "event" : self.event_head(cls),
33 "is_direct": self.direct_head(cls),
34 "origin" : self.origin_head(cls),
35 "loc_ner" : self.loc_ner_head(seq_out),
36 "time_ner" : self.time_ner_head(seq_out),
37 }
38
39
40# ── 2. Load checkpoint & tokenizer ──────────────────────────────────────────
41ckpt_path = hf_hub_download(repo_id=REPO_ID, filename="checkpoint.pt")
42ckpt = torch.load(ckpt_path, map_location=DEVICE)
43
44event_labels = ckpt["event_labels"] # list of str
45origin_labels = ckpt["origin_labels"] # ["none", "international", "local"]
46
47tokenizer = AutoTokenizer.from_pretrained(REPO_ID)
48bert = AutoModel.from_pretrained(REPO_ID)
49
50model = BanglaBertMultiTask(bert, ckpt["num_events"], ckpt["num_origins"]).to(DEVICE)
51model.load_state_dict(ckpt["model_state_dict"])
52model.eval()
53
54
55# ── 3. Predict ───────────────────────────────────────────────────────────────
56headline = "ঢাকায় ছিনতাইয়ের ঘটনায় যুবক গ্রেপ্তার"
57content = "রাতে একটি মোটরসাইকেল থামিয়ে যাত্রীর মোবাইল ও টাকা ছিনিয়ে নেয় দুর্বৃত্তরা।"
58
59enc = tokenizer(
60 headline, content,
61 max_length=MAX_LEN,
62 padding="max_length",
63 truncation=True,
64 return_tensors="pt",
65 return_offsets_mapping=True,
66 return_token_type_ids=True,
67)
68offset_mapping = enc.pop("offset_mapping").squeeze(0).tolist()
69token_type_ids = enc["token_type_ids"].squeeze(0).tolist()
70
71with torch.no_grad():
72 logits = model(enc["input_ids"].to(DEVICE), enc["attention_mask"].to(DEVICE))
73
74# Classification heads
75is_crime = bool(logits["is_crime"].argmax(dim=-1).item())
76is_direct = bool(logits["is_direct"].argmax(dim=-1).item())
77
78event_idx = logits["event"].argmax(dim=-1).item()
79event = event_labels[event_idx] if event_idx != 0 else None
80event_conf = F.softmax(logits["event"], dim=-1).squeeze()[event_idx].item()
81
82origin_idx = logits["origin"].argmax(dim=-1).item()
83origin = origin_labels[origin_idx] if origin_idx != 0 else None
84
85# NER heads — decode BIO spans from token predictions
86def decode_bio(preds, offsets, type_ids, texts):
87 spans, current = [], []
88 for pred, (s, e), tid in zip(preds, offsets, type_ids):
89 text = texts[tid] if tid < len(texts) else ""
90 if pred == 1:
91 if current: spans.append("".join(current))
92 current = [] if (s == 0 and e == 0) else [text[s:e]]
93 elif pred == 2 and current and not (s == 0 and e == 0):
94 current.append(text[s:e])
95 else:
96 if current: spans.append("".join(current)); current = []
97 if current: spans.append("".join(current))
98 return list(dict.fromkeys(spans)) # deduplicate, preserve order
99
100loc_preds = logits["loc_ner"].squeeze(0).argmax(dim=-1).tolist()
101time_preds = logits["time_ner"].squeeze(0).argmax(dim=-1).tolist()
102locations = decode_bio(loc_preds, offset_mapping, token_type_ids, [headline, content])
103time_spans = decode_bio(time_preds, offset_mapping, token_type_ids, [headline, content])
104
105print({
106 "is_crime" : is_crime,
107 "event" : event,
108 "event_conf" : round(event_conf, 4),
109 "is_direct" : is_direct,
110 "origin" : origin,
111 "locations" : locations,
112 "event_occurred": time_spans[0] if time_spans else None,
113})1{
2 "is_crime" : true,
3 "event" : "theft",
4 "event_conf" : 0.9132,
5 "is_direct" : true,
6 "origin" : "local",
7 "locations" : ["ঢাকা"],
8 "event_occurred": null
9}| File | Description |
|---|---|
config.json | BERT encoder config (ELECTRA architecture) |
model.safetensors | BERT encoder weights |
tokenizer_config.json / tokenizer.json | Tokenizer files |
checkpoint.pt | Full model weights (all 6 heads) + label metadata |
Note:checkpoint.ptis required to restore the classification/NER heads. Theconfig.json+model.safetensorsfiles only contain the shared BERT encoder.