You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无循环实现3D矩阵与2D矩阵的批量乘法运算?

无需循环的NumPy矩阵批量乘法实现

当然有办法摆脱循环!NumPy提供了多种向量化操作的方式,既能让代码更简洁,又能利用底层优化大幅提升运算效率。下面给你介绍几种常用的方法:

1. 使用np.einsum(最直观,对应数学逻辑)

einsum通过爱因斯坦求和约定精确描述运算逻辑,可读性拉满:

import numpy as np

A = np.ones((6,6,10))
B = np.ones((6,10))
mat = np.einsum('ijk,jk->ik', A, B)

这里的ijk,jk->ik可以这么理解:

  • ijk对应A的三个维度:第0轴(6行)、第1轴(6列)、第2轴(10个批次)
  • jk对应B的两个维度:第0轴(6行)、第1轴(10个批次)
  • ->ik表示保留A的第0轴(i)和两个数组的批次轴(k),对中间的j轴(维度为6)求和——完美对应每个批次里6×6矩阵和6维向量的乘法运算。

2. 调整维度+广播矩阵乘法

给B增加一个维度,让它和A的维度匹配,借助NumPy的广播特性完成批量运算:

mat = (A @ B[..., None]).squeeze(-1)
  • B[..., None]把B的形状从(6,10)变成(6,1,10),每个批次的向量就变成了6×1的列向量
  • A((6,6,10))和调整后的B做矩阵乘法,每个批次得到6×1的结果,整体形状是(6,1,10)
  • squeeze(-1)去掉最后一个多余维度,最终得到(6,10)的目标结果。

3. 使用np.tensordot(张量点积)

tensordot可以指定两个张量的哪些维度做点积,非常适配这种批量矩阵-向量乘法场景:

mat = np.tensordot(A, B, axes=([1], [0]))

这里axes=([1], [0])表示:对A的第1轴(6列)和B的第0轴(6行)做点积,剩下的A的第0轴(6行)和两个数组的批次轴组合起来,刚好得到(6,10)的结果。

验证结果一致性

你可以用随机数据测试这几种方法和原始循环的结果是否完全一致:

# 生成随机测试数据
A = np.random.rand(6,6,10)
B = np.random.rand(6,10)

# 原始循环实现
mat_loop = np.zeros((6,10))
for i in range(10):
    mat_loop[:,i] = A[:,:,i]@B[:,i]

# 验证三种方法
print(np.allclose(mat_loop, np.einsum('ijk,jk->ik', A, B)))  # 输出True
print(np.allclose(mat_loop, (A @ B[..., None]).squeeze(-1)))  # 输出True
print(np.allclose(mat_loop, np.tensordot(A, B, axes=([1], [0]))))  # 输出True

这些向量化方法在数据量越大时优势越明显——NumPy底层是C优化实现,比Python循环快得多。

内容的提问来源于stack exchange,提问作者arundathi-c

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 09:52:46