目录
- 引言:
numpy.sum()- 数组聚合的基石
- 1.1 为什么
np.sum()在 NumPy 中如此重要? - 1.2
np.sum()与 Python 内置sum()的区别
- 核心功能:
numpy.sum(a, axis=None, dtype=None, out=None, keepdims=False, initial=0)
- 2.1 功能概述:计算数组元素的和
- 2.2 参数详解
-
a: 输入数组 -
axis: 求和的轴向 (最关键参数) -
dtype: 输出数据类型 -
out: 输出数组 -
keepdims: 保留维度 (重要参数) -
initial: 初始值
axis参数详解:控制求和方向
- 3.1
axis=None(默认值):对所有元素求和 (展平后求和) - 3.2
axis=整数:沿指定轴求和 (该轴将“塌缩”)
- 示例一:2D 数组
axis=0(按列求和,行塌缩) - 示例二:2D 数组
axis=1(按行求和,列塌缩) - 示例三:3D 数组
axis=0,axis=1,axis=2
- 3.3
axis=元组:沿多个轴同时求和
keepdims=True参数详解:保留求和轴的维度
- 4.1
keepdims=False(默认值) vskeepdims=True的输出形状对比 - 4.2
keepdims=True在广播中的应用
dtype参数:防止溢出与类型转换
- 数据类型溢出问题示例
- 指定
dtype解决溢出
initial参数:为求和提供起始值numpy.sum()与其他聚合函数
-
np.mean()(平均值) -
np.prod()(乘积) -
np.min()/np.max()(最小值/最大值) -
np.cumsum()/np.cumprod()(累积和/累积积)
- 实际应用场景
- 数据聚合与统计
- 机器学习与深度学习
- 损失函数计算 (如均方误差)
- Softmax 函数的分母
- 特征工程 (行/列总和作为新特征)
- 图像处理 (像素总和)
- 性能考量
- 总结与最佳实践
1. 引言:numpy.sum() - 数组聚合的基石
在数据分析、科学计算和机器学习领域,对数据进行聚合操作(如求和、求平均、求最大值等)是极其常见的任务。NumPy 的 numpy.sum() 函数正是为此目的而设计,它能够高效、灵活地计算数组中元素的总和,并且支持多维数组的特定轴向求和。
1.1 为什么 np.sum() 在 NumPy 中如此重要?
- 高效性: 像所有 NumPy 函数一样,
np.sum()在底层是用 C 语言实现的,对于大型数组,它的计算速度远超 Python 的原生循环求和。 - 多维支持: 能够方便地控制求和的轴向,这是 Python 内置
sum()所不具备的。 - 灵活性: 结合
axis和keepdims参数,可以实现各种复杂的聚合需求,并与广播机制无缝协作。 - 内存优化: NumPy 数组本身内存效率高,求和操作进一步优化了计算过程。
1.2 np.sum() 与 Python 内置 sum() 的区别
虽然两者都用于求和,但存在关键差异:
- 输入: Python
sum()可以接受任何可迭代对象(列表、元组等),而np.sum()专门用于ndarray对象。 - 多维: Python
sum()只能处理一维可迭代对象,如果输入是列表的列表,它会尝试连接而不是求和。np.sum()则可以处理任意维度的数组。 - 轴向:
np.sum()提供了axis参数来指定求和的维度,Pythonsum()没有这个功能。 - 性能: 对于大型数值数据,
np.sum()的性能远超 Pythonsum()。
import numpy as np
list_of_lists = [[1, 2], [3, 4]]
np_array_2d = np.array(list_of_lists)
# Python sum() 的行为
try:
print("Python sum(list_of_lists):", sum(list_of_lists))
except TypeError as e:
print(f"Python sum() 处理列表的列表错误: {e}")
# 错误: TypeError: unsupported operand type(s) for +: 'int' and 'list'
# NumPy sum() 的行为 (默认展平求和)
print("NumPy np.sum(np_array_2d):", np.sum(np_array_2d)) # 10 (1+2+3+4)2. 核心功能:numpy.sum()
numpy.sum(a, axis=None, dtype=None, out=None, keepdims=False, initial=0)
2.1 功能概述:计算数组元素的和
np.sum() 函数会返回输入数组 a 中所有元素的总和,或者沿着指定轴的总和。
2.2 参数详解
-
a: (必需) 输入的ndarray。 axis: (可选)
-
None(默认):对所有元素求和,返回一个标量。 -
int:沿指定轴求和。该轴会从结果的形状中移除。 -
tuple of int:沿多个指定轴求和。这些轴将从结果的形状中移除。
-
dtype: (可选) 指定返回数组的数据类型。这对于防止溢出或控制精度非常有用。 -
out: (可选) 提供一个可选的输出数组,结果将存储在其中。 -
keepdims: (可选)bool类型,默认为False。如果设置为True,则求和的轴在结果中仍保留,但长度变为 1。这对于后续的广播操作非常有用。 -
initial: (可选) 标量。如果提供,它将作为求和的初始值。当数组为空时,这将是结果。
3. axis 参数详解:控制求和方向
理解 axis 是掌握 np.sum() 的关键。它决定了哪个维度被“压缩”或“求和掉”。
我们将使用以下 2D 数组作为示例:
arr_2d = np.arange(1, 13).reshape(3, 4)
print("原始 2D 数组 (3行4列):\n", arr_2d)
# 输出:
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
print("原始数组形状:", arr_2d.shape) # (3, 4)3.1 axis=None (默认值):对所有元素求和 (展平后求和)
这是最简单的用法,它将数组扁平化,然后求所有元素的和。结果是一个标量。
sum_all = np.sum(arr_2d)
print("\n3.1 axis=None (所有元素求和):", sum_all) # 1 + ... + 12 = 78
print("结果形状:", np.shape(sum_all)) # () - 标量没有维度3.2 axis=整数:沿指定轴求和 (该轴将“塌缩”)
axis=0: 沿第一个轴 (行) 求和。结果是每列的总和。这意味着行会“塌缩”,列保持不变。
- 想象成把每一列的数字垂直加起来。
- 原始形状
(rows, cols)变为(cols,)。
sum_axis0 = np.sum(arr_2d, axis=0)
print("\n3.2 axis=0 (按列求和):", sum_axis0)
# 输出: [1+5+9, 2+6+10, 3+7+11, 4+8+12] = [15 18 21 24]
print("结果形状:", sum_axis0.shape) # (4,)axis=1: 沿第二个轴 (列) 求和。结果是每行的总和。这意味着列会“塌缩”,行保持不变。
- 想象成把每一行的数字水平加起来。
- 原始形状
(rows, cols)变为(rows,)。
sum_axis1 = np.sum(arr_2d, axis=1)
print("\n3.2 axis=1 (按行求和):", sum_axis1)
# 输出: [1+2+3+4, 5+6+7+8, 9+10+11+12] = [10 26 42]
print("结果形状:", sum_axis1.shape) # (3,)- 3D 数组示例
arr_3d = np.arange(1, 25).reshape(2, 3, 4)
print("\n原始 3D 数组 (2x3x4):\n", arr_3d)
print("原始数组形状:", arr_3d.shape) # (2, 3, 4)
# arr_3d[0] = 第一层 (3x4)
# arr_3d[1] = 第二层 (3x4)
sum_3d_axis0 = np.sum(arr_3d, axis=0) # 沿第一维度 (层) 求和,结果是 3x4
print("\n3D 数组 axis=0 (层塌缩): 结果形状", sum_3d_axis0.shape, "\n", sum_3d_axis0)
# [1+13, 2+14, ...]
sum_3d_axis1 = np.sum(arr_3d, axis=1) # 沿第二维度 (行) 求和,结果是 2x4
print("\n3D 数组 axis=1 (行塌缩): 结果形状", sum_3d_axis1.shape, "\n", sum_3d_axis1)
# [1+5+9, 2+6+10, ...] (对每个层独立执行)
sum_3d_axis2 = np.sum(arr_3d, axis=2) # 沿第三维度 (列) 求和,结果是 2x3
print("\n3D 数组 axis=2 (列塌缩): 结果形状", sum_3d_axis2.shape, "\n", sum_3d_axis2)
# [1+2+3+4, 5+6+7+8, 9+10+11+12] (对每个层独立执行)3.3 axis=元组:沿多个轴同时求和
您可以指定一个轴元组,NumPy 将沿这些轴同时进行求和。这些指定的轴都将从结果的形状中移除。
# 沿 axis=0 和 axis=1 (即对每个 '深度' 切片求和,结果是 4 个元素的数组)
sum_3d_axis01 = np.sum(arr_3d, axis=(0, 1))
print("\n3.3 3D 数组 axis=(0, 1) (层和行同时塌缩):", sum_3d_axis01)
# 输出: [sum(所有层的第一行), sum(所有层的第二行), sum(所有层的第三行)]
# 比如 sum_3d_axis01[0] = (1+5+9) + (13+17+21) = 56
print("结果形状:", sum_3d_axis01.shape) # (4,)
# 沿 axis=0 和 axis=2 (即对每个 '行' 切片求和)
sum_3d_axis02 = np.sum(arr_3d, axis=(0, 2))
print("\n3.3 3D 数组 axis=(0, 2) (层和列同时塌缩):", sum_3d_axis02)
# 输出: [sum(所有层的第一行所有元素), sum(所有层的第二行所有元素), sum(所有层的第三行所有元素)]
print("结果形状:", sum_3d_axis02.shape) # (3,)4. keepdims=True 参数详解:保留求和轴的维度
当 keepdims=True 时,被求和的轴在结果中仍保留,但其大小变为 1。这使得结果数组的维度数量与原始数组相同,方便进行广播操作。
4.1 keepdims=False (默认值) vs keepdims=True 的输出形状对比
print("\n--- keepdims 参数对比 ---")
print("原始 2D 数组形状:", arr_2d.shape) # (3, 4)
sum_axis0_no_keepdims = np.sum(arr_2d, axis=0, keepdims=False)
print("axis=0, keepdims=False 结果形状:", sum_axis0_no_keepdims.shape) # (4,)
sum_axis0_keepdims = np.sum(arr_2d, axis=0, keepdims=True)
print("axis=0, keepdims=True 结果形状:", sum_axis0_keepdims.shape) # (1, 4)
print("axis=0, keepdims=True 结果:\n", sum_axis0_keepdims)
# [[15 18 21 24]] (注意外层多了一对方括号,表示多了一个维度)
sum_axis1_keepdims = np.sum(arr_2d, axis=1, keepdims=True)
print("axis=1, keepdims=True 结果形状:", sum_axis1_keepdims.shape) # (3, 1)
print("axis=1, keepdims=True 结果:\n", sum_axis1_keepdims)
# [[10]
# [26]
# [42]]4.2 keepdims=True 在广播中的应用
keepdims=True 的主要作用是方便后续的广播操作。例如,在标准化数据时,我们需要从每个元素中减去其所在列的平均值。如果 mean 函数不保留维度,结果形状可能无法直接与原始数组进行广播。
print("\n--- keepdims 在广播中的应用 ---")
data_matrix = np.array([[10, 20, 30],
[11, 21, 31],
[12, 22, 32]]) # 形状 (3, 3)
# 计算每列的平均值
column_means = np.mean(data_matrix, axis=0) # 形状 (3,)
print("每列平均值 (默认 keepdims=False) 形状:", column_means.shape)
# 尝试减去,会进行广播 (3,3) - (3,) -> (3,3) - (1,3) -> (3,3) 广播成功
normalized_data = data_matrix - column_means
print("广播成功 (3,3) - (3,): \n", normalized_data)
# 如果我们想显式地保留维度,可以这样操作:
column_means_keepdims = np.mean(data_matrix, axis=0, keepdims=True) # 形状 (1, 3)
print("每列平均值 (keepdims=True) 形状:", column_means_keepdims.shape)
# (3,3) - (1,3) 可以直接进行广播,更加直观,避免 NumPy 自动填充维度 (规则 1)
normalized_data_keepdims = data_matrix - column_means_keepdims
print("广播成功 (3,3) - (1,3): \n", normalized_data_keepdims)
# 结果是相同的,但在更复杂的广播场景中,keepdims=True 可以使代码更清晰、更可预测。5. dtype 参数:防止溢出与类型转换
当对大量整数进行求和时,结果可能会超出原始数据类型所能表示的范围,导致溢出。通过指定 dtype 参数,可以确保结果存储在足够大的数据类型中。
print("\n--- dtype 参数 ---")
large_int_array = np.array([200, 200, 200], dtype=np.uint8) # 无符号8位整数,最大值 255
print("原始数组 (uint8):", large_int_array)
# 默认求和,结果会溢出 (200+200+200 = 600,超出了 255)
sum_default_dtype = np.sum(large_int_array)
print("默认 dtype 求和结果 (可能溢出):", sum_default_dtype) # 可能会是 88 (600 % 256)
# 指定 dtype 为 np.int64 或 np.float64
sum_int64 = np.sum(large_int_array, dtype=np.int64)
print("指定 dtype=np.int64 求和结果:", sum_int64) # 600
sum_float64 = np.sum(large_int_array, dtype=np.float64)
print("指定 dtype=np.float64 求和结果:", sum_float64) # 600.06. initial 参数:为求和提供起始值
在求和操作开始之前,可以将 initial 的值添加到总和中。当数组为空时,它也是结果。
print("\n--- initial 参数 ---")
arr_small = np.array([10, 20])
sum_with_initial = np.sum(arr_small, initial=100)
print("带初始值的求和:", sum_with_initial) # 100 + 10 + 20 = 130
empty_array = np.array([])
sum_empty_with_initial = np.sum(empty_array, initial=50)
print("空数组带初始值的求和:", sum_empty_with_initial) # 507. numpy.sum() 与其他聚合函数
NumPy 提供了许多与 np.sum() 具有相似参数结构的聚合函数,它们也支持 axis 和 keepdims。
print("\n--- 其他聚合函数 ---")
arr_agg = np.array([[1, 2, 3], [4, 5, 6]])
print("np.mean(arr_agg, axis=0):", np.mean(arr_agg, axis=0)) # [2.5 3.5 4.5]
print("np.prod(arr_agg, axis=1):", np.prod(arr_agg, axis=1)) # [6 120]
print("np.min(arr_agg):", np.min(arr_agg)) # 1
print("np.max(arr_agg, axis=1, keepdims=True):\n", np.max(arr_agg, axis=1, keepdims=True)) # [[3],[6]]
print("np.cumsum(arr_agg, axis=1):\n", np.cumsum(arr_agg, axis=1)) # 累积和
# [[ 1 3 6]
# [ 4 9 15]]8. 实际应用场景
8.1 数据聚合与统计
计算数据集的总和、平均值等统计量。
sales_data = np.random.randint(100, 1000, size=(5, 3)) # 5天3个产品的销售额
print("\n应用场景 - 销售数据:\n", sales_data)
total_sales_per_product = np.sum(sales_data, axis=0)
print("各产品总销售额:", total_sales_per_product)
total_sales_per_day = np.sum(sales_data, axis=1)
print("每天总销售额:", total_sales_per_day)
overall_total_sales = np.sum(sales_data)
print("总销售额:", overall_total_sales)8.2 机器学习与深度学习
- 损失函数计算 (如均方误差 MSE)
predictions = np.array([0.9, 0.2, 0.8, 0.4])
true_labels = np.array([1.0, 0.0, 0.7, 0.5])
mse = np.sum((predictions - true_labels)**2) / len(predictions)
print("\n应用场景 - 均方误差 (MSE):", mse) # 或使用 np.mean((predictions - true_labels)**2)- Softmax 函数的分母
Softmax 函数用于将向量转换为概率分布,其分母是指数化后元素的总和。
logits = np.array([1.0, 2.0, 3.0])
exp_logits = np.exp(logits)
softmax_denom = np.sum(exp_logits)
softmax_output = exp_logits / softmax_denom
print("\n应用场景 - Softmax 函数:")
print("exp_logits:", exp_logits)
print("softmax_denom:", softmax_denom)
print("softmax_output (概率分布):", softmax_output)- 特征工程 (行/列总和作为新特征)
将某些行或列的总和作为新的数据特征。
8.3 图像处理 (像素总和)
计算图像所有像素值的总和,例如用于亮度分析或图像特征。
image_pixels = np.random.randint(0, 256, size=(100, 100), dtype=np.uint8)
total_intensity = np.sum(image_pixels)
print("\n应用场景 - 图像处理 (总像素强度):", total_intensity)9. 性能考量
np.sum() 比 Python 的内置 sum() 具有显著的性能优势,尤其是在处理大型 NumPy 数组时。这是因为 NumPy 操作是经过优化的 C 语言实现,避免了 Python 解释器的开销。对于需要频繁求和的数值计算任务,始终推荐使用 np.sum()。
10. 总结与最佳实践
numpy.sum() 是 NumPy 库中一个功能强大且用途广泛的函数,是进行数据聚合和数值计算不可或缺的工具。
核心要点回顾:
- 元素级求和: 默认或不指定
axis时对所有元素求和。 -
axis参数: 精确控制沿哪个维度进行求和,该维度将被“塌缩”。理解axis=0(按列) 和axis=1(按行) 是基础。 -
keepdims=True: 保留求和轴的维度 (长度为 1),这在需要后续广播操作时非常有用,可以保持数组的维度一致性。 -
dtype参数: 防止整数溢出,并控制输出结果的数据类型。 -
initial参数: 可为求和提供起始值。 - 高性能: 远超 Python 原生
sum()。
掌握 np.sum() 及其参数的细微之处,将使您能够更高效、更灵活地处理各种数值数据,为数据分析、机器学习模型开发和科学研究打下坚实的基础。
















