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

>>> import numpy as np
>>> np.__version__
1.26.4

常用 dtype 速查表

dtype含义字节取值范围
np.int88位有符号整数1[-128, 127]
np.int6464位有符号整数(默认 int)8[-2⁶³, 2⁶³-1]
np.uint88位无符号整数1[0, 255]
np.float32单精度浮点4约 ±3.4×10³⁸
np.float64双精度浮点(默认 float)8约 ±1.8×10³⁰⁸
np.bool_布尔类型1True / False

⚠️ 踩坑:Ubuntu 24.04 的 pip3 install numpy 会报 externally-managed-environment 错误。
解决方案:apt-get install python3-numpypip3 install --break-system-packages numpy

上机实测

>>> 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 多维数组创建

ndarray 核心属性
┌─────────────────────────────────────────┐
│ 属性      │ 含义              │ 示例           │
│───────────│──────────────────│────────────────│
│ .ndim     │ 维度数量(轴数) │ 2              │
│ .shape    │ 各维度大小        │ (3, 4)        │
│ .size     │ 总元素个数        │ 12             │
│ .dtype    │ 元素数据类型      │ dtype('int64') │
│ .itemsize │ 每元素字节数      │ 8              │
│ .nbytes   │ 数组总字节数      │ 96             │
└─────────────────────────────────────────┘

上机实测

>>> 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(),返回 ndarraynp.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])

上机实测

>>> 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),
要求两个数组形状相同,或满足广播规则。

逐元素运算 vs 矩阵乘法
┌────────────────────────────────────────────────────────┐
│ 运算       │ 运算符/函数      │ 说明                       │
│────────────│──────────────────│───────────────────────────│
│ 逐元素加   │ a + b            │ 对应位置相加                │
│ 逐元素乘   │ a * b            │ 对应位置相乘(不是矩阵乘) │
│ 逐元素除   │ a / b            │ 对应位置相除                │
│ 矩阵乘法   │ a @ b 或 np.dot │ 内积 / 矩阵乘法            │
└────────────────────────────────────────────────────────┘

上机实测

>>> 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 自动将标量"广播"到数组的每个元素。

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]]

上机实测

>>> 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()

上机实测

>>> 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 相同,但有一个关键区别

数组切片 = 视图(view)← 修改会影响原数组!
列表切片 = 副本(copy)← 修改不影响原列表

上机实测

>>> 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 副本 — 经典踩坑

>>> 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 二维数组切片

多维数组使用 [行切片, 列切片] 语法。

二维数组切片示意图
┌──────────────────────────────────────────────────┐
│  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]]                             │
└──────────────────────────────────────────────────┘

上机实测

>>> 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)

用整数数组作为索引,一次性取出多个任意位置的元素。

上机实测

>>> 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 布尔索引(过滤)

用布尔数组作为索引,筛选出满足条件的元素。

上机实测

>>> 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 表示"自动计算该维度大小"。

上机实测

>>> 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()始终返回副本修改返回值不影响原数组

上机实测

>>> 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 拼接与堆叠

数组拼接函数对比
┌──────────────────────────────────────────────────┐
│ 函数                │ 说明                         │
│─────────────────────│─────────────────────────────│
│ np.concatenate()    │ 沿指定轴拼接(最通用)       │
│ np.vstack()        │ 垂直堆叠(row方向)          │
│ np.hstack()        │ 水平堆叠(column方向)       │
└──────────────────────────────────────────────────┘

上机实测

>>> 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)计算。

axis 参数图解
┌──────────────────────────────────────────────────┐
│  arr = [[1, 5, 3],                         │
│          [9, 2, 8],                         │
│          [4, 7, 6]]      shape=(3,3)        │
│                                              │
│  axis=None(默认)→ 对所有元素计算              │
│  axis=0          → 沿行方向(跨行)→ 结果形状(3,)  │
│  axis=1          → 沿列方向(跨列)→ 结果形状(3,)  │
└──────────────────────────────────────────────────┘

上机实测

>>> 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])

沿轴统计

>>> 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 设置随机种子

>>> 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)

>>> 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 模块提供完整的线性代数运算。

上机实测

>>> 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 标准):

Y = 0.299 × R + 0.587 × G + 0.114 × B

上机实测

>>> 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:数组切片是视图,不是副本

>>> a = np.arange(10)
>>> b = a[:5]       # b 是 a 的视图!
>>> b[0] = 999
>>> a[0]             # a 被修改了!
999

# 正确做法
>>> c = a[:5].copy()   # 显式创建副本

踩坑2:* 不是矩阵乘法

>>> 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 轴聚合

>>> 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

# 报错: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 自动推断

>>> 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 官方文档:https://numpy.org/doc/
  • NumPy 快速入门:https://numpy.org/doc/stable/user/quickstart.html
  • SciPy Lecture Notes:https://scipy-lectures.org/

实战服务器:ecs-98e5 | Python 3.12.3 | NumPy 1.26.4 | 2026-06-29
作者:主人 | 服务器:华为云 FlexusX x2e.8u.16g

Logo

免费领 150 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