1. 背景
1.1 为什么需要 numpy
python 是一门上手极快、生态丰富的语言,但原生 python 在数值计算上存在三个硬伤:
- python 的 list 是对象指针数组:每个元素都是 pyobject*,存 100 万个浮点数要额外承担 100 万个对象的堆分配与引用计数开销,内存与速度双双不可接受。
- 逐元素循环解释执行:for i in range(n): s += a[i] 每个字节码指令都要经过解释器分派,比编译型语言慢 50~100 倍。
- 缺少多维数组、向量化、广播等数值语义:做矩阵运算、图像处理、信号滤波需要手写嵌套循环,极易出错。
numpy(numerical python)的解法是用 c 语言实现底层的同质化多维数组(ndarray),把"逐元素循环"下沉到编译好的 c 内核里,python 侧只负责描述"对整块数据做什么",这就是向量化(vectorization)。
1.2 在技术栈中的定位
底层数值内核:numpy(ndarray / ufunc / 广播)
↑
科学计算层:scipy(优化/线性代数/信号/统计)
数据分析层:pandas(dataframe,基于 numpy)、xarray
可视化层:matplotlib(绘图基于 numpy 数组)
机器学习层:scikit-learn / pytorch / tensorflow(tensor 语义与 numpy 高度一致)
numpy 是 python 数据科学栈的"地基":pandas 的 dataframe 内部就是 numpy 数组的封装,pytorch 的 torch.tensor 与 ndarray 可以零拷贝互转(.numpy() / torch.from_numpy()),onnx runtime 的输入输出也常以 numpy 数组作为载体。掌握 numpy 是进入 ai / 数据分析 / 工业数据处理的前提。
1.3 与工业数采项目的结合点
- 批量数据清洗:采集到的 cnc 点位原始数据(电压、电流、温度、主轴转速)加载为 ndarray,用向量化表达式一次完成去野值、归一化、滑窗均值。
- ipqc 检测数据统计:cp/cpk 计算、分布直方图、分位数统计,全部可用 numpy 一行完成。
- kafka 消息体解码后的批处理:批量 json → ndarray → 聚合统计 → 写入存储,替代逐条循环。
- ai 质检前置:图像/振动信号做标准化、reshape、dtype 转换后喂给 onnx runtime / pytorch 模型。
2. 核心概念与 api 说明
2.1 ndarray:同质化多维数组
ndarray 是 numpy 的核心数据结构,与 python list 的本质区别:
| 维度 | python list | numpy ndarray |
|---|---|---|
| 元素类型 | 可混合,任意对象 | 同质(单一 dtype),连续内存 |
| 内存布局 | 指针数组 + 分散对象 | c 连续内存块 + shape + strides |
| 逐元素运算 | 需 for 循环 | 内置 ufunc 向量化 |
| 切片 | 拷贝语义 | 视图(view)语义,零拷贝 |
| 广播 | 无 | 有(broadcasting) |
创建数组的常用 api:
import numpy as np a = np.array([1, 2, 3]) # 从列表创建(默认 int64 或按数据推断) b = np.zeros((2, 3)) # 全 0,shape=(2,3),默认 float64 c = np.ones((2, 3), dtype=np.int32) # 全 1,指定 dtype d = np.full((2, 2), 7.5) # 全填充 7.5 e = np.arange(0, 10, 2) # [0, 2, 4, 6, 8],类似 range f = np.linspace(0, 1, 5) # [0., 0.25, 0.5, 0.75, 1.],均匀 5 点(含端点) g = np.eye(3) # 3x3 单位阵 h = np.random.rand(3, 3) # [0,1) 均匀分布 i = np.random.randn(1000) # 标准正态分布 j = np.empty((3, 3)) # 未初始化内存(危险,通常不推荐)
2.2 dtype:数据类型系统
每个 ndarray 有且仅有一个 dtype,常见类型:
| dtype | 说明 |
|---|---|
| int8/int16/int32/int64 | 有符号整数(位宽决定范围) |
| uint8/uint16/uint32/uint64 | 无符号整数 |
| float16/float32/float64 | 半/单/双精度浮点 |
| complex64/complex128 | 复数 |
| bool | 布尔 |
| object | python 对象指针(失去性能优势) |
| str_ / unicode_ | 字符串 |
要点:
a = np.array([1, 2, 3], dtype=np.float32)
a.dtype # dtype('float32')
a.astype(np.int32) # 显式转换(返回新数组)
a.itemsize # 4,每元素字节数
a.nbytes # 12,总字节数 = size * itemsize
dtype 与内存对齐直接相关,工业数据采集时常用 uint16 存储 adc 原始值、float32 存储归一化特征,可大幅压缩内存(相比 float64 省一半)。
2.3 shape / reshape / ndim / size
a = np.zeros((2, 3, 4)) # 3 维数组 a.shape # (2, 3, 4) a.ndim # 3 a.size # 24 a.reshape(6, 4) # 视图重排(只要内存连续即可) a.reshape(-1, 4) # -1 表示自动推断:24/4=6 a.flatten() # 复制展平(返回拷贝) a.ravel() # 展平(尽可能返回视图)
关键区别:reshape 返回视图(view)而非拷贝——修改 reshape 后的数组会改变原数组(只要内存布局兼容)。flatten() 才保证是拷贝。需要真正独立的副本时用 .copy()。
2.4 索引与切片
numpy 切片与 python list 切片语法相同,但语义是视图:
a = np.arange(12).reshape(3, 4) # array([[ 0, 1, 2, 3], # [ 4, 5, 6, 7], # [ 8, 9, 10, 11]]) a[1] # 第二行:array([4, 5, 6, 7]) a[1, 2] # 6,逗号分隔多维索引 a[:, 1] # 第二列:array([1, 5, 9]) a[0:2, 1:3] # 子块视图 a[::-1] # 行反转(负步长) a[a > 5] # 布尔掩码索引:array([ 6, 7, 8, 9, 10, 11])
花式索引(fancy indexing):
idx = [0, 2] a[idx] # 取第 0、2 行(返回拷贝,不是视图!) mask = np.array([true, false, true, false]) a[:, mask] # 按布尔掩码选列
注意:切片 → 视图;花式索引 / 布尔索引 → 拷贝。这个差异是大量隐蔽 bug 的来源。
2.5 广播(broadcasting)
广播规则:从后往前对齐维度,维度相等或其一为 1 时兼容,结果形状取各维度最大值。
a = np.zeros((3, 4)) b = np.array([1, 2, 3, 4]) # shape (4,) a + b # 每行加 b → (3,4) ✔ c = np.array([[1], [2], [3]]) # shape (3,1) a + c # 每列加 c → (3,4) ✔ d = np.array([1, 2, 3]) # shape (3,) a + d # 对齐:(3,4) vs (3,) → (3,4) vs (3,?) 报错!valueerror
广播是在 c 层"逻辑重复"数据,不产生实际拷贝,性能远好于 np.tile 显式铺开。
2.6 ufunc:通用函数
ufunc 是对数组逐元素运算的 c 内核函数,语法上表现为运算符:
x = np.array([1.0, 2.0, 3.0]) y = np.array([4.0, 5.0, 6.0]) x + y # np.add(x, y) x * 2 # np.multiply(x, 2) x ** 2 # np.power(x, 2) np.sqrt(x) # 逐元素开方 np.exp(x), np.log(x), np.sin(x) np.clip(x, 1.5, 2.5) # 限幅(工业去野值常用) np.where(x > 1.5, x, 0.0) # 条件选择
ufunc 支持 out 参数原地写,避免临时分配:
r = np.empty_like(x) np.add(x, 2.0, out=r) # 结果写入 r,不产生中间数组
2.7 聚合与统计
data = np.random.randn(10000) data.sum() # 求和 data.mean() # 均值 data.std(), data.var() # 标准差、方差(默认总体,ddof=1 为样本) data.min(), data.max() data.argmin(), data.argmax() # 极值索引 data.ptp() # 峰峰值 max-min data.median() # 中位数 np.percentile(data, [25, 50, 75]) # 分位数 np.quantile(data, 0.95) # 分位点 np.cumsum(data) # 累计和 np.diff(data) # 相邻差分 np.corrcoef(x, y) # 相关系数
指定轴聚合(axis 参数是最常踩坑的点之一):
m = np.random.rand(3, 4) m.mean(axis=0) # 沿第 0 轴(行方向)求均值 → 每列一个值,shape (4,) m.mean(axis=1) # 沿第 1 轴(列方向)求均值 → 每行一个值,shape (3,) m.mean() # 全数组标量
记忆口诀:axis=k 就是把第 k 维"压掉"。(3,4) 沿 axis=0 求均值 → (4,)。
2.8 线性代数(numpy.linalg)
import numpy.linalg as la a = np.array([[3., 1.], [1., 2.]]) b = np.array([9., 8.]) la.det(a) # 行列式 la.inv(a) # 求逆 la.solve(a, b) # 解线性方程组 a x = b → array([2., 3.]),比 inv 快且数值稳 la.eig(a) # 特征值、特征向量 la.eigvalsh(a) # 对称矩阵特征值(更快) la.svd(a) # svd 分解 la.norm(b) # 向量/矩阵范数 la.qr(a) # qr 分解
矩阵乘法:
a @ b # 矩阵乘法(推荐,python 3.5+) np.matmul(a, b) # 等价 np.dot(a, b) # 高维语义与 matmul 有差异 a * b # 注意!这是逐元素乘(hadamard),不是矩阵乘!
2.9 随机数(np.random,新版 generator api)
新版推荐 default_rng(),而不是旧的 np.random.rand/randn/seed:
rng = np.random.default_rng(42) # 可复现种子 rng.random((3, 3)) # [0,1) 均匀 rng.normal(0, 1, (1000,)) # 正态 rng.integers(0, 100, 10) # 整数 rng.permutation(10) # 排列 rng.choice(10, size=5, replace=false) # 无放回抽样 rng.shuffle(x) # 原地洗牌
2.10 输入输出
np.save('data.npy', arr) # 二进制(推荐,保留 dtype/shape)
arr2 = np.load('data.npy')
np.savez('data.npz', a=arr1, b=arr2) # 多数组压缩打包
d = np.load('data.npz'); d['a']
np.savetxt('data.csv', arr, delimiter=',') # 文本(慢,仅小数据)
arr3 = np.genfromtxt('data.csv', delimiter=',')
工业采集场景大数组用 .npy 持久化;与 pandas 互通:pd.dataframe(arr) / df.to_numpy()。
2.11 与外部生态互转
import torch, pandas as pd
# pandas ↔ numpy
df = pd.dataframe(arr, columns=['c1', 'c2'])
arr_back = df.to_numpy() # 注意:混合类型列会升为 object 或 string
# pytorch ↔ numpy(零拷贝,共享底层内存!)
t = torch.from_numpy(arr) # 共享内存
arr_view = t.numpy() # 共享内存
# 注意:gpu tensor 需先 .cpu();修改一方影响另一方
# opencv ↔ numpy(bgr 图像本质就是 ndarray)
import cv2
img = cv2.imread('a.jpg') # 返回 ndarray,shape=(h, w, 3),dtype=uint8
3. 详细使用说明
3.1 环境安装
# pip 安装 pip install numpy # conda(推荐,带 mkl/openblas 加速) conda install numpy # 验证 python -c "import numpy; print(numpy.__version__)"
性能提示:conda 分发的 numpy 默认链接 mkl/openblas,@/la.solve 等大规模矩阵运算通常比 pip 自编译版本更快;pip 版在纯 cpu 小数组上差异不大。
3.2 示例一:一维信号的滑窗均值滤波(去噪)
工业采集的振动/温度信号常带尖峰噪声,用滑动窗口均值平滑:
import numpy as np
def moving_average(x, window=5):
# 用 cumsum 实现 o(n) 滑窗均值,比逐窗口循环快一个数量级
c = np.cumsum(np.insert(x, 0, 0))
return (c[window:] - c[:-window]) / window
raw = np.array([3.1, 3.2, 12.0, 3.3, 3.0, 3.4, 11.5, 3.2, 3.3]) # 含尖峰
smooth = moving_average(raw, window=3)
print(smooth)
# 期望输出:[6.1 6.16666667 6.1 6.23333333 5.96666667 6.03333333 6.0]
3.3 示例二:批量数据标准化与野值剔除
模拟 cnc 主轴电流采集(10000 点),做 3σ 野值剔除 + z-score 标准化:
import numpy as np
rng = np.random.default_rng(2026)
current = rng.normal(12.5, 0.8, 10000) # 正常电流 ~ n(12.5, 0.8)
current[:50] = rng.uniform(30, 60, 50) # 注入 50 个野值(传感器毛刺)
# 1) 描述统计
print(f"mean={current.mean():.3f}, std={current.std():.3f}")
print(f"min={current.min():.3f}, max={current.max():.3f}")
# 2) 3σ 野值剔除(布尔掩码)
mean, std = current.mean(), current.std()
mask = np.abs(current - mean) <= 3 * std
clean = current[mask]
print(f"剔除 {current.size - clean.size} 个野值,剩余 {clean.size} 点")
# 3) z-score 标准化
normalized = (clean - clean.mean()) / clean.std()
print(f"标准化后 mean={normalized.mean():.6f}, std={normalized.std():.6f}")
# 4) 统计区间分桶(直方图)
counts, edges = np.histogram(clean, bins=20)
3.4 示例三:多元线性回归的最小二乘解(ipqc 数据分析)
用 la.lstsq 拟合 y = a0 + a1x1 + a2x2:
import numpy as np
import numpy.linalg as la
rng = np.random.default_rng(7)
n = 500
x1 = rng.normal(10, 2, n)
x2 = rng.normal(5, 1, n)
true = np.array([3.0, -1.2, 0.8]) # 真实系数 a0, a1, a2
y = true[0] + true[1]*x1 + true[2]*x2 + rng.normal(0, 0.1, n)
# 设计矩阵:首列为 1(截距)
x = np.column_stack([np.ones(n), x1, x2])
coef, residuals, rank, s = la.lstsq(x, y, rcond=none)
print("拟合系数:", np.round(coef, 4)) # 应接近 [3.0, -1.2, 0.8]
# 预测与 r²
y_pred = x @ coef
ss_res = np.sum((y - y_pred) ** 2)
ss_tot = np.sum((y - y.mean()) ** 2)
r2 = 1 - ss_res / ss_tot
print(f"r² = {r2:.4f}")
3.5 示例四:图像预处理(ai 质检前置)
灰度图像转 float32 并归一化到 [0,1],再补成 chw:
import numpy as np
import cv2
img = cv2.imread('part.jpg', cv2.imread_grayscale) # (h, w) uint8
print(img.shape, img.dtype) # (480, 640) uint8
# 归一化:uint8[0,255] → float32[0,1]
x = img.astype(np.float32) / 255.0
# 或就地归一化(省一份内存)
img_norm = cv2.normalize(img, none, 0.0, 1.0, cv2.norm_minmax)
# 加 batch 与 channel 维度:hwc → nchw (1,1,h,w)
x = x[np.newaxis, np.newaxis, :, :]
# 等价:x = np.expand_dims(x, axis=(0, 1))
# 若模型是 rgb 三通道:先复制通道
rgb = np.repeat(x, 3, axis=1) # (1,3,h,w)
3.6 示例五:高性能批量处理模式(内存友好)
工业批量计算避免 python 循环、避免中间大数组:
import numpy as np
# 坏写法:循环 + 逐元素 python 运算(慢 100 倍)
def bad_sum(chunks):
s = 0.0
for c in chunks:
for v in c:
s += v * 2 + 1
return s
# 好写法:一次性向量化
def good_sum(chunks):
arr = np.asarray(chunks) # 列表 → ndarray(尽量一次转换)
return (arr * 2 + 1).sum()
# 内存友好:out= 复用缓冲
buf = np.empty((1000, 64), dtype=np.float32)
for i in range(100):
batch = next_batch() # 假设返回 (1000,64)
np.multiply(batch, 0.5, out=buf) # 结果写 buf,不产生新数组
process(buf)
4. 常错点 / 坑
4.1 视图 vs 拷贝混淆
a = np.arange(12).reshape(3, 4) b = a[0:2] # 视图 b[0, 0] = 999 # 修改 b 会改 a! print(a[0, 0]) # 999 c = a[[0, 1]] # 花式索引 → 拷贝 c[0, 0] = -1 # a 不受影响
规避:需要独立副本时显式 .copy();不确定时可查 np.shares_memory(a, b);写代码前想清楚"我要视图还是要拷贝"。
4.2 reshape 陷阱
a = np.arange(12) b = a.reshape(3, 4) # 视图,共享内存 b[0, 0] = 100 print(a[0]) # 100!a 被改了 # 非连续内存时 reshape 会触发拷贝(语义安全但行为不同) t = a[::2] # 步长切片,非连续 r = t.reshape(3, 2) # 这里实际会拷贝(必要时)
规避:reshape 后不要假设与原数组独立;要独立就用 a.reshape(...).copy()。
4.3 dtype 不匹配:uint8 溢出 / float 精度
x = np.array([250, 250], dtype=np.uint8) y = x + 10 # uint8 溢出回绕!array([4, 4]),不是 260 z = x.astype(np.int32) + 10 # array([260, 260]) ✔ # float 精度 a = np.float32(0.1) + np.float32(0.2) # 0.30000001192092896 # 比较用 np.isclose 而非 == np.isclose(np.float32(0.1) + np.float32(0.2), np.float32(0.3)) # true
规避:图像/adc 数据处理先确认 dtype;浮点比较一律 np.isclose / np.allclose;nan 判断用 np.isnan 而不是 ==(np.nan == np.nan 为 false)。
4.4 axis 方向搞反
m = np.arange(6).reshape(2, 3) # [[0 1 2] # [3 4 5]] m.sum(axis=0) # array([3, 5, 7]) —— 每列和(shape (3,)) m.sum(axis=1) # array([ 3, 12]) —— 每行和(shape (2,))
规避:写前先打印 shape 验证;口诀"axis=k 压掉第 k 维"。
4.5 广播维度不兼容报错
a = np.ones((3, 4)) b = np.ones((3,)) a + b # valueerror: operands could not be broadcast together
规避:手动补齐维度 b[:, np.newaxis] 或 np.expand_dims(b, axis=1);报错时先打印两个 shape 对一下。
4.6 * 是逐元素乘,不是矩阵乘
a = np.array([[1., 2.], [3., 4.]]) b = np.array([[5., 6.], [7., 8.]]) a * b # 逐元素:[[5,12],[21,32]] a @ b # 矩阵乘:[[19,22],[43,50]]
规避:矩阵运算统一用 @,* 只用于逐元素。
4.7 负步长 / 反序切片陷阱
a = np.arange(10) a[::-1] # 反序,ok a[9:0:-1] # 注意:不含索引 0!结果 9..1 a[:0:-1] # 9..1(同样不含 0) a[::-2] # 隔一个取反序
规避:反序直接 a[::-1];要含端点用 a[9::-1]。
4.8 原地修改 += 的共享内存爆炸
a = np.ones((3, 3)) b = a[0:2] # 视图 b += 10 # 修改了 a 的对应块(这是预期的视图行为)
但更隐蔽的是跨库共享:
t = torch.from_numpy(a) # 与 a 共享内存 t.add_(1) # a 也被改!
规避:跨库转换前明确是否需要独立副本:np.array(arr, copy=true) / torch.from_numpy(a.copy())。
4.9 忘记 astype 导致模型推理精度问题
# 错误:图像 uint8 直接喂模型 x = img # uint8 [0,255],模型期望 float32 [0,1] # 正确 x = img.astype(np.float32) / 255.0
规避:喂 ai 模型前检查 dtype 和值域;x.dtype 与 x.min()/max() 是必查项。
4.10 大规模数组的内存翻倍
# 坏:多次中间数组 y = np.sqrt(x) + np.square(x) * 0.5 - 1 # 临时数组峰值可达 3~4 倍 # 好:out= 复用 r = np.empty_like(x) np.square(x, out=r); r *= 0.5; np.add(r, -1, out=r); np.sqrt(x, out=np.add(r, np.square(x, out=r), out=r))
规避:百 mb 级以上数组用 out= 与分块处理;监控 np.info(x) / x.nbytes;内存不足先降 dtype(float64→float32 减半)。
4.11 在 python 循环里逐元素操作 ndarray
# 极慢(性能自杀)
for i in range(len(arr)):
arr[i] = arr[i] * 2 + 1
# 正确:向量化
arr = arr * 2 + 1
规避:凡是"对每个元素做同样操作"一律向量化;循环只在索引依赖(如滑窗因果处理)时保留,并用 numba/cython 加速。
4.12 np.random 新旧 api 混用与不可复现
np.random.seed(42) # 旧全局状态(影响全局,多线程/库间互相污染) rng = np.random.default_rng(42) # 新推荐:局部 generator,互不干扰
规避:统一用 default_rng(seed) 并把 rng 传入函数;生产代码禁用裸 np.random.* 全局函数。
4.13 savetxt 存大数组慢到怀疑人生
np.savetxt('big.csv', huge_arr) # 文本 io,1gb 数组可能数分钟
np.save('big.npy', huge_arr) # 二进制,秒级
规避:中间/大数组一律 .npy;只有对外交换才用文本,且优先 np.savetxt 的 fmt='%.4f' 控制精度与文件体积。
4.14 布尔索引修改的只读视图误用
a = np.arange(10) mask = a % 2 == 0 a[mask] = 0 # 合法,可写 a[mask].sort() # 不合法预期?a[mask] 返回拷贝,sort 只作用在临时拷贝上,a 不变
规避:需按掩码排序用 np.argsort 配合索引。
4.15 nan 污染聚合结果
data = np.array([1.0, np.nan, 3.0]) data.mean() # nan!一个 nan 毁掉整个统计 np.nanmean(data) # 2.0,忽略 nan np.nan_to_num(data, nan=0.0) # 显式替换
规避:采集数据先做 np.isnan 检查;统计一律用 np.nan* 系列(nanmean/nanstd/nanmin/nanmax/nansum)。
4.16 np.copy 与 = 赋值语义
b = a # 只是别名,b 和 a 是同一个对象 b = a.copy() # 深拷贝 b = a[:] # 视图(切片),不是拷贝!
规避:想清楚"别名 / 视图 / 拷贝"三种语义;跨函数传参时若下游会写,先 .copy()。
4.17 大矩阵 la.inv 数值不稳定
# 解方程用 solve 而非 inv x = la.inv(a) @ b # 慢且数值误差大 x = la.solve(a, b) # 快且稳 ✔
规避:解线性方程/最小二乘一律 la.solve/la.lstsq,不要先求逆再乘;条件数大(la.cond(a))时改用正则化或 svd。
4.18 排序与 argsort 混用
a = np.array([3, 1, 2]) a.sort() # 原地排序,返回 none b = np.argsort(a) # 返回索引数组,不改 a c = a[np.argsort(a)] # 非原地排序的推荐方式
规避:要保留原数组用 np.sort(a) 或 a[np.argsort(a)];a.sort() 是原地操作且返回 none,别写 x = a.sort()。
5. 总结
5.1 核心要点速记
- ndarray 是同质化连续内存数组,性能来自 c 内核 + 向量化,python 循环是性能杀手。
- 切片=视图、花式索引=拷贝;需要独立数据显式 .copy()。
- 广播消除显式铺开循环,从后往前对齐、维度相等或为 1 才兼容。
- @ 是矩阵乘,* 是逐元素乘,别混。
- axis=k 压掉第 k 维,聚合前先打印 shape 验证。
- dtype 决定内存与精度:图像 uint8→float32、浮点比较用 np.isclose、nan 用 np.nan* 系列。
- 矩阵求解用 la.solve/lstsq 而非 la.inv。
- 随机数用 np.random.default_rng(seed),保证可复现且不污染全局。
- 大数组用 .npy 持久化、用 out= 复用缓冲,避免内存翻倍。
- 跨库转换(pytorch/opencv/pandas)共享内存,一方修改会波及另一方。
5.2 适用场景
| 场景 | 推荐 |
|---|---|
| 中小规模数值计算、数据分析、教学 | numpy 直接够用 |
| 表格型数据清洗聚合 | pandas(底层就是 numpy) |
| 机器学习建模 | scikit-learn / pytorch(输入输出与 numpy 无缝) |
| 深度学习推理部署 | onnx runtime / pytorch + numpy 前后处理 |
| 大规模矩阵/线性代数(>10⁴ 维度) | 考虑 gpu(pytorch/cupy)或 c++ eigen |
| 需要 gpu 加速的 ndarray 运算 | cupy(api 兼容 numpy) |
5.3 工业数采实践建议
- 采集通道数据结构化:每个通道(主轴电流/进给速度/温度)存为独立 float32 数组,配套时间戳数组,便于向量化统计。
- 实时滑窗处理:用 cumsum 滑窗均值 / np.roll 做差分,避免 python 循环;50 万点/秒级别 cpu 完全可承受。
- 异常检测组合拳:3σ 阈值 + 分位数 + 滑动窗口统计,全部一行 numpy 完成,可作为 kafka 消费端的批量预处理步骤。
- ai 质检链路:cv2.imread → astype(np.float32)/255 → np.expand_dims → ort.run → np.argmax,与 onnx runtime 篇无缝衔接。
- 性能自检:处理 100 万点若耗时超过几十毫秒,优先怀疑 python 循环和临时数组,而不是 numpy 本身。
5.4 faq 速查表
| 问题 | 答案 |
|---|---|
| 切片会不会拷贝? | 不会,切片是视图;需要拷贝用 .copy() |
| a.reshape(-1) 是什么意思? | 展平为一维,-1 由总元素数自动推断 |
| 如何优雅地加一维? | np.newaxis 或 np.expand_dims(a, axis=k) |
| np.dot 和 @ 有何区别? | 一维/二维等价;高维 np.dot 是"后轴和前轴"收缩,@ 是标准矩阵乘,推荐 @ |
| 如何判断两个数组共享内存? | np.shares_memory(a, b) |
| 数组里有 nan 怎么统计? | 用 np.nanmean/nanstd/nanmin/... 或先 np.isnan 掩码剔除 |
| 如何让随机结果可复现? | rng = np.random.default_rng(固定种子),并始终使用 rng |
| float 比较为什么总是 false? | 二进制浮点误差,用 np.isclose(a, b, rtol, atol) |
| 大文件读取慢怎么办? | 二进制 .npy/.npz 优先;文本用 genfromtxt 并指定 dtype |
| 如何把列表快速变数组? | np.asarray(list)(不拷贝已有 ndarray)或 np.array(list)(强制拷贝) |
| 多线程里 numpy 安全吗? | 读操作安全;写同一数组需自行加锁;释放 gil 的 ufunc 大数组并行是安全的(numpy 1.x 部分释放,2.x 逐步放开) |
到此这篇关于深度解析python中numpy数值计算库的实战教学的文章就介绍到这了,更多相关python numpy数值计算内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论