{"record":{"id":"d6b05887fccb06ee","repo":"hankcs/HanLP","slug":"expected-last-dimension-of-emissions-is-self-num","errorCode":null,"errorMessage":"expected last dimension of emissions is {self.num_tags}, got {emissions.size(2)}","messagePattern":"expected last dimension of emissions is (.+?), got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"hanlp/layers/crf/crf.py","lineNumber":168,"sourceCode":"        self._validate(emissions, mask=mask)\n        if mask is None:\n            mask = emissions.new_ones(emissions.shape[:2], dtype=torch.uint8)\n\n        if self.batch_first:\n            emissions = emissions.transpose(0, 1)\n            mask = mask.transpose(0, 1)\n\n        return self._viterbi_decode(emissions, mask)\n\n    def _validate(\n            self,\n            emissions: torch.Tensor,\n            tags: Optional[torch.LongTensor] = None,\n            mask: Optional[torch.ByteTensor] = None) -> None:\n        if emissions.dim() != 3:\n            raise ValueError(f'emissions must have dimension of 3, got {emissions.dim()}')\n        if emissions.size(2) != self.num_tags:\n            raise ValueError(\n                f'expected last dimension of emissions is {self.num_tags}, '\n                f'got {emissions.size(2)}')\n\n        if tags is not None:\n            if emissions.shape[:2] != tags.shape:\n                raise ValueError(\n                    'the first two dimensions of emissions and tags must match, '\n                    f'got {tuple(emissions.shape[:2])} and {tuple(tags.shape)}')\n\n        if mask is not None:\n            if emissions.shape[:2] != mask.shape:\n                raise ValueError(\n                    'the first two dimensions of emissions and mask must match, '\n                    f'got {tuple(emissions.shape[:2])} and {tuple(mask.shape)}')\n            no_empty_seq = not self.batch_first and mask[0].all()\n            no_empty_seq_bf = self.batch_first and mask[:, 0].all()\n            if not no_empty_seq and not no_empty_seq_bf:\n                raise ValueError('mask of the first timestep must all be on')","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/hankcs/HanLP/blob/ddb1299bddff079e447af52ec12549c50636bfa8/hanlp/layers/crf/crf.py#L150-L186","documentation":"CRF._validate also checks that the last dimension of emissions equals the num_tags the CRF was constructed with (its transition matrices are num_tags x num_tags). A mismatch — e.g. the scoring head outputs a different number of classes than the CRF expects — raises ValueError with both sizes.","triggerScenarios":"Loading/rebuilding a model where the linear output layer size differs from CRF.num_tags (vocab changed between runs); constructing CRF with num_tags=N but the encoder head outputs M features; fine-tuning with a reduced/extended label set.","commonSituations":"Changing the label vocabulary and restoring old checkpoints; manually wiring a CRF with a hardcoded tag count; multi-task heads sharing a CRF with mismatched sizes.","solutions":["Rebuild the CRF with num_tags matching the head output: CRF(num_tags=out_features)","Re-create the vocab/tag set so model head and CRF are built from the same vocab in one place","When loading checkpoints, rebuild the whole model from the current vocab rather than patching layers"],"exampleFix":"# before\nself.crf = CRF(num_tags=20)\nout = self.linear(h)          # out.shape[-1] == 25 -> error\n# after\nself.crf = CRF(num_tags=self.linear.out_features)","handlingStrategy":"validation","validationCode":"assert emissions.size(-1) == crf.num_tags, f'{emissions.size(-1)} != {crf.num_tags}; rebuild CRF with matching num_tags'","typeGuard":"def emissions_match_crf(emissions: torch.Tensor, crf) -> bool:\n    return emissions.dim() == 3 and emissions.size(-1) == crf.num_tags","tryCatchPattern":null,"preventionTips":["Derive CRF num_tags from the same vocab object that sizes the output layer","Rebuild the entire model from the current vocab when label sets change"],"tags":["python","pytorch","crf","tensor-shape","vocab-mismatch"],"backgroundTag":"model-dimension-mismatch","analyzedSha":"ddb1299bddff079e447af52ec12549c50636bfa8","analyzedAt":"2026-08-27T03:36:54.287Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}