首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >人工智能之数据分析 numpy:第九章 数组运算

人工智能之数据分析 numpy:第九章 数组运算

原创
作者头像
咚咚王
发布2025-11-23 18:55:11
发布2025-11-23 18:55:11
770
举报

人工智能之数据分析 numpy

第九章 数组运算


前言

NumPy 不仅提供了高效的多维数组(ndarray)结构,还内置了丰富的数组运算功能,包括基础算术、比较逻辑、位运算、通用函数(ufunc)、矩阵与线性代数等。这些运算是向量化的,无需显式循环,性能远超纯 Python。

下面系统讲解 NumPy 的各类数组运算。


一、基础算术运算(Element-wise Arithmetic)

NumPy 支持对数组进行逐元素(element-wise) 的四则运算和幂运算。

1. 基本运算符(支持广播)

代码语言:python
复制
import numpy as np

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

print(a + b)  # [5 7 9]
print(a - b)  # [-3 -3 -3]
print(a * b)  # [4 10 18]
print(a / b)  # [0.25 0.4  0.5 ]
print(a ** 2) # [1 4 9]
print(a % 2)  # [1 0 1]

2. 广播(Broadcasting)示例

代码语言:python
复制
# 标量与数组运算
print(a + 10)   # [11 12 13]

# 不同形状但兼容的数组
A = np.array([[1, 2, 3],
              [4, 5, 6]])  # shape (2,3)
B = np.array([10, 20, 30])   # shape (3,)

print(A + B)
# [[11 22 33]
#  [14 25 36]] ← B 被广播到每一行

✅ 广播规则:从后往前对齐维度,缺失或为1的维度可扩展。


二、比较运算(Comparison)

返回布尔数组,常用于筛选。

代码语言:python
复制
a = np.array([1, 2, 3, 4])
b = np.array([1, 3, 2, 4])

print(a == b)   # [ True False False  True]
print(a != b)   # [False  True  True False]
print(a > 2)    # [False False  True  True]
print(np.equal(a, b))  # 等价于 a == b

多数组比较

代码语言:python
复制
# 找出三个数组中相等的位置
c = np.array([1, 3, 3, 4])
mask = (a == b) & (b == c)
print(mask)  # [ True False  True  True]

三、逻辑运算(Logical Operations)

适用于布尔数组。

运算

函数

说明

np.logical_and(x, y)x & y

元素级 AND

np.logical_or(x, y)x \| y

元素级 OR

np.logical_not(x)~x

元素级 NOT

异或

np.logical_xor(x, y)

XOR

代码语言:python
复制
x = np.array([True, False, True])
y = np.array([True, True, False])

print(x & y)           # [ True False False]
print(np.logical_and(x, y))  # 同上

print(~x)              # [False  True False]

⚠️ 注意:对非布尔数组使用 &, | 会执行位运算(见下文),而非逻辑运算!


四、位运算(Bitwise Operations)

对整数类型的二进制位进行操作。

运算符

函数

说明

&

np.bitwise_and

按位与

\|

np.bitwise_or

按位或

^

np.bitwise_xor

按位异或

~

np.invert

按位取反

<<

np.left_shift

左移

>>

np.right_shift

右移

代码语言:python
复制
a = np.array([1, 2, 3])  # 二进制: 01, 10, 11
b = np.array([3, 2, 1])  #         11, 10, 01

print(a & b)   # [1 2 1] → 01&11=01, 10&10=10, 11&01=01
print(a << 1)  # [2 4 6] → 左移1位(×2)

💡 位运算常用于掩码操作、图像处理、嵌入式系统等。


五、通用函数(ufunc: Universal Functions)

ufunc 是 NumPy 的核心,提供向量化、快速、元素级的数学函数。

1. 常见数学 ufunc

代码语言:python
复制
x = np.array([0, np.pi/2, np.pi])

print(np.sin(x))      # [0.0, 1.0, ~0.0]
print(np.cos(x))      # [1.0, ~0.0, -1.0]
print(np.exp(x))      # [1.0, ~4.81, ~23.14]
print(np.log([1, np.e, np.e**2]))  # [0. 1. 2.]
print(np.sqrt([4, 9, 16]))         # [2. 3. 4.]

2. 累积与聚合 ufunc

代码语言:python
复制
a = np.array([1, 2, 3, 4])

