原帖希望在第一维补 29 个零,却在拼接时报其他维度不匹配:
RuntimeError: invalid argument 0: Sizes of tensors must match except in dimension 2. Got 32 and 71 in dimension 0 at /pytorch/aten/src/THC/generic/THCTensorMath.cu:87
报错中的 dimension 2 与目标的第 0 维不一致
要把 [71,32,1] 变为 [100,32,1],应扩展第 0 维。原报错又出现 32 与 71 在第 0 维不一致,说明实际对象轴顺序可能与描述不完全相同;先打印两侧 shape,再决定拼接维,不能只把所有 dim 改成一个固定值。
对 cat 来说,只有指定的拼接维允许长度不同;原错误明确说当前尝试沿 dimension 2 拼接,而需求是扩大第 0 维。
下面 x 对应原张量,先检查实际形状,再用它派生同 dtype、同设备的补零部分:
import torch
x = torch.randn(71, 32, 1)
print("josh050608")
print("x:", x.shape, x.dtype, x.device)
missing = 100 - x.shape[0]
assert missing >= 0
padding = x.new_zeros((missing, *x.shape[1:]))
y = torch.cat((x, padding), dim=0)
assert y.shape == (100, 32, 1)
assert torch.equal(y[:71], x)
assert torch.count_nonzero(y[71:]) == 0
真实项目把示例 x 换成自己的张量即可。new_zeros 避免用默认 CPU/float32 的 zeros 与原 CUDA 张量冲突。
如果你的实际对象是 [32,71,1],要先确认轴分别代表 batch、时间还是特征;不能看见 71 就无条件沿 dim=0。原报错还出现 32 与 71 在第 0 维冲突,说明至少有一个实际对象的轴顺序与文字描述不同,务必打印两者 shape。
若是可变长度序列批次,还需要记录原长度或构造 mask,使后续损失和注意力不会把补零当成真实数据。补齐后的形状正确只是第一步,验证时还要确认原数据未改动、padding 所在轴符合模型约定。
包装成带边界检查的补齐函数
下面完整 CPU 示例只沿第 0 维补零,拒绝原数据已经超过目标长度的情况,并验证原数据和梯度路径仍保留:
import torch
def pad_first_axis(x, target_length):
missing = target_length - x.shape[0]
if missing < 0:
raise ValueError("原长度超过目标,需要显式定义截断规则")
padding = x.new_zeros((missing, *x.shape[1:]))
return torch.cat([x, padding], dim=0)
x = torch.ones(71, 32, 1, requires_grad=True)
y = pad_first_axis(x, 100)
assert y.shape == (100, 32, 1)
assert torch.equal(y[:71], x)
assert torch.count_nonzero(y[71:]) == 0
y.sum().backward()
assert torch.equal(x.grad, torch.ones_like(x))
valid = torch.arange(100) < x.shape[0]
assert valid.sum().item() == 71
print("padded shape/valid length:", y.shape, valid.sum().item())
若第 0 维表示时间,valid 可以作为长度掩码的基础;若实际布局是 batch_first,时间通常在另一轴,应相应调整函数,而不是按数字 71 猜位置。
零向量并不自动成为“忽略”标记。后续 RNN、注意力或损失必须按照任务使用 lengths、mask 或有效区域,避免把 padding 当成真实训练信号。
修复后除了目标 shape,还要确认原数据顺序、补零区域、dtype/device 一致,以及上游需要的梯度没有被断开。若设计需要截断,另行明确裁掉哪一端,不能在补齐函数里默默丢数据。
参考:原始求助帖;技术依据:torch.cat(2.5)、PyTorch 数据加载(2.5)。