{"record":{"id":"8ec7db8fe99b8909","repo":"hankcs/HanLP","slug":"invalid-number-of-tags-num-tags","errorCode":null,"errorMessage":"invalid number of tags: {num_tags}","messagePattern":"invalid number of tags: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"hanlp/layers/crf/crf.py","lineNumber":59,"sourceCode":"        start_transitions (`~torch.nn.Parameter`): Start transition score tensor of size\n            ``(num_tags,)``.\n        end_transitions (`~torch.nn.Parameter`): End transition score tensor of size\n            ``(num_tags,)``.\n        transitions (`~torch.nn.Parameter`): Transition score tensor of size\n            ``(num_tags, num_tags)``.\n\n\n    .. [LMP01] Lafferty, J., McCallum, A., Pereira, F. (2001).\n       \"Conditional random fields: Probabilistic models for segmenting and\n       labeling sequence data\". *Proc. 18th International Conf. on Machine\n       Learning*. Morgan Kaufmann. pp. 282–289.\n\n    .. _Viterbi algorithm: https://en.wikipedia.org/wiki/Viterbi_algorithm\n    \"\"\"\n\n    def __init__(self, num_tags: int, batch_first: bool = True) -> None:\n        if num_tags <= 0:\n            raise ValueError(f'invalid number of tags: {num_tags}')\n        super().__init__()\n        self.num_tags = num_tags\n        self.batch_first = batch_first\n        self.start_transitions = nn.Parameter(torch.empty(num_tags))\n        self.end_transitions = nn.Parameter(torch.empty(num_tags))\n        self.transitions = nn.Parameter(torch.empty(num_tags, num_tags))\n\n        self.reset_parameters()\n\n    def reset_parameters(self) -> None:\n        \"\"\"Initialize the transition parameters.\n\n        The parameters will be initialized randomly from a uniform distribution\n        between -0.1 and 0.1.\n        \"\"\"\n        nn.init.uniform_(self.start_transitions, -0.1, 0.1)\n        nn.init.uniform_(self.end_transitions, -0.1, 0.1)\n        nn.init.uniform_(self.transitions, -0.1, 0.1)","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/hankcs/HanLP/blob/ddb1299bddff079e447af52ec12549c50636bfa8/hanlp/layers/crf/crf.py#L41-L77","documentation":"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.","triggerScenarios":"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.","commonSituations":"Training with wrong field mapping (labels read as features); empty or malformed training data; creating CRF manually with a placeholder 0.","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"],"exampleFix":"# before\ncrf = CRF(num_tags=len(tag_vocab))  # tag_vocab empty -> 0\n# after\nassert len(tag_vocab) > 0, 'no labels parsed from training data'\ncrf = CRF(num_tags=len(tag_vocab))","handlingStrategy":"validation","validationCode":"assert len(tag_vocab) > 0, 'tag vocab empty; check training data and label mapping'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Assert non-empty label vocab before building models","Smoke-test data loading (labels parsed) before training runs"],"tags":["python","pytorch","crf","argument-validation"],"backgroundTag":"empty-vocab","analyzedSha":"ddb1299bddff079e447af52ec12549c50636bfa8","analyzedAt":"2026-08-27T03:36:54.287Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}