Named Entity Recognition
Named entity recognition (NER) detects spans and assigns entity types such as person, organization, location, date, product, or medication. It is a special case of sequence labelling, and it often feeds entity linking and matching or information extraction. The output is not just a class; the exact span boundary is part of the prediction.
BIO tagging
NER labels each token with a BIO tag marking whether it begins, continues, or falls outside an entity span:
| Tag | Meaning | Example (token → tag) |
|---|---|---|
| B-TYPE | begins an entity of that type | Paris → B-LOC |
| I-TYPE | continues the current entity | Tower → I-LOC (in “Eiffel Tower”) |
| O | outside any entity | visited → O |
Formally, the model predicts the most likely tag for each token:
The tag sequence is then converted into spans:
Evaluation usually requires exact span and type agreement, because confusing Paris as an organization instead of a location changes downstream behavior.
Worked example
This snippet extracts BIO entity spans from gold and predicted tags, then computes span-level precision, recall, and F1.
import numpy as np
np.random.seed(7)
def spans(tags):
out, start, typ = [], None, None
for i, t in enumerate(tags + ["O"]):
if t.startswith("B-") or (t == "O" and typ):
if typ:
out.append((start, i, typ)); start, typ = None, None
if t.startswith("B-"):
start, typ = i, t[2:]
elif t.startswith("I-") and typ is None:
start, typ = i, t[2:]
return out
gold = ["B-PER", "I-PER", "O", "B-LOC", "O", "B-ORG"]
pred = ["B-PER", "I-PER", "O", "B-ORG", "O", "B-ORG"]
G, P = set(spans(gold)), set(spans(pred))
tp = len(G & P)
precision, recall = tp / len(P), tp / len(G)
f1 = 2 * precision * recall / (precision + recall)
print("gold_spans", sorted(G))
print("pred_spans", sorted(P))
print("span_precision", round(precision, 3), "span_recall", round(recall, 3), "span_f1", round(f1, 3))Observed output:
gold_spans [(0, 2, 'PER'), (3, 4, 'LOC'), (5, 6, 'ORG')]
pred_spans [(0, 2, 'PER'), (3, 4, 'ORG'), (5, 6, 'ORG')]
span_precision 0.667 span_recall 0.667 span_f1 0.667The model found the boundary for token 3 but assigned the wrong type, so that span is false positive and false negative under exact typed-span scoring.
Caveats
Entity schemas are domain-specific. Apple can be a company, food item, record label, or product family; dates and locations may be nested inside larger legal or medical spans. Tokenization can split names into awkward pieces, and aggregate F1 can hide severe errors on rare entity types.
References
- Jurafsky and Martin, Speech and Language Processing, 3rd ed. draft
- Finkel, Grenager, and Manning, Incorporating Non-local Information into Information Extraction Systems
- scikit-learn API: f1_score
Nav