hankcs/HanLP · error · ValueError

invalid number of tags: {num_tags}

Error message

invalid number of tags: {num_tags}

What it means

The CRF layer (used by taggers with crf=True) requires at least one tag; constructing CRF(num_tags=0) or a negative value raises ValueError. num_tags is typically derived from the tag vocab size, so this usually means an empty label set.

Source

Thrown at hanlp/layers/crf/crf.py:59

        start_transitions (`~torch.nn.Parameter`): Start transition score tensor of size
            ``(num_tags,)``.
        end_transitions (`~torch.nn.Parameter`): End transition score tensor of size
            ``(num_tags,)``.
        transitions (`~torch.nn.Parameter`): Transition score tensor of size
            ``(num_tags, num_tags)``.


    .. [LMP01] Lafferty, J., McCallum, A., Pereira, F. (2001).
       "Conditional random fields: Probabilistic models for segmenting and
       labeling sequence data". *Proc. 18th International Conf. on Machine
       Learning*. Morgan Kaufmann. pp. 282–289.

    .. _Viterbi algorithm: https://en.wikipedia.org/wiki/Viterbi_algorithm
    """

    def __init__(self, num_tags: int, batch_first: bool = True) -> None:
        if num_tags <= 0:
            raise ValueError(f'invalid number of tags: {num_tags}')
        super().__init__()
        self.num_tags = num_tags
        self.batch_first = batch_first
        self.start_transitions = nn.Parameter(torch.empty(num_tags))
        self.end_transitions = nn.Parameter(torch.empty(num_tags))
        self.transitions = nn.Parameter(torch.empty(num_tags, num_tags))

        self.reset_parameters()

    def reset_parameters(self) -> None:
        """Initialize the transition parameters.

        The parameters will be initialized randomly from a uniform distribution
        between -0.1 and 0.1.
        """
        nn.init.uniform_(self.start_transitions, -0.1, 0.1)
        nn.init.uniform_(self.end_transitions, -0.1, 0.1)
        nn.init.uniform_(self.transitions, -0.1, 0.1)

View on GitHub (pinned to ddb1299bdd)

Solutions

  1. Verify the label vocab is non-empty (print len(vocab) before model build)
  2. Fix training data path/column mapping so labels are actually parsed
  3. Pass a positive num_tags when constructing CRF directly

Example fix

# before
crf = CRF(num_tags=len(tag_vocab))  # tag_vocab empty -> 0
# after
assert len(tag_vocab) > 0, 'no labels parsed from training data'
crf = CRF(num_tags=len(tag_vocab))
Defensive patterns

Strategy: validation

Validate before calling

assert len(tag_vocab) > 0, 'tag vocab empty; check training data and label mapping'

Prevention

When it happens

Trigger: Building a tagger whose config/vocab yields num_tags=0 — e.g. training before labels are counted, a mis-parsed label column, or an empty training file — then the CRF constructor is called during model build.

Common situations: Training with wrong field mapping (labels read as features); empty or malformed training data; creating CRF manually with a placeholder 0.

Related errors


AI-assisted analysis of hankcs/HanLP@ddb1299bdd (2026-08-27). Data as JSON: /api/errors/8ec7db8fe99b8909. Report an issue: GitHub.