多维数组矩阵乘法报错:(3,2,2,2)与(2,2,2,2)无法广播求修正
问题分析
你把两个数组理解为「每个元素是2x2矩阵的3x2矩阵」和「每个元素是2x2矩阵的2x2矩阵」,这个逻辑是对的,但NumPy的@运算符和np.dot的维度匹配规则和你的预期不匹配:
@运算符将高维数组的最后两个维度视为矩阵维度,前面的维度视为batch维度。你的第一个数组batch维度是(3,2),第二个是(2,2),这两个batch维度无法广播,所以触发错误。np.dot会对所有非最后一个维度做广播后点积,导致结果维度膨胀到(3,2,2,2,2,2),不符合需求。
修正方案
方案1:用np.einsum明确指定维度映射
这是最直观的方式,直接按你理解的维度对应关系编写:
import numpy as np a = np.random.randn(3,2,2,2) b = np.random.randn(2,2,2,2) result = np.einsum('abij,bcjk->abik', a, b) print(result.shape) # 输出 (3,2,2,2)
解释:
abij对应数组a的维度:a的第0维是3(a)、第1维是2(b)、第2-3维是2x2矩阵(i,j)bcjk对应数组b的维度:b的第0维是2(b)、第1维是2(c)、第2-3维是2x2矩阵(j,k)abik是输出维度:保留a的a、b维度,保留矩阵的i、k维度,中间的b和j维度做矩阵乘法求和。
方案2:调整维度后用@运算符
如果你更习惯用@,可以先调整数组维度,让batch维度匹配广播规则:
# 把a的维度从(3,2,2,2)变成(3,2,1,2,2),b的维度从(2,2,2,2)变成(1,2,2,2,2) result = a[:, :, None, :, :] @ b[None, :, :, :, :] # 去掉中间多余的维度 result = result.squeeze() print(result.shape) # 输出 (3,2,2,2)
这里通过添加None扩展维度,让batch维度(3,2,1)和(1,2,2)可以广播为(3,2,2),然后@对最后两个维度做矩阵乘法,最后用squeeze()去掉多余的单维度。
方案3:用np.matmul配合维度扩展
和方案2逻辑一致,np.matmul的规则和@相同:
result = np.matmul(a[:, :, None, :, :], b[None, :, :, :, :]).squeeze() print(result.shape) # 输出 (3,2,2,2)
内容的提问来源于stack exchange,提问作者Manu Dwivedi
相关产品推荐
相关产品推荐

