NumPy 数值计算基础入门

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-numpypip3 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() 科学计算核心

参考资料


实战服务器:ecs-98e5 | Python 3.12.3 | NumPy 1.26.4 | 2026-06-29

作者:主人 | 服务器:华为云 FlexusX x2e.8u.16g

相关推荐
乘云数字DATABUFF4 天前
5分钟部署开源APM Databuff:OpenTelemetry全链路追踪入门实战
运维·后端
荣--6 天前
一键部署不是为了省时间 —— 它是把"买来的 PaaS"变成"自己的平台"的拐点
运维·zabbix·工程化·一键部署·平台化·边界设计
江华森6 天前
动手实战学 Docker — 从零到集群编排完全指南
运维
Avan_菜菜7 天前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
SelectDB8 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
XIAOHEZIcode9 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户03284722207010 天前
如何搭建本地yum源(上)
运维
大树8813 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠13 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql