Intermediate

Named Entity Recognition

Extract structured information from unstructured text by identifying and classifying named entities like people, organizations, and locations.

Built-in Entity Types

LabelDescriptionExample
PERSONPeople, including fictionalElon Musk, Sherlock Holmes
ORGCompanies, agencies, institutionsGoogle, United Nations
GPECountries, cities, statesFrance, New York
DATEAbsolute or relative datesJune 2024, last week
MONEYMonetary values$1.5 million, 500 euros
PRODUCTObjects, vehicles, foodsiPhone, Boeing 747
EVENTNamed eventsOlympics, World War II

Using NER

Python - Extract entities
import spacy
nlp = spacy.load("en_core_web_sm")

text = """Microsoft was founded by Bill Gates and Paul Allen
in Albuquerque, New Mexico on April 4, 1975. The company
is now worth over $2 trillion."""

doc = nlp(text)

for ent in doc.ents:
    print(f"{ent.text:25} {ent.label_:10} "
          f"[{ent.start_char}:{ent.end_char}]")

# Microsoft                ORG        [0:9]
# Bill Gates               PERSON     [25:35]
# Paul Allen               PERSON     [40:50]
# Albuquerque              GPE        [54:65]
# New Mexico               GPE        [67:77]
# April 4, 1975            DATE       [81:95]
# over $2 trillion         MONEY      [125:141]

Rule-Based Matching

Python - EntityRuler for custom patterns
from spacy.language import Language

# Add entity ruler to the pipeline
ruler = nlp.add_pipe("entity_ruler", before="ner")

patterns = [
    {"label": "TECH", "pattern": "Python"},
    {"label": "TECH", "pattern": "JavaScript"},
    {"label": "TECH", "pattern": [{"LOWER": "machine"}, {"LOWER": "learning"}]},
    {"label": "FRAMEWORK", "pattern": "spaCy"},
    {"label": "FRAMEWORK", "pattern": "TensorFlow"},
]
ruler.add_patterns(patterns)

doc = nlp("We use Python and TensorFlow for machine learning")
for ent in doc.ents:
    print(f"{ent.text:20} {ent.label_}")

Training Custom NER

Python - Prepare training data (spaCy v3)
import spacy
from spacy.tokens import DocBin

nlp = spacy.blank("en")
db = DocBin()

# Training data: (text, {"entities": [(start, end, label)]})
TRAIN_DATA = [
    ("Uber blew past Q2 earnings estimates", {"entities": [(0, 4, "ORG"), (15, 17, "DATE")]}),
    ("Tesla stock surged 10% on Monday", {"entities": [(0, 5, "ORG"), (26, 32, "DATE")]}),
    ("AWS announced new GPU instances", {"entities": [(0, 3, "ORG"), (18, 21, "PRODUCT")]}),
]

for text, annotations in TRAIN_DATA:
    doc = nlp.make_doc(text)
    ents = []
    for start, end, label in annotations["entities"]:
        span = doc.char_span(start, end, label=label)
        if span:
            ents.append(span)
    doc.ents = ents
    db.add(doc)

db.to_disk("./train.spacy")
Terminal - Train with spaCy CLI
# Generate config file
python -m spacy init config config.cfg --lang en --pipeline ner

# Train the model
python -m spacy train config.cfg --output ./output --paths.train ./train.spacy --paths.dev ./dev.spacy
Best practice: For custom NER, aim for at least 200-500 annotated examples per entity type. Use Prodigy (by the same team) for efficient annotation, or export from Label Studio in spaCy format.

Ready to Go Deeper?

Live instructor-led courses from our partners. Affiliate disclosure.