Named Entity Recognition: Sequence Labeling and Beyond
Module: Natural Language Processing | Difficulty: Advanced
BIO Tagging
CRF Layer
Transition Matrix
Span-Based NER
import torch
import torch.nn as nn
class BiLSTM_CRF(nn.Module):
def __init__(self, vocab_size, embed_dim=128, hidden_dim=256, n_tags=9):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim)
self.lstm = nn.LSTM(embed_dim, hidden_dim//2, bidirectional=True, batch_first=True)
self.hidden2tag = nn.Linear(hidden_dim, n_tags)
self.transitions = nn.Parameter(torch.randn(n_tags, n_tags))
def _forward_alg(self, feats):
init_alphas = torch.full((1, self.n_tags), -10000.)
init_alphas[0][self.tag_to_ix[START_TAG]] = 0.
forward_var = init_alphas
for feat in feats:
emit_score = feat.view(1, -1).expand(self.n_tags, -1)
trans_score = self.transitions
next_tag_var = forward_var + trans_score + emit_score
forward_var = torch.logsumexp(next_tag_var, dim=1).view(1, -1)
return torch.logsumexp(forward_var + self.transitions[self.tag_to_ix[STOP_TAG]], dim=1)
Research Insight: The CRF layer improves NER by modeling label dependencies (e.g., I-LOC cannot follow B-PER). This is especially important for nested entities and complex label schemes. BERT-CRF achieves state-of-the-art on most NER benchmarks.