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
- Verify the label vocab is non-empty (print len(vocab) before model build)
- Fix training data path/column mapping so labels are actually parsed
- 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
- Assert non-empty label vocab before building models
- Smoke-test data loading (labels parsed) before training runs
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
- invalid reduction: {reduction}
- Got average f{average}, expected one of None, 'token', or 'b
- activation must be callable: type={}
- DataParallel not supported when CRF is used
- emissions must have dimension of 3, got {emissions.dim()}
AI-assisted analysis of hankcs/HanLP@ddb1299bdd (2026-08-27).
Data as JSON: /api/errors/8ec7db8fe99b8909.
Report an issue: GitHub.