Word Tokenization › Tokenization Evaluation

Michael BrenndoerferUpdated March 21, 202511 min read
Language AI HandbookAll chapters
Part 1 of 67Text as Data
Chapter 5Word Tokenization › Tokenization Evaluation
Reading section 11 of 17 · Tokenization Evaluation · 11 minSection 11 of 17 · 11 min

Book contents

Section 11 of 17 · 11 min read

Word Tokenization › Tokenization EvaluationOne section · Sections in this chapter11 / 17 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

How do you know if your tokenizer is working correctly? Unlike many NLP tasks where quality is subjective, tokenization can be evaluated objectively: either a token boundary is in the right place, or it isn't. But this requires something to compare against: a gold standard of human-annotated text with correct token boundaries.

The gold standard matters. Without a reference, "correct" is undefined. The Penn Treebank provides the most widely used gold standard for English tokenization, which is why Penn Treebank conventions have become so dominant: not because they are linguistically superior to other approaches, but because they are the basis for the most commonly used evaluation resource.

The core insight is that tokenization is fundamentally a boundary detection problem. We're not just counting tokens; we're asking: did the tokenizer place boundaries in the correct positions? This framing leads naturally to the standard evaluation metrics.

The Boundary Detection Framework

Think of a text as a sequence of character positions. A tokenizer's job is to decide which positions mark the start of a new token. Consider the sentence "I can't go":

Position: 0 1 2 3 4 5 6 7 8 9 Text: I c a n ' t g o

A tokenizer that keeps contractions together places boundaries at positions 0, 2, and 8, producing ["I", "can't", "go"]. A tokenizer that splits contractions places boundaries at positions 0, 2, 4, and 8, producing ["I", "ca", "n't", "go"]. The evaluation question becomes: which boundaries match the gold standard?

Out[44]:
Visualization
Character-level visualization showing gold standard token boundaries for 'I can't go'.
Gold Standard (Penn Treebank): Boundaries at positions 0, 2, 4, 8 produce tokens [I | ca | n''t | go]. This represents the target tokenization against which other tokenizers are measured.
Character-level visualization showing conservative tokenizer boundaries with missed boundary marked.
Conservative Tokenizer: Only 3 boundaries (0, 2, 8) keeping ''can''t'' together. Precision is 100% (all predicted boundaries are correct), but Recall is 75% because the boundary at position 4 is missed.
Character-level visualization showing aggressive tokenizer boundaries matching gold standard.
Aggressive Tokenizer: All 4 boundaries match the gold standard exactly. Both Precision and Recall are 100%, yielding an F1 score of 1.0.

Evaluation Metrics

With this boundary-based view, we can apply the classic precision-recall framework from information retrieval. This framework is used throughout NLP evaluation, so understanding it in the context of tokenization prepares you for applying it to other tasks later.

Precision answers the question: of all the boundaries the tokenizer predicted, how many were correct? A tokenizer with high precision makes few false boundary predictions. It might miss some boundaries (under-tokenizing), but when it does place a boundary, it's usually right.

We compute precision by taking the intersection of predicted boundaries PP with gold boundaries GG, and dividing by the total number of predicted boundaries:

Precision=∣P∩G∣∣P∣\text{Precision} = \frac{|P \cap G|}{|P|}

where:

  • PP: the set of boundary positions predicted by the tokenizer
  • GG: the set of true boundary positions in the gold standard
  • ∣P∩G∣|P \cap G|: the number of correctly predicted boundaries (the intersection of predicted and gold boundaries)
  • ∣P∣|P|: the total number of boundaries the tokenizer predicted

Why does this formula make sense? Notice that ∣P∩G∣|P \cap G| counts only the boundaries where the tokenizer was right, and we divide by ∣P∣|P|, the total number of predictions the tokenizer made. If the tokenizer made 10 predictions and 8 were correct, precision is 8/10 = 0.8. The tokenizer is right 80% of the time.

Recall answers the complementary question: of all the true boundaries in the gold standard, how many did the tokenizer find? A tokenizer with high recall catches most boundaries. It might predict some spurious boundaries (over-tokenizing), but it rarely misses a real one.

Recall=∣P∩G∣∣G∣\text{Recall} = \frac{|P \cap G|}{|G|}

where:

  • ∣P∩G∣|P \cap G|: the number of correctly predicted boundaries (same as in precision)
  • ∣G∣|G|: the total number of true boundaries in the gold standard

Why does this formula make sense? Now we divide by ∣G∣|G|, the total number of true boundaries. If there are 10 true boundaries and the tokenizer found 8, recall is 8/10 = 0.8. The tokenizer found 80% of all boundaries.

Neither metric alone tells the full story. A tokenizer that places a boundary after every character would have perfect recall (it finds all real boundaries) but terrible precision (most of its predictions are wrong). A tokenizer that outputs the entire text as one token would have very high precision on its one boundary but miss all the others.

F1 Score balances both concerns by computing the harmonic mean of precision and recall. The harmonic mean is used rather than the arithmetic mean because it penalizes extreme imbalances: if either precision or recall is very low, F1 will be low, even if the other is high.

F1=2⋅Precision⋅RecallPrecision+RecallF_1 = 2 \cdot \frac{\text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}}