print(np.add.reduce(a))     # 10(求和)
print(np.multiply.reduce(a))# 24(连乘)

print(np.add.accumulate(a)) # [1 3 6 10](前缀和)

3. 自定义 ufunc(高级)

代码语言:python
复制
# 将普通函数转为 ufunc
def my_func(x, y):
    return x**2 + y**2

my_ufunc = np.frompyfunc(my_func, 2, 1)
result = my_ufunc([1, 2], [3, 4])  # 返回 object 数组

⚠️ frompyfunc 性能较低,仅用于无法向量化的场景。


六、矩阵与线性代数(numpy.linalg

Ⅰ. 矩阵乘法

在 NumPy 中,矩阵(Matrix) 有两种主要表示方式:

  1. 普通的二维 ndarray(推荐方式)
  2. 已弃用的 np.matrix

下面将详细讲解这两种方式,并重点说明为什么现代 NumPy 推荐使用 ndarray 而非 matrix,以及如何高效进行矩阵运算。


np.matrix:历史遗留(已弃用)

1. 创建方式
代码语言:python
复制
import numpy as np

# 从字符串、列表或 ndarray 创建
M = np.matrix([[1, 2], [3, 4]])
N = np.matrix('1 2; 3 4')  # 字符串形式
print(M)
# [[1 2]
#  [3 4]]
2. 特点
  • 始终是二维的(即使你试图 reshape)
  • * 表示矩阵乘法(不是逐元素相乘)
  • .I(逆)、.T(转置)等属性
代码语言:python
复制
A = np.matrix([[1, 2], [3, 4]])
B = np.matrix([[5, 6], [7, 8]])

print(A * B)  # 矩阵乘法!
# [[19 22]
#  [43 50]]

print(A.I)    # 逆矩阵
print(A.T)    # 转置
3. ❌ 为什么被弃用?
  • 行为不一致:与 ndarray 混用时容易出错
  • 维度限制:无法表示三维及以上张量(深度学习必需)
  • 社区共识:NumPy 官方自 1.15 版本起标记为 deprecated,未来可能移除

📌 官方建议不要使用 np.matrix,改用 ndarray + @ 运算符。


✅ 推荐方式:使用二维 ndarray 表示矩阵

1. 创建矩阵(本质是 2D array)
代码语言:python
复制
A = np.array([[1, 2],
              [3, 4]])   # shape: (2, 2)

B = np.arange(1, 5).reshape(2, 2)
# [[1 2]
#  [3 4]]
2. 矩阵运算(使用标准 NumPy 函数和运算符)

操作

推荐写法

说明

矩阵乘法

A @ Bnp.dot(A, B)

Python 3.5+ 支持 @

逐元素乘法

A * B

默认行为

转置

A.TA.transpose()

逆矩阵

np.linalg.inv(A)

行列式

np.linalg.det(A)

解方程 Ax=b

np.linalg.solve(A, b)

示例:
代码语言:python
复制
A = np.array([[1, 2],
              [3, 4]], dtype=float)
B = np.array([[5, 6],
              [7, 8]], dtype=float)

# 矩阵乘法
C = A @ B
print("A @ B =\n", C)

# 转置
print("A.T =\n", A.T)

# 逆矩阵
A_inv = np.linalg.inv(A)
print("A⁻¹ =\n", A_inv)
print("A @ A⁻¹ ≈ I:\n", A @ A_inv)  # 应接近单位矩阵

# 解线性方程组
b = np.array([5, 11])
x = np.linalg.solve(A, b)
print("Solution x =", x)  # [1. 2.] → 1*1+2*2=5, 3*1+4*2=11

输出:

代码语言:python
复制
A @ B =
 [[19. 22.]
  [43. 50.]]
A.T =
 [[1. 3.]
  [2. 4.]]
A⁻¹ =
 [[-2.   1. ]
  [ 1.5 -0.5]]
A @ A⁻¹ ≈ I:
 [[1.0000000e+00 0.0000000e+00]
  [8.8817842e-16 1.0000000e+00]]
Solution x = [1. 2.]

常用矩阵操作汇总(基于 ndarray

1. 基本属性
代码语言:python
复制
M = np.array([[1, 2, 3],
              [4, 5, 6]])

print(M.ndim)   # 2
print(M.shape)  # (2, 3)
print(M.size)   # 6
2. 特殊矩阵构造
代码语言:python
复制
# 零矩阵
Z = np.zeros((3, 3))

# 单位矩阵
I = np.eye(3)        # 或 np.identity(3)

# 对角矩阵
D = np.diag([1, 2, 3])

# 随机矩阵
R = np.random.rand(2, 2)
3. 矩阵分解(numpy.linalg
代码语言:python
复制
A = np.array([[1, 2], [3, 4]], dtype=float)

# 特征值分解
eigenvals, eigenvecs = np.linalg.eig(A)

# 奇异值分解 (SVD)
U, s, Vt = np.linalg.svd(A)

# QR 分解
Q, R = np.linalg.qr(A)
4. 范数与条件数
代码语言:python
复制
# L2 范数(谱范数)
norm_A = np.linalg.norm(A, 2)

# Frobenius 范数
fro_norm = np.linalg.norm(A, 'fro')

# 条件数
cond_num = np.linalg.cond(A)

广播与矩阵运算的注意事项

1. 矩阵乘法维度必须匹配
代码语言:python
复制
A = np.random.rand(3, 4)
B = np.random.rand(4, 2)
C = A @ B  # ✅ (3,4) @ (4,2) → (3,2)

# D = A @ A  # ❌ (3,4) @ (3,4) → 维度不匹配!
2. 向量与矩阵相乘
代码语言:python
复制
A = np.array([[1, 2],
              [3, 4]])
v = np.array([1, 2])  # shape: (2,) —— 一维向量

# 左乘:v^T A → 结果是行向量(一维)
result1 = v @ A  # [7, 10]

# 右乘:A v → 结果是列向量(一维)
result2 = A @ v  # [5, 11]

# 若需显式列向量,用 reshape
v_col = v.reshape(-1, 1)  # shape: (2, 1)
Av = A @ v_col  # shape: (2, 1)

💡 NumPy 中的一维数组在矩阵乘法中自动视为行或列向量,非常灵活。


实际应用示例

📌 示例 1:线性回归(最小二乘解)
代码语言:python
复制
# 数据:X (n_samples, n_features), y (n_samples,)
X = np.array([[1, 1],
              [1, 2],
              [1, 3]])  # 添加偏置项
y = np.array([2, 3, 4])

# 正规方程:w = (X^T X)^{-1} X^T y
XTX_inv = np.linalg.inv(X.T @ X)
w = XTX_inv @ X.T @ y
print("Weights:", w)  # [1. 1.] → y = 1 + 1*x
📌 示例 2:图像仿射变换(旋转矩阵)
代码语言:python
复制
theta = np.pi / 4  # 45度
R = np.array([[np.cos(theta), -np.sin(theta)],
              [np.sin(theta),  np.cos(theta)]])  # 旋转矩阵

point = np.array([1, 0])  # x轴上的点
rotated = R @ point
print("Rotated point:", rotated)  # [0.707, 0.707]

总结:矩阵操作最佳实践

项目

推荐做法

数据结构

使用 np.array(二维),不要用 np.matrix

矩阵乘法

@np.dot()

转置

.T

逆矩阵

np.linalg.inv()

解方程

np.linalg.solve()(比求逆更稳定高效)

高维张量

ndarray 支持任意维度,matrix 不支持

🔑 核心理念统一使用 ndarray,通过 @linalg 模块完成所有矩阵运算,代码更清晰、兼容性更好、性能更优。


Ⅱ. 常用线性代数函数(np.linalg

NumPy 通过 np.dotnumpy.linalg 模块支持线性代数运算。

函数

说明

np.linalg.inv(A)

矩阵求逆

np.linalg.det(A)

行列式

np.linalg.eig(A)

特征值与特征向量

np.linalg.solve(A, b)

解线性方程组 Ax = b

np.linalg.norm(x)

向量/矩阵范数(默认 L2)

np.linalg.svd(A)

奇异值分解

示例:解线性方程组

代码语言:python
复制
# 2x + y = 5
# x + 3y = 10

A = np.array([[2, 1],
              [1, 3]])
b = np.array([5, 10])

x = np.linalg.solve(A, b)
print(x)  # [1. 3.] → x=1, y=3

示例:计算矩阵的 Frobenius 范数

代码语言:python
复制
norm = np.linalg.norm(A, 'fro')  # 或默认 ord=None

七、其他重要运算

1. 聚合函数(Reduction)

代码语言:python
复制
arr = np.array([[1, 2, 3],
                [4, 5, 6]])

print(arr.sum())          # 21
print(arr.sum(axis=0))    # [5 7 9](按列求和)
print(arr.mean(axis=1))   # [2. 5.](每行均值)
print(np.std(arr))        # 标准差
print(np.max(arr))        # 最大值

2. 四舍五入

代码语言:python
复制
x = np.array([1.234, 2.567, 3.891])
print(np.round(x, 1))  # [1.2 2.6 3.9]
print(np.floor(x))     # [1. 2. 3.]
print(np.ceil(x))      # [2. 3. 4.]

八、小结:运算类型速查表

类型

示例函数/运算符

说明

算术

+ - * / ** %

逐元素运算,支持广播

比较

== != > < >= <=

返回布尔数组

逻辑

& \| ~(布尔数组)

逻辑与/或/非

位运算

& \| ^ ~ << >>(整数)

二进制位操作

ufunc

np.sin, np.exp, np.sqrt

向量化数学函数

矩阵乘法

@, np.dot

线性代数乘法

线性代数

np.linalg.inv, solve, eig

高级矩阵运算

聚合

sum, mean, std, max

沿轴归约


九、注意事项

  1. 区分 *@
  • A * B:逐元素相乘
  • A @ B:矩阵乘法
  1. 广播陷阱
代码语言:python
复制
a = np.array([1, 2])
b = np.array([[1], [2]])
   print(a + b)  # shape (2,2) —— 小心意外广播!
  1. 整数溢出
代码语言:python
复制
   x = np.array([200], dtype=np.uint8)
   print(x * 2)  # 144(200*2=400 → 溢出回绕)
  1. 除零警告
代码语言:python
复制
np.seterr(divide='ignore', invalid='ignore')  # 控制警告行为

后续

本文主要讲述了numpy数组相关的运算。python过渡项目部分代码已经上传至gitee,后续会逐步更新,主要受时间原因限制,当然自己也可以克隆到本地学习拓展。

资料关注

公众号:咚咚王

《Python编程:从入门到实践》

《利用Python进行数据分析》

《算法导论中文第三版》

《概率论与数理统计(第四版) (盛骤) 》

《程序员的数学》

《线性代数应该这样学第3版》

《微积分和数学分析引论》

《(西瓜书)周志华-机器学习》

《TensorFlow机器学习实战指南》

《Sklearn与TensorFlow机器学习实用指南》

《模式识别(第四版)》

《深度学习 deep learning》伊恩·古德费洛著 花书

《Python深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》

《深入浅出神经网络与深度学习+(迈克尔·尼尔森(Michael+Nielsen)》

《自然语言处理综论 第2版》

《Natural-Language-Processing-with-PyTorch》

《计算机视觉-算法与应用(中文版)》

《Learning OpenCV 4》

《AIGC:智能创作时代》杜雨+&+张孜铭

《AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型》

《从零构建大语言模型(中文版)》

《实战AI大模型》

《AI 3.0》

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 人工智能之数据分析 numpy
  • 前言
  • 一、基础算术运算(Element-wise Arithmetic)
    • 1. 基本运算符(支持广播)
    • 2. 广播(Broadcasting)示例
  • 二、比较运算(Comparison)
    • 多数组比较
  • 三、逻辑运算(Logical Operations)
  • 四、位运算(Bitwise Operations)
  • 五、通用函数(ufunc: Universal Functions)
    • 1. 常见数学 ufunc
    • 2. 累积与聚合 ufunc
    • 3. 自定义 ufunc(高级)
  • 六、矩阵与线性代数(numpy.linalg)
    • Ⅰ. 矩阵乘法
      • np.matrix:历史遗留(已弃用)
      • ✅ 推荐方式:使用二维 ndarray 表示矩阵
      • 常用矩阵操作汇总(基于 ndarray)
      • 广播与矩阵运算的注意事项
      • 实际应用示例
      • 总结:矩阵操作最佳实践
    • Ⅱ. 常用线性代数函数(np.linalg)
      • 示例:解线性方程组
      • 示例:计算矩阵的 Frobenius 范数
  • 七、其他重要运算
    • 1. 聚合函数(Reduction)
    • 2. 四舍五入
  • 八、小结:运算类型速查表
  • 九、注意事项
  • 后续
  • 资料关注
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档