{"record":{"id":"90a76a800cc77bb2","repo":"huggingface/candle","slug":"the-target-tensor-should-have-two-dimensions-dim","errorCode":null,"errorMessage":"the target tensor should have two dimensions ({dims:?})","messagePattern":"the target tensor should have two dimensions \\((.+?)\\)","errorType":"exception","errorClass":"candle::Error","httpStatus":null,"severity":"error","filePath":"candle-nn/src/loss.rs","lineNumber":25,"sourceCode":"/// Arguments\n///\n/// * [inp]: The input tensor of dimensions `N, C` where `N` is the batch size and `C` the number\n///   of categories. This is expected to contain log probabilities.\n/// * [target]: The ground truth labels as a tensor of u32 of dimension `N`.\n///\n/// The resulting tensor is a scalar containing the average value over the batch.\npub fn nll(inp: &Tensor, target: &Tensor) -> Result<Tensor> {\n    let b_sz = match target.dims() {\n        &[b_sz] => b_sz,\n        dims => candle::bail!(\"the target tensor should have a single dimension ({dims:?})\"),\n    };\n    match inp.dims() {\n        &[inp_b_sz, _] => {\n            if inp_b_sz != b_sz {\n                candle::bail!(\"batch size mismatch between inp ({inp_b_sz}) and target ({b_sz})\")\n            }\n        }\n        dims => candle::bail!(\"the target tensor should have two dimensions ({dims:?})\"),\n    }\n    inp.gather(&target.unsqueeze(1)?, 1)?\n        .sum_all()?\n        .affine(-1f64 / b_sz as f64, 0.)\n}\n\n/// The cross-entropy loss.\n///\n/// Arguments\n///\n/// * [inp]: The input tensor of dimensions `N, C` where `N` is the batch size and `C` the number\n///   of categories. This is expected to raw logits.\n/// * [target]: The ground truth labels as a tensor of u32 of dimension `N`.\n///\n/// The resulting tensor is a scalar containing the average value over the batch.\npub fn cross_entropy(inp: &Tensor, target: &Tensor) -> Result<Tensor> {\n    if inp.rank() != 2 {\n        candle::bail!(\"cross_entropy expects an input tensor of rank 2\")","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-nn/src/loss.rs#L7-L43","documentation":"nll requires the input (already log-softmaxed logits) to be exactly 2-D of shape [batch, num_classes]. This bail fires for any other rank — e.g. 3-D sequence logits of shape [B, T, C] — because the single gather is written for the 2-D classification case only.","triggerScenarios":"Calling nll or cross_entropy with inp of rank 1, 3, or higher — commonly per-token logits [B, T, C] from a language model, or [C] unbatched logits.","commonSituations":"Sequence/token-level classification fed straight into cross_entropy instead of flattening time; unbatched inference tensor; porting PyTorch code where F.cross_entropy supports [N, C, d1..] and assuming candle does too.","solutions":["For sequence logits, reshape [B, T, C] to [B*T, C] and flatten targets to [B*T] before calling cross_entropy, then reshape the scalar/mean as needed.","Add a batch dimension for unbatched input: logits.unsqueeze(0)?.","For per-token losses, reshape to 2-D, compute cross_entropy, and apply your own masking/averaging over valid tokens.","Use mse_loss/other losses only for regression; for structured outputs write a custom NLL with gather on the appropriate axis."],"exampleFix":"// before: logits [B, T, C]\nlet loss = cross_entropy(&logits, &targets)?; // error\n// after\nlet (b, t, _c) = logits.dims3()?;\nlet loss = cross_entropy(&logits.reshape((b * t, ()))?, &targets.reshape((b * t, ()))?)?;","handlingStrategy":"validation","validationCode":"if inp.rank() != 2 {\n    return Err(anyhow!(\"nll input must be [B, C], got dims {:?}\", inp.dims()));\n}","typeGuard":"fn is_logit_matrix(x: &Tensor) -> bool { x.rank() == 2 }","tryCatchPattern":"let (logits, targets) = if logits.rank() == 3 {\n    let (b, t, _c) = logits.dims3()?;\n    (logits.reshape((b * t, ()))?, targets.reshape((b * t, ()))?)\n} else { (logits, targets) };\nlet loss = cross_entropy(&logits, &targets)?;","preventionTips":["Flatten sequence dimensions before candle's cross_entropy (unlike PyTorch it does not accept [B,T,C])","Add a loss-wrapper module that reshapes any rank into [N, C] first","Keep unbatched inference tensors unsqueezed to [1, C]","Read the candle loss docs note on supported ranks before porting PyTorch code"],"tags":["loss","shape","tensor","rust"],"backgroundTag":"tensor-rank-mismatch","analyzedSha":"d5fee525bfde3273eb7c9b75fd2bc4937be867ca","analyzedAt":"2026-09-02T00:15:47.023Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}