where:

  • Precision\text{Precision}: the fraction of predicted boundaries that are correct (as defined above)
  • Recall\text{Recall}: the fraction of true boundaries that were found (as defined above)
  • The factor of 2 in the numerator ensures that when precision equals recall, F1F_1 equals both values exactly

Why does this formula make sense? Notice that if precision is 1.0 and recall is 0.0, the denominator is 1.0 but the numerator is 0.0, so F1=0F_1 = 0. Similarly, if precision is 0.0 and recall is 1.0, F1=0F_1 = 0 again. This is by design: a tokenizer that is extremely good at one metric but terrible at the other is not useful in practice. The F1F_1 score forces the tokenizer to do reasonably well at both.

Let's implement this evaluation framework and see it in action:

In[45]:
Code
def evaluate_tokenizer(predicted_tokens, gold_tokens):
    """Evaluate tokenizer output against gold standard."""

    # Convert to sets of token boundaries (character positions)
    def get_boundaries(tokens):
        boundaries = set()
        pos = 0
        for token in tokens:
            boundaries.add(pos)
            pos += len(token) + 1  # +1 for space
        return boundaries

    pred_boundaries = get_boundaries(predicted_tokens)
    gold_boundaries = get_boundaries(gold_tokens)

    # Calculate metrics
    correct = len(pred_boundaries & gold_boundaries)
    precision = correct / len(pred_boundaries) if pred_boundaries else 0
    recall = correct / len(gold_boundaries) if gold_boundaries else 0
    f1 = (
        2 * precision * recall / (precision + recall)
        if (precision + recall) > 0
        else 0
    )

    return {
        "precision": precision,
        "recall": recall,
        "f1": f1,
        "predicted_count": len(predicted_tokens),
        "gold_count": len(gold_tokens),
    }


# Example evaluation
gold = ["I", "ca", "n't", "believe", "it", "'s", "not", "butter", "!"]
predicted = ["I", "can't", "believe", "it's", "not", "butter", "!"]

metrics = evaluate_tokenizer(predicted, gold)

The get_boundaries function walks through the token list, tracking character positions. Each token's starting position becomes a boundary. We then compute the set intersection between predicted and gold boundaries to count correct predictions.

Out[46]:
Console
Tokenization Evaluation:
  Gold standard: ['I', 'ca', "n't", 'believe', 'it', "'s", 'not', 'butter', '!']
  Predicted:     ['I', "can't", 'believe', "it's", 'not', 'butter', '!']

Metrics:
  Precision: 28.57%
  Recall:    22.22%
  F1 Score:  25.00%

  Gold count:      9
  Predicted count: 7

The predicted tokenization scores below 100% because it didn't split the contractions "can't" and "it's". The gold standard expects boundaries at "ca|n't" and "it|'s", but our tokenizer kept these as single tokens. This illustrates an important point: whether this is an "error" depends entirely on the task. For syntactic parsing, the gold standard is correct. For bag-of-words text classification, keeping contractions together might be preferable.

Out[47]:
Visualization
Scatter plot showing precision versus recall for five tokenization strategies, with four constant-F1 contours and an ideal region marked in the upper right.
The precision-recall tradeoff in tokenization strategies. Aggressive tokenizers (splitting at more boundaries) achieve high recall but lower precision, placing false boundaries that inflate the prediction count. Conservative tokenizers show high precision but miss boundaries, producing low recall. The ideal tokenizer sits in the upper-right region where both metrics are high. Dashed lines show constant F1-score contours, revealing that even a balanced tokenizer must maintain both precision and recall above roughly 0.85 to achieve an F1 above 0.9.

Common Evaluation Corpora

Standard tokenization benchmarks provide consistent test beds for comparing tokenizers. Using a standard benchmark rather than a custom test set is important because it enables comparison with published results and ensures that your tokenizer is being evaluated on a representative sample of real-world text:

  • Penn Treebank: The original standard for English tokenization. Contains one million words of Wall Street Journal text, carefully annotated by linguistic experts. Still the most widely cited benchmark for English tokenization.
  • Universal Dependencies: A cross-lingual collection of treebanks covering more than 100 languages with consistent tokenization and annotation standards. Essential for multilingual NLP evaluation.
  • CoNLL shared tasks: Various NLP benchmarks with tokenization components, often targeting specific domains or languages.
In[48]:
Code
# Simulated evaluation on multiple examples
test_set = [
    (["I", "'m", "happy", "."], ["I'm", "happy", "."]),
    (["Do", "n't", "worry", "!"], ["Don't", "worry", "!"]),
    (["It", "'s", "fine", "."], ["It's", "fine", "."]),
]

# Evaluate each
evaluations = []
for gold, pred in test_set:
    metrics = evaluate_tokenizer(pred, gold)
    evaluations.append((gold, pred, metrics))

# Average F1
avg_f1 = sum(e[2]["f1"] for e in evaluations) / len(evaluations)
Out[49]:
Console
Evaluation Results:
------------------------------------------------------------
Gold: ['I', "'m", 'happy', '.']
Pred: ["I'm", 'happy', '.']
F1:   28.57%

Gold: ['Do', "n't", 'worry', '!']
Pred: ["Don't", 'worry', '!']
F1:   28.57%

Gold: ['It', "'s", 'fine', '.']
Pred: ["It's", 'fine', '.']
F1:   28.57%

Average F1: 28.57%