{"record":{"id":"fb5499282ff869e5","repo":"hankcs/HanLP","slug":"the-first-two-dimensions-of-emissions-and-tags-mus","errorCode":null,"errorMessage":"the first two dimensions of emissions and tags must match, got {tuple(emissions.shape[:2])} and {tuple(tags.shape)}","messagePattern":"the first two dimensions of emissions and tags must match, got (.+?) and (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"hanlp/layers/crf/crf.py","lineNumber":174,"sourceCode":"            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')\n\n    def _compute_score(\n            self, emissions: torch.Tensor, tags: torch.LongTensor,\n            mask: torch.ByteTensor) -> torch.Tensor:\n        # emissions: (seq_length, batch_size, num_tags)\n        # tags: (seq_length, batch_size)","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/hankcs/HanLP/blob/ddb1299bddff079e447af52ec12549c50636bfa8/hanlp/layers/crf/crf.py#L156-L192","documentation":"Raised by HanLP's TorchCRF._validate during forward/decode when the batch/sequence dimensions of emissions and tags disagree. emissions must be (seq_len, batch, num_tags) or (batch, seq_len, num_tags) per batch_first, and tags must match the first two dims exactly. This mirrors torchcrf's validation, ensuring score computation is well-defined.","triggerScenarios":"Calling crf(emissions, tags, mask) where tags has a different batch size or sequence length than emissions, e.g. tags trimmed/padded differently, or passing batch-first tags with seq-first emissions (or vice versa) when batch_first=False (the default).","commonSituations":"Mismatched padding between the encoder output and the tag tensor; using a data loader that pads emissions and labels with different lengths; forgetting the CRF defaults to batch_first=False while the rest of the pipeline is batch_first=True.","solutions":["Ensure tags.shape == emissions.shape[:2] before calling forward/decode","Construct the CRF with batch_first=True if your tensors are (batch, seq, ...) and verify all tensors use that layout","Check your collate/padding function pads emissions and tags to the same max length"],"exampleFix":"# before\ncrf = CRF(num_tags, batch_first=False)\nloss = crf(emissions, tags)  # emissions (B,T,C), tags (B,T) -> error\n# after\ncrf = CRF(num_tags, batch_first=True)\nloss = crf(emissions, tags)  # emissions (B,T,C), tags (B,T)","handlingStrategy":"validation","validationCode":"assert emissions.dim() == 3 and emissions.shape[:2] == tags.shape, (emissions.shape, tags.shape)","typeGuard":"def tags_match(emissions: torch.Tensor, tags: torch.Tensor) -> bool:\n    return emissions.dim() == 3 and tuple(emissions.shape[:2]) == tuple(tags.shape)","tryCatchPattern":"try:\n    loss = crf(emissions, tags)\nexcept ValueError as e:\n    if 'first two dimensions' in str(e):\n        raise ValueError(f'Padding mismatch: {emissions.shape} vs {tags.shape}') from e\n    raise","preventionTips":["Derive tags and emissions from the same padded batch","Standardize batch_first across the whole model","Assert shapes in debug builds before crf.forward"],"tags":["hanlp","crf","pytorch","shape-mismatch","validation"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"ddb1299bddff079e447af52ec12549c50636bfa8","analyzedAt":"2026-08-27T03:36:54.287Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}