pytorch 中 `nn.conv3d` 要求输入为 `(n, c, d, h, w)` 五维张量,而当前数据被误读为 `(1, 4, 193, 229, 193)`——即模型将 batch_size=4 当作了通道数 c=4;根本原因是 nifti 数据加载后未正确增加通道维,需在预处理中显式插入 `unsqueeze(1)`。
该错误本质是 输入张量的通道维度(C)与卷积层权重期望不一致。nn.Conv3d(in_channels=1, ...) 的权重形状为 [32, 1, 3, 3, 3],明确要求输入第 2 维(索引 1)必须为 1;但实际输入 x.shape = [1, 4, 193, 229, 193],PyTorch 将 4 解释为通道数,导致冲突。
修改 CustomDataset.__getitem__(),确保每个样本输出形状为 (1, D, H, W):
import torch
import nibabel as nib
from torch.utils.data import Dataset
from torchvision.transforms import ToTensor
class CustomDataset(Dataset):
def __init__(self, root_dir, transform=None):
self.root_dir = root_dir
self.files = [...] # your file list logic here
self.transform = transform
def __getitem__(self, idx):
# Load NIfTI (returns numpy array of shape (D, H, W))
img_path = self.files[idx]
img = nib.load(img_path).get_fdata() # shape: (193, 229, 193)
# ✅ Critical: Add channel dimension BEFORE ToTensor
img = torch.from_numpy(img).unsqueeze(0) # shap
e: (1, 193, 229, 193)
if self.transform:
img = self.transform(img) # ToTensor is optional now, but safe to keep
# Ensure final shape is (1, D, H, W)
assert img.ndim == 4 and img.shape[0] == 1, f"Expected (1,D,H,W), got {img.shape}"
return img? 提示:ToTensor() 对 (1, D, H, W) 输入无副作用(它主要处理 HWC→CHW 和 dtype 转换),但若你移除了 ToTensor(),需手动保证 img = img.float()。
在训练前加入调试代码:
for x, _ in train_loader:
print("Input shape:", x.shape) # 应输出: torch.Size([4, 1, 193, 229, 193])
break若输出为 [4, 1, 193, 229, 193],则 Conv3d 可正常工作。
# 在 forward 中临时打印以校验尺寸
x = self.pool(F.relu(self.conv2(x)))
print("After conv2+pool:", x.shape) # e.g., torch.Size([4, 64, 48, 57, 48])
x = x.view(x.size(0), -1) # ✅ 安全展平,自动适配 batch该错误不是模型结构问题,而是数据管道中张量维度约定未对齐所致。核心动作只有一步:在 Dataset.__getitem__ 中对原始 3D 医学图像调用 .unsqueeze(0),确保每个样本为 (1, D, H, W),再经 DataLoader 后自然形成 (N, 1, D, H, W) ——完全符合 nn.Conv3d 的接口契约。坚持“显式优于隐式”,可避免 90% 的 PyTorch 维度相关 RuntimeError。