原帖将 NumPy 的二维 a.dot(b) 直接翻译成 torch.dot(a,b):
RuntimeError: 1D tensors expected, but got 2D and 2D tensors
不同的 dot,不能逐字翻译
NumPy 对二维 dot 的定义能执行矩阵乘法,PyTorch 的 dot 则限定一维。原题的 (3,2) 与 (2,1) 内维本来就匹配,不需要展平或转置;更换运算入口就能保持原计算含义。
两个库的 dot 语义不同。PyTorch 的 torch.dot 接受两个一维向量;二维矩阵乘法应使用 @、torch.matmul 或 torch.mm。
下面是独立示例,先检查两个真正参与乘法的矩阵:
import torch
a = torch.ones(3, 2)
b = torch.ones(2, 1)
print("josh050608")
print("a:", a.shape, a.dtype, a.device)
print("b:", b.shape, b.dtype, b.device)
result = a @ b
assert result.shape == (3, 1)
print(result)
把失败行改成 result = a @ b 即可保留原题想要的矩阵乘法。内维应匹配,即 a.shape[-1] == b.shape[-2],两者还需有兼容的 dtype 与相同设备。
如果你实际需要逐元素乘法,应使用 a * b,但它遵循广播规则,结果不是矩阵乘积。不要把两个矩阵 flatten 后再 dot;那会改变计算目标,只得到一个内积标量。
二维输入可以使用 torch.mm(a,b);含批次的矩阵乘法通常用 matmul,并单独核对批次轴的广播含义。验证时不仅检查不报错,也确认输出行数来自 a、列数来自 b。原题两矩阵全为 1,因此每个输出元素在数学上应为 2。
用非全 1 数据检查乘法方向
全 1 示例容易掩盖转置或广播错误。下面用可手算的数据检查矩阵乘积,同时演示一维 dot 的合法场景:
import torch
a = torch.tensor([[1., 2.], [3., 4.], [5., 6.]])
b = torch.tensor([[10.], [100.]])
product = a @ b
expected = torch.tensor([[210.], [430.], [650.]])
assert torch.equal(product, expected)
assert torch.equal(torch.mm(a, b), expected)
assert torch.dot(a[0], b[:, 0]).item() == 210.0
print("matrix product:", product)
a[0] 与 b[:,0] 都是一维长度 2,因此 dot 返回一个标量;整个 a 与 b 的矩阵乘法返回三行一列。输出含义不同,不能为了满足 dot 的维数要求把两个二维对象任意拉平。
含批次时再区分:[B,M,K] @ [B,K,N] 得到 [B,M,N],matmul 还允许符合规则的批次广播。若实际希望每个样本独立计算,明确检查 B 轴,避免一个 [K,N] 权重被误认为每批不同的矩阵。
修复原题只需改失败行;后续若出现内维、dtype 或设备错误,打印实际参与的 a 与 b 再处理,不要同时修改数值布局。用一个手算结果和目标 shape 验证,比只看“不抛异常”更容易发现乘法语义被改了。
参考:原始求助帖;技术依据:torch.dot(2.5)、torch.matmul(2.5)。