新闻中心
NumPy数组乘法详解:*运算符与np.dot()的区别与应用

本文深入探讨numpy数组乘法中`*`运算符与`np.dot()`/`np.matmul()`函数的关键区别。`*`运算符执行元素级乘法,并遵循numpy的广播机制;而`np.dot()`和`np.matmul()`则用于执行矩阵乘法或点积。理解这两种操作的内在逻辑和适用场景,以及如何通过重塑数组来满足不同乘法运算的要求,对于高效、准确地使用numpy至关重要。
在NumPy中进行数组乘法时,初学者常常会对*运算符和np.dot()(或np.matmul())函数的行为感到困惑。这两种乘法操作虽然都涉及数组元素,但其数学含义和执行机制截然不同。正确区分并应用它们,是掌握NumPy高级功能的基础。
1. NumPy中的元素级乘法 (* 运算符)
*运算符在NumPy中执行的是元素级(element-wise)乘法。这意味着它会将两个数组中对应位置的元素进行相乘,并返回一个新的数组。为了使这种操作成为可能,两个数组必须具有兼容的形状。NumPy通过其强大的广播(broadcasting)机制来处理形状不匹配的数组。
广播机制
广播机制允许NumPy在执行算术运算时,自动扩展较小数组的形状,使其与较大数组的形状兼容。广播遵循一系列规则:
- 如果两个数组的维度数不同,那么维度较小的数组的形状会在其前面填充1,直到它们的维度数相同。
- 从最后一个维度开始,逐个比较两个数组的维度。如果维度相等,或者其中一个维度为1,则它们是兼容的。
- 如果某个维度不兼容(即不相等且都不为1),则会引发错误。
示例分析
考虑以下两个NumPy数组:
import numpy as np a = np.array([1, 2, 3]) # 形状: (3,) b = np.array([[1]]) # 形状: (1,1)
当我们尝试执行 a * b 时,NumPy会应用广播规则:
- 维度填充: a 是1维数组,b 是2维数组。a 会被视为 (1, 3)。
-
形状比较:
- a 的形状: (1, 3)
- b 的形状: (1, 1)
- 从右往左比较:
- 最后一个维度:3 和 1。兼容(其中一个为1)。
- 倒数第二个维度:1 和 1。兼容(相等)。
- 广播过程: b 的 1 会沿着其第二个维度(列)广播3次,使其成为 [[1, 1, 1]]。a 的 [1, 2, 3] 会沿着其第一个维度(行)广播1次,使其成为 [[1, 2, 3]]。
- 元素级乘法: [[1, 2, 3]] * [[1, 1, 1]] 结果为 [[1*1, 2*1, 3*1]] 即 [[1, 2, 3]]。
result_element_wise = a * b
print(f"a 的形状: {a.shape}")
print(f"b 的形状: {b.shape}")
print(f"a * b 的结果: {result_element_wise}")
print(f"a * b 的结果形状: {result_element_wise.shape}")
# 输出:
# a 的形状: (3,)
# b 的形状: (1,1)
# a * b 的结果: [[1 2 3]]
# a * b 的结果形状: (1, 3)这解释了为什么 a * b 会得到 [[1, 2, 3]]。
2. NumPy中的矩阵乘法 (np.dot() 和 np.matmul())
如果你的目标是执行线性代数中的矩阵乘法(或点积),那么应该使用 np.dot() 或 np.matmul() 函数。这两个函数在大多数情况下行为相似,但在处理多维数组时略有不同(np.matmul() 对堆叠矩阵乘法更友好)。
矩阵乘法规则
对于矩阵乘法 A @ B (或 np.dot(A, B)), 假设 A 的形状是 (m, n),B 的形状是 (n, p),那么结果矩阵的形状将是 (m, p)。关键在于第一个矩阵的列数必须等于第二个矩阵的行数。
N世界
一分钟搭建会展元宇宙
138
查看详情
实现期望结果
用户期望的结果是 [[1],[2],[3]],这是一个形状为 (3,1) 的矩阵。要实现这个结果,我们需要将 a 数组转换为一个列向量(形状为 (3,1)),然后与 b 数组进行矩阵乘法。
a_reshaped = a.reshape(3, 1) # 将 a 转换为列向量
print(f"重塑后 a 的形状: {a_reshaped.shape}")
# 使用 np.dot 进行矩阵乘法
result_dot_product = np.dot(a_reshaped, b)
print(f"np.dot(a_reshaped, b) 的结果: {result_dot_product}")
print(f"np.dot(a_reshaped, b) 的结果形状: {result_dot_product.shape}")
# 使用 np.matmul 也可以
result_matmul = np.matmul(a_reshaped, b)
print(f"np.matmul(a_reshaped, b) 的结果: {result_matmul}")
print(f"np.matmul(a_reshaped, b) 的结果形状: {result_matmul.shape}")
# 输出:
# 重塑后 a 的形状: (3, 1)
# np.dot(a_reshaped, b) 的结果:
# [[1]
# [2]
# [3]]
# np.dot(a_reshaped, b) 的结果形状: (3, 1)
# np.matmul(a_reshaped, b) 的结果:
# [[1]
# [2]
# [3]]
# np.matmul(a_reshaped, b) 的结果形状: (3, 1)通过将 a 重塑为 (3,1),我们成功地进行了矩阵乘法,得到了期望的 (3,1) 形状的数组。
3. 特殊情况与注意事项
在上述示例中,有一个值得注意的特殊情况:在将 a 重塑为 (3,1) 后,如果继续使用 * 运算符,它竟然也给出了与 np.dot() 相同的结果!
a_reshaped = a.reshape(3, 1) # 形状: (3,1) b = np.array([[1]]) # 形状: (1,1) result_element_wise_reshaped = a_reshaped *b print(f"a_reshaped * b 的结果: {result_element_wise_reshaped}") print(f"a_reshaped * b 的结果形状: {result_element_wise_reshaped.shape}") # 输出: # a_reshaped * b 的结果: # [[1] # [2] # [3]] # a_reshaped * b 的结果形状: (3, 1)
为什么会这样?同样是广播机制在起作用:
- a_reshaped 形状: (3, 1)
- b 形状: (1, 1)
- 从右往左比较:
- 最后一个维度:1 和 1。兼容。
- 倒数第二个维度:3 和 1。兼容(其中一个为1)。
- 广播过程: b 的 1 会沿着其第一个维度(行)广播3次,使其成为 [[1],[1],[1]]。
- 元素级乘法: [[1],[2],[3]] * [[1],[1],[1]] 结果为 [[1*1],[2*1],[3*1]] 即 [[1],[2],[3]]。
重要提示:
尽管在这个特定例子中,重塑后的 a_reshaped * b 与 np.dot(a_reshaped, b) 得到了相同的结果,但这仅仅是巧合,并且是广播规则在特定形状下产生的副作用。
- *`` 运算符始终执行元素级乘法。**
- np.dot() / np.matmul() 始终执行矩阵乘法。
为了代码的清晰性、可读性和正确性,当你需要进行矩阵乘法时,务必使用 np.dot() 或 np.matmul()。 依赖 * 运算符在特定广播场景下“恰好”得到矩阵乘法的结果,是非常危险且容易出错的做法。在更复杂的矩阵或多维数组操作中,这种混淆可能导致难以发现的逻辑错误。
总结
理解NumPy中 * 运算符和 np.dot() / np.matmul() 的区别是进行高效数值计算的关键。
- *`` 运算符 用于元素级乘法,并依赖于NumPy的广播机制**来处理形状不兼容的数组。
- np.dot() 或 np.matmul() 用于矩阵乘法(或点积),要求输入数组的维度符合线性代数的规则。
始终根据你期望的数学运算类型来选择正确的工具。如果目标是对应位置元素相乘,请使用 *;如果目标是矩阵乘法,请使用 np.dot() 或 np.matmul(),并在必要时使用 reshape() 来调整数组形状以满足乘法要求。
以上就是NumPy数组乘法详解:*运算符与np.dot()的区别与应用的详细内容,更多请关注其它相关文章!
# 工具
# 区别
# 网络营销与推广客户
# 鹿泉区上门网站优化商家
# 女鞋店铺设计营销推广
# 佛山安天网站优化方案
# 淮安如何做网站推广运营
# 银海区网络营销推广中心
# 苏州工商网站优化模式
# 转换为
# 这两种
# 较小
# 请使用
# 其中一个
# 第一个
# 使其
# 第二个
# 多维
# 运算符
# 为什么
# 微信的seo优化
# seo备案技巧
# 洛阳网站运营优化系统
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
Composer的 archive 命令怎么用_快速打包你的PHP项目及其Composer依赖
学习通网页版快速入口 学习通官网网页版直接打开
php源码怎么看淘宝客系统_看php源码淘宝客系统技巧
HTML长属性值处理:表单action路径优化与代码规范应对
vivo浏览器怎么扫描二维码 vivo浏览器内置扫一扫功能使用方法
css绝对定位元素脱离父容器怎么办_确保父元素position非static
拷贝漫画电脑版官网入口 拷贝漫画(PC版)在线直达
解决Django多数据库/多Schema环境下外键迁移问题
windows10怎么查看硬盘序列号_windows10硬盘id查询命令
在J*a中如何开发简易博客标签推荐系统_博客标签推荐项目实战解析
谷歌浏览器怎么给标签页静音_Chrome标签静音快捷操作
Win10怎么设置静态IP地址 Win10手动配置IP地址步骤【指南】
Golang如何优化内存分配与垃圾回收_Golang内存管理与GC优化实践
黑鲨3Pro怎样在相册开漫画风滤镜_iPhone黑鲨3Pro相册开漫画风滤镜【趣味滤镜】
使用 Pandas 高效处理 .dat 文件:字符清理与数据计算
Windows 11怎么彻底关闭定位_Windows 11服务中禁用Geolocation
Python Socket多播通信中指定源IP地址的实践指南
必由学官方网站入口 必由学学生教师共用登录通道
快手网页版在线登录 快手网页版官网入口快速访问
PostgreSQL海量数据高效导入策略:Python与Django实践指南
将HTML动态表格多行数据保存到Google Sheet的教程
企业名称高精度匹配:N-gram方法在结构相似性分析中的应用
Win11怎么关闭快速启动_Win11彻底关机设置教程
2026年发布! 美少女养成动作RPG《神剑少女战记》发布实机演示
AO3官方在线访问地址 Archive of Our Own最新镜像合集
抓大鹅无需下载版 抓大鹅秒玩版入口
2026春节假期时间安排 2026春节假日查询
Lar*el用户头像管理:实现图片缩放、存储与旧文件安全删除的最佳实践
CSS Grid如何控制元素对齐_align-items与justify-items组合使用
妖精漫画网页版登录入口免费_妖精漫画官网主页直接阅读漫画
Odoo 16:在表单视图中基于当前记录动态修改Tree视图属性
深入理解J*a合成构造器:何时以及为何阻止其生成
4399免费游戏网址入口 4399小游戏免费入口点开即玩
俄罗斯Yandex搜索引擎入口_Yandex官网免登录一键访问
探索高级语言到原生C/C++的转译:挑战与内存管理策略
vivo手机参数配置怎么增强信号_vivo手机参数配置信号增强方法
斑马英语APP如何开启夜间护眼阅读_斑马英语APP夜间模式与低蓝光设置教程
谷歌google账号怎么注册账号 谷歌账号注册官方流程
必由学官网快捷入口 必由学网页版在线学习平台
内存疯狂猛猛涨价:主板销量直接腰斩!
MAC怎么在地图App里使用“四处看看”_MAC体验部分城市的3D实景街景
CKEditor 5 自定义构建在React应用中渲染失败的调试与解决
windows10怎么查看本机ip_windows10命令提示符ipconfig使用
漫蛙漫画网页端入口 漫蛙2官方正版漫画站点
win11 Snap Layouts怎么用 Win11窗口布局与分屏多任务高效指南【必学】
蛙漫移动版在线看 蛙漫手机浏览器直达入口
Lar*el头像管理:图片缩放与旧文件删除的最佳实践
58动漫网在线官方网 58动漫网正版动漫入口网址
Excel Power Pivot如何处理XML数据源 构建高级数据模型
Django AJAX 文件上传教程:解决图片无法保存到模型的常见问题


2025-11-26
浏览次数:次
返回列表
b
print(f"a_reshaped * b 的结果: {result_element_wise_reshaped}")
print(f"a_reshaped * b 的结果形状: {result_element_wise_reshaped.shape}")
# 输出:
# a_reshaped * b 的结果:
# [[1]
# [2]
# [3]]
# a_reshaped * b 的结果形状: (3, 1)