问题与目标
Python 列表可以保存数值,但它不直接表达多维形状、统一类型和批量运算。NumPy 的 ndarray 用连续数据和向量化操作承载数值计算,是后续数据分析与机器学习的基础。
完成标准:能创建和检查数组,使用索引、切片、布尔筛选、广播和矩阵乘法,并解释形状不匹配问题。

广播比较形状时从最右侧维度开始:对应维度相等,或其中一个为 1,才可以继续扩展。把形状写出来再对齐,比只看报错信息更容易定位问题。
核心概念
数组的三个关键属性是 shape、ndim 和 dtype。同一数组通常使用统一类型;混入字符串可能导致整体转换,影响计算。
切片通常返回视图,修改它可能影响原数组;需要独立数据时显式 .copy()。向量化把循环交给底层实现,代码更接近公式,但并不意味着所有操作都会无条件更快或更省内存。
广播从尾部维度比较:维度相等、其中一个为 1,或一方缺少该维度时可以扩展。* 是逐元素乘法,@ 是矩阵乘法。
创建数组与检查结构
import numpy as np
print(np.zeros((2, 3)))
print(np.ones((2, 3), dtype=np.int64))
print(np.arange(0, 10, 2))
print(np.linspace(0, 1, 5))
array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float64)
print(array.shape, array.ndim, array.size, array.dtype)
reshape 只改变形状解释,元素总数必须一致;使用 -1 可以让 NumPy 推断一个维度。ravel() 尽量返回视图,flatten() 总是复制,是否共享内存会影响修改结果和内存开销。
索引、轴与聚合
二维数组中 axis=0 沿行方向压缩,得到每列结果;axis=1 沿列方向压缩,得到每行结果:
matrix = np.array([[1, 2, 3], [4, 5, 6]])
print(matrix.sum(axis=0))
print(matrix.sum(axis=1))
print(matrix[:, 1])
print(matrix[matrix > 3])
布尔索引返回一维选中结果;需要保留二维结构时使用 np.where 替换或按行列分别筛选。
广播的形状推导
形状 (3, 4) 的矩阵减去 (4,) 向量时,向量按每一行广播;减去 (3, 1) 时,单列按每一列广播。形状 (3,) 不能直接表达“每行一个值”,应通过 values[:, None] 变成 (3, 1)。
可运行实现
对三名用户的四项指标做标准化和加权评分:
python -m pip install numpy
import numpy as np
features = np.array(
[
[80.0, 5.0, 12.0, 0.9],
[65.0, 8.0, 18.0, 0.7],
[92.0, 4.0, 10.0, 0.95],
],
dtype=np.float64,
)
minimum = features.min(axis=0)
maximum = features.max(axis=0)
scale = np.where(maximum == minimum, 1.0, maximum - minimum)
normalized = (features - minimum) / scale
weights = np.array([0.4, -0.2, -0.1, 0.3])
scores = normalized @ weights
print("shape:", features.shape)
print("normalized:\n", np.round(normalized, 2))
print("scores:", np.round(scores, 3))
print("best index:", int(np.argmax(scores)))
输入是形状 (3, 4) 的特征矩阵和形状 (4,) 的权重向量,输出是标准化矩阵、三项得分和最高分行号。axis=0 表示沿行聚合,为每一列计算统计值。
常见创建与筛选方式:
values = np.arange(12).reshape(3, 4)
print(values[:, 1:3])
print(values[values % 2 == 0])
print(np.linspace(0, 1, 5))
随机实验使用生成器并固定种子以便复现:rng = np.random.default_rng(42)。
向量化并不等于没有成本
表达式 (features - minimum) / scale 可能创建中间数组。数据很大时应关注峰值内存,必要时分块处理或使用允许的原地操作。原地运算还受 dtype 转换规则限制,不能为节省内存牺牲正确性。
可以用以下方式进一步验证:给定一次矩阵运算,先手写输入、广播中间形状和输出形状,再运行代码核对;对随机过程固定种子;对切片修改明确说明是否希望影响原数组。
进一步验证
- 对形状为
(4, 3)的矩阵,分别计算按列和按行归一化,写出所有中间形状。 - 制造一次整数数组原地除法错误,再通过显式转换
dtype修复。 - 比较切片视图和
.copy()在修改后的差异,并说明两者的内存取舍。
验证时不仅要数值正确,还要能预先写出每个数组的 shape、dtype 以及是否与原数据共享内存。
常见问题与排查
operands could not be broadcast together:从右向左比较两个shape,明确希望按行还是按列扩展。*与@混淆:先写出期望输入、输出形状。- 整数数组计算后被截断:构造时指定浮点
dtype,不要向整数数组原地写小数。 - 修改切片导致原数组变化:视图共享数据,需要隔离时
.copy()。 - 用
np.vectorize期待底层加速:它主要改善调用形式,通常仍执行 Python 函数。
小结
NumPy 的核心不是函数数量,而是形状、轴、类型和广播。每次计算前后都能写出 shape,数值代码才容易验证和排查。
许可协议:CC BY-NC 4.0
更新于 1 小时前
觉得文章有帮助?点个赞吧!
0 条评论


