ModernBERT-based token classifier for detecting oral and literate markers in text, based on Walter Ong's "Orality and Literacy" (1982).
This model performs multi-label span-level detection of 53 rhetorical marker types, where each token independently carries B/I/O labels per type — allowing overlapping spans (e.g. a token that is simultaneously part of a concessive and a nested clause).
Model Details
Property
Value
Base model
answerdotai/ModernBERT-base
Task
Multi-label token classification (independent B/I/O per type)
Marker types
53 (22 oral, 31 literate)
Test macro F1
0.378 (per-type detection, binary positive = B or I)
Training
20 epochs, fp16
Regularization
Mixout (p=0.1) — stochastic L2 anchor to pretrained weights
Loss
Per-type focal loss (γ=2.0) with inverse-frequency OBI and type weights
Min examples
150 (types below this threshold excluded)
Usage
python
1import json
2import torch
3from transformers import AutoModel, AutoTokenizer
4from huggingface_hub import hf_hub_download
56model_name ="HavelockAI/bert-token-classifier"7tokenizer = AutoTokenizer.from_pretrained(model_name)8model = AutoModel.from_pretrained(model_name, trust_remote_code=True)9model.eval()1011# Load marker type map12type_map_path = hf_hub_download(model_name,"type_to_idx.json")13type_to_idx = json.loads(open(type_map_path).read())14idx_to_type ={v: k for k, v in type_to_idx.items()}1516text ="Tell me, O Muse, of that ingenious hero who travelled far and wide"17inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=128)1819with torch.no_grad():20 logits = model(**inputs)# (1, seq_len, num_types, 3)21 preds = logits.argmax(dim=-1)# (1, seq_len, num_types)2223tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0])24for i, token inenumerate(tokens):25 active =[26f"{idx_to_type[t]}={'OBI'[v]}"27for t, v inenumerate(preds[0, i].tolist())28if v >029]30if active:31print(f"{token:15}{', '.join(active)}")
Note: This model uses a custom architecture (HavelockTokenClassifier) with independent B/I/O heads per marker type, enabling overlapping span detection. Loading requires trust_remote_code=True.
Training Data
Sources: Project Gutenberg, textfiles.com, Reddit, Wikipedia talk pages
Types with fewer than 150 annotated spans are excluded from training
Multi-label BIO annotation: tokens can carry labels for multiple overlapping marker types simultaneously
Marker Types (53)
Oral Markers (22 types)
Characteristics of oral tradition and spoken discourse:
Precision-recall tradeoff: Most types show balanced precision/recall. Notable exceptions include anaphora (0.800 precision / 0.028 recall), parallelism (0.741 / 0.110), and intensifier_doubling (0.680 / 0.200), which remain high-precision but very low-recall.
Architecture
Custom MultiLabelTokenClassifier with independent B/I/O heads per marker type:
ModernBERT (answerdotai/ModernBERT-base)
└── Dropout (p=0.1)
└── Linear (hidden_size → num_types × 3)
└── Reshape to (batch, seq, num_types, 3)
Each marker type gets an independent 3-way O/B/I classification, so a token can simultaneously carry labels for multiple overlapping marker types. Types share the full backbone representation but make independent predictions.
Regularization
Mixout (p=0.1): During training, each backbone weight element has a 10% chance of being replaced by its pretrained value per forward pass, acting as a stochastic L2 anchor that prevents representation drift (Lee et al., 2019)
Per-type focal loss (γ=2.0): Focuses learning on hard examples, reducing the contribution of easy negatives
Inverse-frequency type weights: Rare marker types receive higher loss weighting
Inverse-frequency OBI weights: B and I classes upweighted relative to dominant O class
Weighted random sampling: Examples containing rarer markers sampled more frequently
Initialization
Fine-tuned from answerdotai/ModernBERT-base. Backbone linear layers wrapped with Mixout during training (frozen pretrained copy used as anchor). The classification head is randomly initialized:
backbone.* layers → loaded from pretrained, anchored via Mixout
classifier.weight → randomly initialized
classifier.bias → randomly initialized
Limitations
Near-zero recall types: anaphora (0.028 recall), simple_conjunction (0.102), parallelism (0.110), and tricolon (0.119) are rarely detected despite being present in training data
Low-precision types: nested_clauses (0.091), metadiscourse (0.140), and qualified_assertion (0.143) have precision below 0.15, meaning most predictions for those types are false positives
Context window: 128 tokens max; longer spans may be truncated
Domain: Trained primarily on historical/literary texts; may underperform on modern social media
Subjectivity: Some marker boundaries are inherently ambiguous
Ong, Walter J. Orality and Literacy: The Technologizing of the Word. Routledge, 1982.
Lee, C. et al. "Mixout: Effective Regularization to Finetune Large-scale Pretrained Language Models." ICLR 2020.
Warner, A. et al. "Smarter, Better, Faster, Longer: A Modern Bidirectional Encoder for Fast, Memory Efficient, and Long Context Finetuning and Inference." 2024.