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:

TagMeaningExample (token → tag)
B-TYPEbegins an entity of that typeParis → B-LOC
I-TYPEcontinues the current entityTower → I-LOC (in “Eiffel Tower”)
Ooutside any entityvisited → 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.667

The 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