- NumPy 教程
- NumPy - 首页
- NumPy - 简介
- NumPy - 环境
- NumPy 数组
- NumPy - Ndarray 对象
- NumPy - 数据类型
- NumPy 创建和操作数组
- NumPy - 数组创建例程
- NumPy - 数组操作
- NumPy - 从现有数据创建数组
- NumPy - 从数值范围创建数组
- NumPy - 遍历数组
- NumPy - 数组重塑
- NumPy - 连接数组
- NumPy - 堆叠数组
- NumPy - 分割数组
- NumPy - 扁平化数组
- NumPy - 转置数组
- NumPy 索引和切片
- NumPy - 索引和切片
- NumPy - 高级索引
- NumPy 数组属性和操作
- NumPy - 数组属性
- NumPy - 数组形状
- NumPy - 数组大小
- NumPy - 数组步长
- NumPy - 数组元素大小
- NumPy - 广播
- NumPy - 算术运算
- NumPy - 数组加法
- NumPy - 数组减法
- NumPy - 数组乘法
- NumPy - 数组除法
- NumPy 高级数组操作
- NumPy - 交换数组轴
- NumPy - 字节交换
- NumPy - 复制和视图
- NumPy - 元素级数组比较
- NumPy - 过滤数组
- NumPy - 连接数组
- NumPy - 排序、搜索和计数函数
- NumPy - 搜索数组
- NumPy - 数组的并集
- NumPy - 查找唯一行
- NumPy - 创建日期时间数组
- NumPy - 二元运算符
- NumPy - 字符串函数
- NumPy - 数学函数
- NumPy - 统计函数
- NumPy - 矩阵库
- NumPy - 线性代数
- NumPy - Matplotlib
- NumPy - 使用 Matplotlib 绘制直方图
- NumPy - NumPy 的 I/O
- NumPy 排序和高级操作
- NumPy - 数组排序
- NumPy - 沿轴排序
- NumPy - 使用花式索引排序
- NumPy - 结构化数组
- NumPy - 创建结构化数组
- NumPy - 操作结构化数组
- NumPy - 字段访问
- NumPy - 记录数组
- Numpy - 加载数组
- Numpy - 保存数组
- NumPy - 将值追加到数组
- NumPy - 交换数组的列
- NumPy - 向数组插入轴
- NumPy 处理缺失数据
- NumPy - 处理缺失数据
- NumPy - 识别缺失值
- NumPy - 删除缺失数据
- NumPy - 填充缺失数据
- NumPy 性能优化
- NumPy - 使用数组进行性能优化
- NumPy - 使用数组进行向量化
- NumPy - 数组的内存布局
- Numpy 线性代数
- NumPy - 线性代数
- NumPy - 矩阵库
- NumPy - 矩阵加法
- NumPy - 矩阵减法
- NumPy - 矩阵乘法
- NumPy - 元素级矩阵运算
- NumPy - 点积
- NumPy - 矩阵求逆
- NumPy - 行列式计算
- NumPy - 特征值
- NumPy - 特征向量
- NumPy - 奇异值分解
- NumPy - 求解线性方程组
- NumPy - 矩阵范数
- NumPy 元素级矩阵运算
- NumPy - 求和
- NumPy - 求平均值
- NumPy - 求中位数
- NumPy - 求最小值
- NumPy - 求最大值
- NumPy 集合运算
- NumPy - 唯一元素
- NumPy - 交集
- NumPy - 并集
- NumPy - 差集
- NumPy 有用资源
- NumPy 编译器
- NumPy - 快速指南
- NumPy - 有用资源
- NumPy - 讨论
NumPy - 使用数组进行性能优化
使用数组进行性能优化
使用数组进行性能优化包括提高数组操作的效率,例如减少计算时间和内存使用。
我们应该出于以下原因优化性能:
- 速度: 更快的计算速度带来更快的结果和更灵敏的应用程序。
- 可扩展性: 优化的代码可以有效地处理更大的数据集和更复杂的操作。
- 资源效率: 减少内存使用和计算开销。
使用向量化运算
向量化运算指的是能够一步执行整个数组或矩阵上的运算,而无需使用显式循环。
这是通过广播和内部优化实现的,使这些运算更快、更高效。
示例
在以下示例中,我们使用 NumPy 的数组运算对两个大型数组“a”和“b”执行向量化加法。此运算计算数组的元素级和并将结果存储在新数组“c”中:
import numpy as np # Create two large arrays a = np.random.rand(1000000) b = np.random.rand(1000000) # Vectorized addition c = a + b print (c)
以下是获得的输出:
[0.91662816 0.65486861 1.60409272 ... 0.95122935 1.12795861 0.15812103]
利用高效的数据类型
为数组选择合适的数据类型对于优化 NumPy 中的性能和内存使用非常重要。
例如,使用np.float32而不是np.float64可以显着影响内存使用和性能,尤其是在处理大型数据集时。
在 NumPy 中,数据类型(或 dtype)定义了数组保存的元素类型以及存储每个元素所需的存储空间。
示例
在此示例中,我们演示了通过创建具有双精度(64 位)浮点数的数组,然后使用 astype() 方法将其转换为单精度(32 位)来使用精度更改:
import numpy as np
# Create an array with double precision (64-bit)
arr_double = np.array([1.0, 2.0, 3.0], dtype=np.float64)
# Print the original double precision array
print("Original double precision array:")
print(arr_double)
print("Data type:", arr_double.dtype)
# Convert to single precision (32-bit)
arr_single = arr_double.astype(np.float32)
# Print the converted single precision array
print("\nConverted single precision array:")
print(arr_single)
print("Data type:", arr_single.dtype)
这将产生以下结果:
Original double precision array: [1. 2. 3.] Data type: float64 Converted single precision array: [1. 2. 3.] Data type: float32
避免使用 NumPy 函数的循环
在 NumPy 中,主要优势之一是可以避免使用内置函数和数组运算显式循环。这种方法通常称为向量化。
通过使用 NumPy 函数,您可以一次对整个数组执行运算,这与使用循环相比更加简洁。
示例
在下面的示例中,我们使用 np.mean() 函数计算数组元素的平均值,而无需使用任何显式循环:
import numpy as np
# Create an array
arr = np.array([1, 2, 3, 4, 5])
# Calculate the mean of array elements
mean = np.mean(arr)
print("mean:",mean)
以下是上述代码的输出:
mean: 3.0
使用广播进行向量化
广播指的是能够对形状不同的数组执行元素级运算。它遵循一组规则来确定如何对形状不同的数组进行对齐以进行运算:
- 相同维度: 如果数组具有不同的维度,则较小数组的形状在左侧填充 1,直到两个形状具有相同的长度。
- 维度兼容性: 当两个维度相等或其中一个为 1 时,它们是兼容的。对于每个维度,如果大小不同,并且如果它们都不为 1,则广播失败。
- 拉伸: 尺寸为 1 的数组沿该尺寸拉伸以匹配另一个数组尺寸的大小。
示例
在以下示例中,我们广播“array_1d”以匹配“array_2d”的形状,从而允许元素级加法:
import numpy as np # Create a 2D array and a 1D array array_2d = np.array([[1, 2, 3], [4, 5, 6]]) array_1d = np.array([10, 20, 30]) # Add the 1D array to each row of the 2D array result = array_2d + array_1d print(result)
获得的输出如下所示:
[[11 22 33] [14 25 36]]
就地运算用于向量化
NumPy 中的就地运算指的是直接修改数组的数据,而无需创建新数组来存储结果,从而节省内存并提高性能。
这是通过使用修改原始数组内容的运算符和函数来实现的。这些运算通常使用带就地后缀的运算符(例如,+=、-=、*=、/=)或支持就地修改的函数。
示例:使用就地运算符
在此示例中,我们直接对数组应用算术运算“+=”而无需创建新的数组:
import numpy as np # Create an array arr = np.array([1, 2, 3, 4, 5]) # Add 10 to each element in-place arr += 10 print(arr)
执行上述代码后,我们得到以下输出:
[11 12 13 14 15]
示例:使用就地函数
在这里,我们使用 NumPy exp() 函数就地计算数组中每个元素的指数值:
import numpy as np # Create an array with a floating-point data type arr = np.array([1, 2, 3, 4, 5], dtype=np.float64) # Compute the exponential of each element in-place np.exp(arr, out=arr) print(arr)
执行上述代码后,我们得到以下输出:
[ 2.71828183 7.3890561 20.08553692 54.59815003 148.4131591 ]
使用内存视图进行向量化
内存视图指的是访问或查看数组中相同底层数据的不同方式,而无需复制它。此概念允许您创建数组的不同“视图”或“切片”,这些视图可以以各种方式操作相同的数据:
- 切片: 当您切片数组时,NumPy 会创建原始数组的视图,而不是副本。此视图共享相同的内存缓冲区,因此对视图的更改会影响原始数组,反之亦然。
- 重塑: 重塑数组会创建具有不同形状的相同数据的新的视图。这不会更改底层数据,但会更改其解释方式。
示例:切片
在下面的示例中,我们创建了一个二维 NumPy 数组和原始数组的视图(切片)。修改视图也会影响原始数组:
import numpy as np # Create a 2D array arr = np.array([[1, 2, 3], [4, 5, 6]]) # Create a view (slice) of the original array view = arr[:, 1:] # Modify the view view[0, 0] = 99 print(arr)
我们得到如下所示的输出:
[[ 1 99 3] [ 4 5 6]]
示例:重塑
在这里,我们使用 arange() 函数创建一个一维 NumPy 数组,然后将其重塑为一个具有 3 行 4 列的二维数组,更改其结构同时保留原始数据:
import numpy as np # Create a 1D array arr = np.arange(12) # Reshape to a 2D array reshaped = arr.reshape((3, 4)) print(reshaped)
我们得到如下所示的输出:
[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]]
使用步长进行向量化
步长是一个元组,指示遍历数组时每个维度要步进的字节数。它们确定如何在内存中访问数组元素,从而深入了解数据的布局和访问方式。
步长为您提供每个维度的内存偏移量。例如,在二维数组中,第二个维度的步长告诉您在内存中移动多少字节才能访问该行中的下一个元素。
示例
在以下示例中,我们创建了一个二维 NumPy 数组,并使用strides属性检索遍历数组时每个维度要步进的字节数:
import numpy as np # Create a 2D array arr = np.array([[1, 2, 3], [4, 5, 6]]) # Print the strides of the array print(arr.strides)
我们得到如下所示的输出:
(24, 8)