NumPy 数值计算基础入门
服务器环境 :华为云 ECS ecs-98e5-0001(FlexusX x2e.8u.16g)
系统 :Ubuntu 24.04 | Python :3.12.3 | NumPy :1.26.4
公网 IP :120.46.31.149
实战账号 :root / 1qaz@WSX
实战时间:2026-06-29
目录
| # | 章节 | 核心知识点 |
|---|---|---|
| 1 | 数值类型与多维数组 | dtype / ndarray / 快速创建函数 |
| 2 | 数组运算 | 逐元素运算 / 矩阵乘法 / Broadcasting |
| 3 | 切片与索引 | 基础切片 / 花式索引 / 布尔索引 |
| 4 | 形状操作 | reshape / ravel / stack / split |
| 5 | 统计函数 | mean/median/std / axis 参数 / percentile |
| 6 | 随机数 | rand/randn/randint / shuffle / 分布抽样 |
| 7 | 线性代数 | inv / det / solve / norm |
| 8 | 综合实战 | 图像灰度化处理 |
前言
NumPy(Numerical Python)是 Python 科学计算生态系统的基石。 它提供了:
-
ndarray:高效的多维齐次数组对象(C 语言实现,连续内存) -
向量化运算:逐元素操作无需显式循环,性能远超原生 Python list
-
广播机制(Broadcasting):不同形状数组间自动对齐的运算规则
-
线性代数 :
np.linalg模块封装 BLAS/LAPACK原生 Python list vs NumPy ndarray
┌────────────────────────────────────────────────┐
│ 原生 list │ NumPy ndarray │
│ ┌──┬──┬──┬──┐ │ ┌────┬────┬────┬────┐ │
│ │ │ │ │ │ │ │ 1.1│ 2.2│ 3.3│ 4.4│ │
│ └──┴──┴──┴──┘ │ └────┴────┴────┴────┘ │
│ 分散对象,指针间接引用 连续内存,缓存友好 │
│ 每个元素 Python 对象 每个元素固定字节 dtype │
│ 逐元素运算需 for 循环 向量化运算,C 级别速度 │
└────────────────────────────────────────────────┘
实验1:数值类型与多维数组
1.1 数值类型(dtype)
NumPy 数组的所有元素必须是同一数据类型(homogeneous)。 dtype 决定每个元素占用的字节数和解释方式。
上机环境 :
Python 3.12.3|NumPy 1.26.4|Ubuntu 24.04
python
>>> import numpy as np
>>> np.__version__
1.26.4
常用 dtype 速查表
| dtype | 含义 | 字节 | 取值范围 |
|---|---|---|---|
np.int8 |
8位有符号整数 | 1 | -128, 127 |
np.int64 |
64位有符号整数(默认 int) | 8 | -2⁶³, 2⁶³-1 |
np.uint8 |
8位无符号整数 | 1 | 0, 255 |
np.float32 |
单精度浮点 | 4 | 约 ±3.4×10³⁸ |
np.float64 |
双精度浮点(默认 float) | 8 | 约 ±1.8×10³⁰⁸ |
np.bool_ |
布尔类型 | 1 | True / False |
⚠️ 踩坑 :Ubuntu 24.04 的
pip3 install numpy会报externally-managed-environment错误。解决方案:
apt-get install python3-numpy或pip3 install --break-system-packages numpy
上机实测
ini
>>> a = np.array([1, 2, 3]); a.dtype
int64 # Linux 64位,默认 int64
>>> b = np.array([1.0, 2.0, 3.0]); b.dtype
float64
>>> c = np.array([1, 2, 3], dtype=np.float32); c.dtype, c
(float32, array([1., 2., 3.], dtype=float32))
>>> d = np.array([1, 2, 3], dtype=np.int16); d.dtype, d.itemsize
(int16, 2) # int16 占 2 字节
1.2 多维数组创建
scss
ndarray 核心属性
┌─────────────────────────────────────────┐
│ 属性 │ 含义 │ 示例 │
│───────────│──────────────────│────────────────│
│ .ndim │ 维度数量(轴数) │ 2 │
│ .shape │ 各维度大小 │ (3, 4) │
│ .size │ 总元素个数 │ 12 │
│ .dtype │ 元素数据类型 │ dtype('int64') │
│ .itemsize │ 每元素字节数 │ 8 │
│ .nbytes │ 数组总字节数 │ 96 │
└─────────────────────────────────────────┘
上机实测
ini
>>> arr1d = np.array([10, 20, 30, 40, 50])
>>> arr1d.ndim, arr1d.shape, arr1d.size
(1, (5,), 5)
>>> arr2d = np.array([[1,2,3],[4,5,6],[7,8,9]])
[[1 2 3]
[4 5 6]
[7 8 9]]
>>> arr2d.ndim, arr2d.shape, arr2d.size
(2, (3, 3), 9)
>>> arr3d = np.ones((2, 3, 4))
>>> arr3d.shape
(2, 3, 4) # 2×3×4 的三维数组
1.3 快速创建数组的常用函数
| 函数 | 功能 | 示例 |
|---|---|---|
np.arange(start, stop, step) |
类似 range(),返回 ndarray | np.arange(0, 20, 3) |
np.linspace(start, stop, num) |
等间隔取 num 个点 | np.linspace(0, 1, 5) |
np.zeros(shape) |
全0数组 | np.zeros((2,3)) |
np.ones(shape, dtype) |
全1数组 | np.ones((2,3), dtype=np.int16) |
np.eye(N) |
N×N 单位矩阵 | np.eye(3) |
np.diag(v) |
对角矩阵 | np.diag([1,2,3]) |
上机实测
lua
>>> np.arange(0, 20, 3)
array([ 0, 3, 6, 9, 12, 15, 18])
>>> np.linspace(0, 1, 5)
array([0. , 0.25, 0.5 , 0.75, 1. ])
>>> np.zeros((2, 3))
array([[0., 0., 0.],
[0., 0., 0.]])
>>> np.eye(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
>>> np.diag([1, 2, 3])
array([[1, 0, 0],
[0, 2, 0],
[0, 0, 3]])
实验2:数组运算
2.1 逐元素运算
NumPy 的算术运算符(+ - * / **)对数组执行逐元素运算(element-wise), 要求两个数组形状相同,或满足广播规则。
less
逐元素运算 vs 矩阵乘法
┌────────────────────────────────────────────────────────┐
│ 运算 │ 运算符/函数 │ 说明 │
│────────────│──────────────────│───────────────────────────│
│ 逐元素加 │ a + b │ 对应位置相加 │
│ 逐元素乘 │ a * b │ 对应位置相乘(不是矩阵乘) │
│ 逐元素除 │ a / b │ 对应位置相除 │
│ 矩阵乘法 │ a @ b 或 np.dot │ 内积 / 矩阵乘法 │
└────────────────────────────────────────────────────────┘
上机实测
css
>>> a = np.array([1, 2, 3, 4])
>>> b = np.array([10, 20, 30, 40])
>>> a + b
array([11, 22, 33, 44])
>>> a * b
array([ 10, 40, 90, 160])
>>> b / a
array([10., 10., 10., 10.])
>>> a ** 2
array([ 1, 4, 9, 16])
>>> np.sqrt(b)
array([3.16227766, 4.47213595, 5.47722558, 6.32455532])
>>> np.exp(a)
array([ 2.71828183, 7.3890561 , 20.08553692, 54.59815003])
2.2 标量广播(Broadcasting)
标量可以与任意形状的数组直接运算,NumPy 自动将标量"广播"到数组的每个元素。
lua
Broadcasting 规则
┌──────────────────────────────────────────────────┐
│ 规则:从最右维度向左对齐,若 │
│ - 维度大小相等 → 兼容 │
│ - 其中一个为 1 → 广播 │
│ - 其中一个不存在 → 广播 │
│ - 其他情况 → 报错 ValueError │
└──────────────────────────────────────────────────┘
示例:(3, 1) + (1, 4) → (3, 4)
[[1] + [[10, 20, 30, 40]]
[2] ↓ 广播
[3]]
= [[11, 21, 31, 41],
[12, 22, 32, 42],
[13, 23, 33, 43]]
上机实测
css
>>> a = np.array([1, 2, 3, 4])
>>> a + 100
array([101, 102, 103, 104])
>>> a * 3
array([ 3, 6, 9, 12])
>>> np.power(a, 3) # a 的每个元素的三次方
array([ 1, 8, 27, 64], dtype=int32)
2.3 矩阵乘法(注意:不是 *)
⚠️ 重要 :* 是逐元素乘法,矩阵乘法用 @ 或 np.dot() 或 np.matmul()。
上机实测
lua
>>> A = np.array([[1, 2], [3, 4]])
>>> B = np.array([[5, 6], [7, 8]])
>>> A * B # 逐元素乘法(不是矩阵乘法!)
array([[ 5, 12],
[21, 32]])
>>> A @ B # 矩阵乘法(正确)
array([[19, 22],
[43, 50]])
>>> np.dot(A, B) # 等价写法
array([[19, 22],
[43, 50]])
实验3:数组切片与索引
3.1 一维数组切片
NumPy 数组切片语法与 Python list 相同,但有一个关键区别:
sql
数组切片 = 视图(view)← 修改会影响原数组!
列表切片 = 副本(copy)← 修改不影响原列表
上机实测
ini
>>> a = np.arange(10, 30, 2) # [10 12 14 16 18 20 22 24 26 28]
>>> a[2] # 第三个元素(索引从0开始)
14
>>> a[-1] # 最后一个元素
28
>>> a[2:7] # 切片 [2, 7)
array([14, 16, 18, 20, 22])
>>> a[:5] # 前5个
array([10, 12, 14, 16, 18])
>>> a[::2] # 步长2(隔一个取)
array([10, 14, 18, 22, 26])
>>> a[::-1] # 反转
array([28, 26, 24, 22, 20, 18, 16, 14, 12, 10])
⚠️ 视图 vs 副本 --- 经典踩坑
css
>>> b = a[2:7] # b 是 a 的视图(view)
>>> b[0] = 999 # 修改 b 会影响 a!
>>> b
array([999, 16, 18, 20, 22])
>>> a # a 被修改了!
array([ 10, 12, 999, 16, 18, 20, 22, 24, 26, 28])
# 解决方案:使用 .copy()
>>> c = a[2:7].copy() # c 是独立副本
>>> c[0] = 0
>>> a # a 不受影响
array([ 10, 12, 999, 16, 18, 20, 22, 24, 26, 28])
3.2 二维数组切片
多维数组使用 [行切片, 列切片] 语法。
lua
二维数组切片示意图
┌──────────────────────────────────────────────────┐
│ m = [[ 1, 2, 3, 4], │
│ [ 5, 6, 7, 8], │
│ [ 9, 10, 11, 12], │
│ [13, 14, 15, 16]] │
│ │
│ m[1, 2] = 7 → 第1行第2列 │
│ m[0:2, 1:3] = │
│ [[2, 3], → 行0~1,列1~2 │
│ [6, 7]] │
│ m[:, ::2] = │
│ [[1, 3], → 所有行,偶数列 │
│ [5, 7], │
│ [9, 11], │
│ [13, 15]] │
└──────────────────────────────────────────────────┘
上机实测
lua
>>> m = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
>>> m[1, 2]
7
>>> m[0:2, 1:3]
array([[2, 3],
[6, 7]])
>>> m[:, ::2] # 所有行,偶数列
array([[ 1, 3],
[ 5, 7],
[ 9, 11],
[13, 15]])
>>> m[1:, :3] # 第1行起,前3列
array([[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]])
3.3 花式索引(Fancy Indexing)
用整数数组作为索引,一次性取出多个任意位置的元素。
上机实测
lua
>>> arr = np.array([10, 20, 30, 40, 50, 60, 70])
>>> arr[[0, 2, 5]] # 取索引 0, 2, 5 的元素
array([10, 30, 60])
>>> mat = np.array([[1, 2],[3, 4],[5, 6],[7, 8]])
>>> mat[[0, 2, 3]] # 取第0, 2, 3行
array([[1, 2],
[5, 6],
[7, 8]])
3.4 布尔索引(过滤)
用布尔数组作为索引,筛选出满足条件的元素。
上机实测
scss
>>> data = np.array([1, -2, 3, -4, 5, -6, 7])
>>> data[data > 0]
array([1, 3, 5, 7])
>>> data[data < 0]
array([-2, -4, -6])
>>> mask = np.abs(data) > 3
>>> mask
array([False, False, False, True, True, True, True])
>>> data[mask]
array([-4, 5, -6, 7])
实验4:数组形状操作
4.1 reshape:改变形状
reshape() 不改变元素总数,只改变"看待"数组的方式。 -1 表示"自动计算该维度大小"。
上机实测
lua
>>> a = np.arange(12)
>>> a.reshape(3, 4)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> b = np.arange(24)
>>> b.reshape(2, 3, -1) # -1 自动计算为 4
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
4.2 ravel / flatten:展平
| 方法 | 行为 | 说明 |
|---|---|---|
arr.ravel() |
返回视图(如果可能) | 修改返回值会影响原数组 |
arr.flatten() |
始终返回副本 | 修改返回值不影响原数组 |
上机实测
scss
>>> m = np.array([[1, 2, 3],[4, 5, 6]])
>>> m.ravel()
array([1, 2, 3, 4, 5, 6])
>>> m.flatten()
array([1, 2, 3, 4, 5, 6])
4.3 拼接与堆叠
scss
数组拼接函数对比
┌──────────────────────────────────────────────────┐
│ 函数 │ 说明 │
│─────────────────────│─────────────────────────────│
│ np.concatenate() │ 沿指定轴拼接(最通用) │
│ np.vstack() │ 垂直堆叠(row方向) │
│ np.hstack() │ 水平堆叠(column方向) │
└──────────────────────────────────────────────────┘
上机实测
lua
>>> A = np.arange(6).reshape(2, 3)
>>> B = np.arange(6).reshape(2, 3) + 10
>>> A
array([[0, 1, 2],
[3, 4, 5]])
>>> B
array([[10, 11, 12],
[13, 14, 15]])
>>> np.vstack([A, B]) # 垂直堆叠
array([[ 0, 1, 2],
[ 3, 4, 5],
[10, 11, 12],
[13, 14, 15]])
>>> np.hstack([A, B]) # 水平堆叠
array([[ 0, 1, 2, 10, 11, 12],
[ 3, 4, 5, 13, 14, 15]])
实验5:统计函数
NumPy 提供完整的统计函数,支持沿指定轴(axis)计算。
ini
axis 参数图解
┌──────────────────────────────────────────────────┐
│ arr = [[1, 5, 3], │
│ [9, 2, 8], │
│ [4, 7, 6]] shape=(3,3) │
│ │
│ axis=None(默认)→ 对所有元素计算 │
│ axis=0 → 沿行方向(跨行)→ 结果形状(3,) │
│ axis=1 → 沿列方向(跨列)→ 结果形状(3,) │
└──────────────────────────────────────────────────┘
上机实测
python
>>> scores = np.array([85, 92, 78, 95, 88, 76, 93, 81, 69, 90])
>>> np.min(scores), np.max(scores)
(69, 95)
>>> np.mean(scores) # 均值
84.7
>>> np.median(scores) # 中位数
86.5
>>> np.std(scores) # 标准差
8.05
>>> np.sum(scores) # 求和
847
>>> np.cumsum(scores) # 累计和
array([ 85, 177, 255, 350, 438, 514, 607, 688, 757, 847])
沿轴统计
ini
>>> matrix = np.array([[1,5,3],[9,2,8],[4,7,6]])
>>> np.mean(matrix, axis=0) # 每列均值
array([4.66666667, 4.66666667, 5.66666667])
>>> np.mean(matrix, axis=1) # 每行均值
array([3. , 6.33333333, 5.66666667])
实验6:随机数(np.random)
6.1 设置随机种子
python
>>> np.random.seed(42) # 固定种子,保证结果可复现
6.2 常用随机函数
| 函数 | 功能 | 示例 |
|---|---|---|
np.random.rand(d0, d1, ...) |
[0,1) 均匀分布 | np.random.rand(3,4) |
np.random.randn(d0, d1, ...) |
标准正态分布 N(0,1) | np.random.randn(3,4) |
np.random.randint(low, high, size) |
[low, high) 整数 | np.random.randint(1, 101, (2,5)) |
np.random.choice(a, size) |
从 a 中随机抽样 | np.random.choice([1,2,3], 5) |
np.random.shuffle(arr) |
原地打乱数组 | np.random.shuffle(arr) |
np.random.normal(loc, scale, size) |
正态分布 N(loc, scale²) | np.random.normal(70, 10, 10) |
上机实测(种子=42)
lua
>>> np.random.seed(42)
>>> np.random.rand(3, 4)
array([[0.37454012, 0.95071431, 0.73199394, 0.59865848],
[0.15601864, 0.15599452, 0.05808361, 0.86617615],
[0.60111501, 0.70807258, 0.02058449, 0.96990985]])
>>> np.random.randn(3, 4)
array([[-0.46947439, 0.54256004, -0.46341769, -0.46572975],
[ 0.24196227, -1.91328024, -1.72491783, -0.56228753],
[-1.01283112, 0.31424733, -0.90802408, -1.4123037 ]])
>>> np.random.randint(1, 101, size=(2, 5))
array([[62, 62, 47, 62, 51],
[55, 64, 3, 51, 7]])
实验7:线性代数(np.linalg)
np.linalg 模块提供完整的线性代数运算。
上机实测
lua
>>> import numpy as np
>>> M = np.array([[4, 7], [2, 6]])
>>> np.linalg.inv(M) # 逆矩阵
array([[ 0.6, -0.7],
[-0.2, 0.4]])
>>> np.linalg.det(M) # 行列式
10.0
>>> np.linalg.solve([[3, 1], [1, -2]], [9, -2]) # 解方程组 3x+y=9, x-2y=-2
array([2.28571429, 2.14285714]) # x≈2.29, y≈2.14
注意 :上面方程组的精确解是 x=2, y=3,但用浮点求解得到近似值。 若使用整数矩阵:
np.linalg.solve(np.array([[3,1],[1,-2]], dtype=float), [9,-2])可得更精确结果。
实验8:综合实战 --- 图像灰度化处理
用 NumPy 模拟 RGB 图像转灰度图像,展示向量化运算的威力。
灰度化公式(ITU-R BT.601 标准):
ini
Y = 0.299 × R + 0.587 × G + 0.114 × B
上机实测
ini
>>> np.random.seed(0)
>>> img_rgb = np.random.randint(0, 256, size=(4, 6, 3), dtype=np.uint8)
>>> img_rgb.shape
(4, 6, 3) # (高, 宽, 通道)
# 原始 RGB 图像(前2行)
行0: [[172 10 127]
[140 47 170]
[196 151 117]
[166 22 183]
[192 204 33]
[216 67 179]]
行1: [[ 78 154 251]
[ 82 162 219]
...
>>> weights = np.array([0.299, 0.587, 0.114])
>>> img_gray = np.dot(img_rgb, weights).astype(np.uint8)
>>> img_gray.shape
(4, 6) # 灰度图只有一个通道
>>> img_gray
array([[ 71, 88, 160, 83, 180, 124],
[142, 144, 141, 116, 196, 129],
[211, 69, 151, 135, 118, 91],
[ 65, 87, 190, 73, 213, 188]], dtype=uint8)
踩坑记录
踩坑1:数组切片是视图,不是副本
python
>>> a = np.arange(10)
>>> b = a[:5] # b 是 a 的视图!
>>> b[0] = 999
>>> a[0] # a 被修改了!
999
# 正确做法
>>> c = a[:5].copy() # 显式创建副本
踩坑2:* 不是矩阵乘法
python
>>> A = np.array([[1, 2], [3, 4]])
>>> B = np.array([[5, 6], [7, 8]])
>>> A * B # 逐元素乘法,不是矩阵乘法!
array([[ 5, 12],
[21, 32]])
>>> A @ B # 正确的矩阵乘法
array([[19, 22],
[43, 50]])
踩坑3:axis 参数的含义
axis=i 表示"沿第 i 轴操作",即跨第 i 轴聚合。
python
>>> arr = np.array([[1, 2, 3],
... [4, 5, 6]])
>>> np.sum(arr, axis=0) # 跨行求和 → 每列的和
array([5, 7, 9])
>>> np.sum(arr, axis=1) # 跨列求和 → 每行的和
array([ 6, 15])
踩坑4:Ubuntu 24.04 pip 安装需要 --break-system-packages
bash
# 报错:externally-managed-environment
$ pip3 install numpy
error: externally-managed-environment
# 解决方案1:使用 apt(推荐,更快)
$ apt-get install -y python3-numpy
# 解决方案2:使用 --break-system-packages
$ pip3 install --break-system-packages numpy
# 解决方案3:使用 venv 虚拟环境(最佳实践)
$ python3 -m venv myenv
$ source myenv/bin/activate
(myenv) $ pip install numpy
踩坑5:reshape(-1, n) 的 -1 自动推断
python
>>> a = np.arange(12)
>>> a.reshape(-1, 3) # -1 自动计算为 4
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
总结
| 核心概念 | 关键函数/方法 | 说明 |
|---|---|---|
| 数组创建 | np.array() / np.arange() / np.zeros() |
多种创建方式 |
| 数组属性 | .shape / .dtype / .ndim |
了解数组的"元信息" |
| 逐元素运算 | + - * / ** / np.sqrt() / np.exp() |
自动广播 |
| 矩阵乘法 | @ / np.dot() / np.matmul() |
与 * 区分! |
| 切片索引 | arr[a:b] / arr[[i,j]] / arr[mask] |
视图 vs 副本 |
| 形状操作 | reshape() / ravel() / concatenate() |
灵活变换形状 |
| 统计函数 | mean() / median() / std() / percentile() |
支持 axis 参数 |
| 随机数 | rand() / randn() / seed() |
设置种子保证可复现 |
| 线性代数 | np.linalg.inv() / solve() / eig() |
科学计算核心 |
参考资料
- NumPy 官方文档:numpy.org/doc/
- NumPy 快速入门:numpy.org/doc/stable/...
- SciPy Lecture Notes:scipy-lectures.org/
实战服务器:ecs-98e5 | Python 3.12.3 | NumPy 1.26.4 | 2026-06-29
作者:主人 | 服务器:华为云 FlexusX x2e.8u.16g