RuntimeError: Expected scalar type Long but found Float in PyTorch
Cast target labels and lookup indices to 64-bit integer format using targets.long() or dtype=torch.long.
Root Cause Analysis
This error occurs when Python tries to pass a floating-point tensor (such as FloatTensor) into a PyTorch operation that strictly requires discrete integer indices (such as torch.LongTensor / int64).
1. Discrete Indices vs Continuous Predictions
Classification loss functions (including nn.CrossEntropyLoss and nn.NLLLoss) and indexing layers (such as nn.Embedding) expect discrete class labels that act as lookup indices. Indices must be discrete whole numbers (integers). When target labels are created as floating-point numbers, PyTorch cannot use them as discrete array indices and raises RuntimeError: Expected scalar type Long but found Float (or expected LongTensor).
2. Common Scenarios in Classification
This error frequently occurs when: (1) target labels are parsed from floating-point CSV columns; (2) label preprocessing involves normalization or division operations that implicitly coerce integers into floats; or (3) creating one-hot target tensors instead of sparse class index vectors for CrossEntropyLoss.
3. Resolving Label Type Mismatches
Cast target tensors using .long() or torch.as_tensor(labels, dtype=torch.long) before calculating the loss.
4. CrossEntropyLoss vs BCEWithLogitsLoss
Remember that nn.CrossEntropyLoss expects 1D integer class indices of shape (N,), whereas nn.BCEWithLogitsLoss expects floating-point probabilities of shape (N, 1) or (N, C).
Reproduction Code (MCVE)
import torch
import torch.nn as nn
criterion = nn.CrossEntropyLoss()
logits = torch.randn(2, 5)
# Targets created as float instead of long
targets = torch.tensor([1.0, 3.0])
# RuntimeError: Expected scalar type Long but found Float
loss = criterion(logits, targets)
Solution 1: Cast Target Tensor to Long (int64)
Cast label tensors to torch.long using .long() or specify dtype=torch.long during tensor instantiation.
import torch
import torch.nn as nn
criterion = nn.CrossEntropyLoss()
logits = torch.randn(2, 5)
# Targets defined with explicit long dtype
targets = torch.tensor([1, 3], dtype=torch.long)
loss = criterion(logits, targets)
print('Loss computed successfully:', loss.item())
Solution 2: Use torch.as_tensor with Explicit Target Type
When converting from raw Python lists or NumPy arrays in custom Dataset classes, use torch.as_tensor with dtype=torch.long.
import torch
import torch.nn as nn
criterion = nn.CrossEntropyLoss()
logits = torch.randn(2, 5)
raw_labels = [1.0, 3.0] # Raw list with float values
targets = torch.as_tensor(raw_labels, dtype=torch.long)
loss = criterion(logits, targets)
print('Converted loss value:', loss.item())
A common misunderstanding is passing one-hot encoded targets of shape (batch_size, num_classes) to nn.CrossEntropyLoss. PyTorch's CrossEntropyLoss expects class indices (batch_size,) of dtype torch.long. Contrast this with binary classification using nn.BCEWithLogitsLoss, which requires targets of type torch.float32 matching logits shape. Always verify label ranges: class indices must be integers strictly within 0 <= target < num_classes.