最强总结! 十大 NumPy 数组操作 !!

文摘   2024-10-03 11:26   山西  

哈喽,我是小白~

假期之余,今儿和大家聊聊,NumPy 数组操作的一些技巧!~

在机器学习实验中,NumPy 数组操作技巧能够高效处理和转换大量数据,使得特征工程、数据预处理等步骤更加简洁和快速。它提供了矩阵运算、数组合并、条件筛选等工具,帮助实现复杂的数值计算和数据变换。

通过这些操作,研究者可以优化数据流、提高模型性能,并增强实验的可扩展性。


往期 Numpy 合集

Numpy 十大基础操作 

Numpy 十大高级操作 

NumPy 十大矩阵运算 

1. 创建数组 (np.array())

np.array() 是创建数组的基础函数,用于将普通的 Python 序列(如列表、元组)转换为 NumPy 数组。这是大多数操作的第一步,因为它支持高效的数组操作和计算。

主要功能:

  • 支持多种数据结构:将列表、元组、甚至嵌套的列表转换为数组。
  • 支持指定数据类型:可以通过 dtype 参数指定数据类型(整数、浮点数等)。
  • 支持多维数组:不仅限于一维数组,还可以轻松创建多维数组。

Python 实现

import numpy as np

# 创建一维数组
arr1 = np.array([1234])
print("一维数组:", arr1)

# 创建二维数组
arr2 = np.array([[12], [34]])
print("二维数组:\n", arr2)

# 创建三维数组
arr3 = np.array([[[12], [34]], [[56], [78]]])
print("三维数组:\n", arr3)

# 指定数据类型为浮点型
arr4 = np.array([1234], dtype=float)
print("指定浮点型数组:", arr4)

2. 数组形状操作 (reshape()flatten()ravel())

形状操作是将数组在不同维度之间转换的方式。对于多维数据处理,常常需要重新调整数组的形状来适应不同的操作或模型。

主要功能:

  • reshape():改变数组的形状而不改变其数据。注意,新形状必须与原数组的元素数量相匹配。
  • flatten():将多维数组展平成一维数组,返回的是数组的副本。
  • ravel():同样展平数组,但尽可能返回的是数组的视图而非副本,效率更高。

Python 实现

# 创建二维数组
arr = np.array([[123], [456]])

# 改变形状为 (3, 2)
reshaped = arr.reshape((32))
print("重塑后的数组:\n", reshaped)

# 展平数组
flattened = arr.flatten()
print("展平后的数组:", flattened)

# 使用 ravel 展平数组
ravelled = arr.ravel()
print("使用 ravel 展平的数组:", ravelled)

场景

这些形状操作在模型输入或预处理时很常用。例如,卷积神经网络的输入通常需要将图像从二维形式重塑为三维(width x height x channels),而全连接层需要展平输入。

3. 数组索引与切片 (array slicing)

索引和切片是数组操作的基础功能之一,它允许我们访问数组中的特定元素、子数组或进行修改操作。与 Python 的列表索引类似,但在 NumPy 中更强大,可以应用于多维数组。

主要功能:

  • 单元素索引:通过下标访问数组中的某个元素。
  • 切片:可以获取数组的子集,使用类似于 start:end:step 的切片方式。
  • 多维索引:在多维数组中,使用逗号分隔的索引来访问特定元素。

Python 实现

# 创建二维数组
arr = np.array([[123], [456], [789]])

# 访问单个元素
print("访问 (0, 1) 元素:", arr[01])

# 切片操作
print("切片得到的子数组:\n", arr[1:, 1:])

# 使用步长进行切片
print("步长为 2 的切片:\n", arr[::2, ::2])

场景

在机器学习中,数据通常以矩阵或张量的形式存储和处理。索引和切片用于提取感兴趣的部分,如选取特征子集、批量数据等。

4. 数组广播 (broadcasting)

广播是一种强大的机制,它允许 NumPy 以不同形状的数组参与操作。即使两个数组的维度不同,它们也能通过扩展较小数组的维度,使其形状与较大数组一致来进行运算。

主要功能:

  • 形状自动匹配:可以让不同维度的数组进行算术操作,NumPy 会自动调整较小数组的形状。
  • 无需显式调整维度:无需手动使用 reshape(),广播机制会自动处理。

Python 实现

# 广播标量和数组
arr = np.array([123])
print("数组与标量相加:", arr + 10)

# 广播不同形状的数组
arr2 = np.array([[123], [456]])
arr3 = np.array([123])
print("二维数组与一维数组相加:\n", arr2 + arr3)

场景

广播广泛用于数组的批量操作,如在机器学习中可以快速处理特征归一化、矩阵加减法等。它减少了手动调整数组形状的需求,提高了代码简洁性和可读性。

5. 数学运算 (array operations)

NumPy 提供了丰富的数学运算功能,这些运算以向量化的方式进行,能够在数组上快速执行各种数学计算,而无需使用显式的循环。

主要功能:

  • 基本运算:加减乘除、指数运算等,直接在数组上操作。
  • 统计运算:如 sum()mean()max()min() 等聚合函数。
  • 线性代数:如矩阵乘法(dot())、矩阵逆、特征值计算等。

Python 实现

arr = np.array([123])

# 基本算术运算
print("数组加 5:", arr + 5)
print("数组乘 2:", arr * 2)

# 数组的统计运算
print("数组的和:", arr.sum())
print("数组的均值:", arr.mean())

# 线性代数运算
mat1 = np.array([[12], [34]])
mat2 = np.array([[56], [78]])
print("矩阵乘法:\n", np.dot(mat1, mat2))

场景

在机器学习中,数学运算和统计函数广泛用于数据的归一化、标准化、特征处理等操作。而线性代数操作在模型计算(如梯度计算、矩阵乘法)中尤为重要。

6. 数组条件筛选 (boolean masking)

布尔掩码(boolean masking)是一种非常强大的数据筛选方式,它允许基于条件筛选数组中的元素。通过创建布尔数组或条件表达式,可以选取满足条件的元素。

主要功能:

  • 布尔索引:根据条件表达式创建布尔数组,并用它来过滤原数组中的元素。
  • 条件替换:使用 np.where() 根据条件选择性地替换数组中的值。

Python 实现

arr = np.array([123456])

# 布尔掩码筛选
mask = arr > 3
print("大于 3 的元素:", arr[mask])

# 使用 np.where 条件替换
new_arr = np.where(arr > 3, arr * 10, arr)
print("大于 3 的元素乘以 10:", new_arr)

场景

布尔掩码广泛用于数据预处理、异常值检测和特征工程。例如,你可以根据某个条件筛选数据集中的样本或特征,或基于条件对数据进行变换。

7. 数组合并与分割 (concatenate()split())

数组合并与分割是在处理多组数据时的常用操作,NumPy 提供了多个函数来处理这一需求。

主要功能:

  • concatenate():将多个数组沿指定轴拼接。
  • stack():沿新的维度进行堆叠,创建高维数组。
  • split():将一个数组拆分为多个子数组。

Python 实现

# 合并数组
arr1 = np.array([123])
arr2 = np.array([456])
combined = np.concatenate((arr1, arr2))
print("合并后的数组:", combined)

# 堆叠数组
stacked = np.stack((arr1, arr2), axis=0)
print("堆叠后的数组:\n", stacked)

# 分割数组
split_arr = np.split(combined, 2)
print("分割后的数组:", split_arr)

场景

合并和分割常用于数据增强、特征组合、模型输入预处理等场景。例如,你可以将多个特征列组合成一个矩阵,或者将大批量数据分割成多个小批次。

8. 数组维度扩展与压缩 (expand_dims()squeeze())

维度扩展与压缩用于在需要时增加或减少数组的维度。例如,在深度学习中,有时需要在批次维度、通道维度等位置扩展或压缩维度,以便适应模型输入的要求。

主要功能:

  • expand_dims():在指定轴插入一个新的维度,增加数组的维度。
  • squeeze():删除数组中尺寸为 1 的维度,压缩维度。

Python 实现

# 原始数组
arr = np.array([123])

# 扩展维度
expanded = np.expand_dims(arr, axis=0)
print("扩展维度后的数组:\n", expanded)

# 压缩维度
squeezed = np.squeeze(expanded)
print("压缩维度后的数组:", squeezed)

场景

维度扩展和压缩在图像处理、深度学习模型输入中很常见。例如,在卷积神经网络中,可能需要在输入数据的前面或后面增加一个批量维度或通道维度。

9. 数组排序与去重 (sort()unique())

数组排序与去重操作在数据处理中非常常见,尤其是在需要对特征进行排序或筛选唯一值时。

主要功能:

  • sort():对数组进行排序,默认按升序排序,可以指定轴。
  • unique():返回数组中的唯一值,并可以选择返回唯一值的索引和计数。

Python 实现

arr = np.array([31234])

# 排序
sorted_arr = np.sort(arr)
print("排序后的数组:", sorted_arr)

# 去重
unique_arr = np.unique(arr)
print("去重后的数组:", unique_arr)

场景

排序和去重在特征工程和数据预处理中很常用,例如对类别特征进行唯一化处理或对数值特征进行排序操作。

10. 随机数生成 (np.random 模块)

随机数生成器允许我们生成符合特定分布的随机数组,这在机器学习、数据增强和蒙特卡洛方法中非常有用。

主要功能:

  • rand():生成均匀分布的随机数。
  • randn():生成标准正态分布的随机数。
  • randint():生成随机整数。
  • shuffle():对数组进行随机打乱。

Python 实现

# 生成均匀分布的随机数
rand_arr = np.random.rand(33)
print("均匀分布的随机数数组:\n", rand_arr)

# 生成标准正态分布的随机数
randn_arr = np.random.randn(33)
print("标准正态分布的随机数数组:\n", randn_arr)

# 生成随机整数
randint_arr = np.random.randint(010, size=(33))
print("随机整数数组:\n", randint_arr)

# 随机打乱数组
arr = np.array([12345])
np.random.shuffle(arr)
print("打乱后的数组:", arr)

场景

在机器学习中,随机数生成广泛应用于初始化模型权重、生成数据集的随机批次以及进行数据增强(如随机裁剪、翻转等)。

下面,咱们举一个案例,整体的运用一下~

完整案例

案例中,加入数据生成、处理和可视化中引入 NumPy 操作,包括:

  • 数据标准化、均值调整
  • 形状变换
  • 合并多个数组
  • 使用条件筛选和广播操作
  • 统计汇总

完整代码:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

# 设置随机种子,确保结果可复现
np.random.seed(42)

# 1. 使用 NumPy 生成虚拟数据集
# 生成 X 特征数据,均匀分布在 0 到 10 之间
X = np.random.rand(1001) * 10

# 生成 Y 特征数据,假设 Y 与 X 存在线性关系,但有噪声影响
# Y = 2.5 * X + 噪声,噪声服从正态分布
noise = np.random.randn(1001) * 5
Y = 2.5 * X + noise

# 2. 数组操作 - 数据标准化 (Z-Score Normalization)
X_mean = X.mean()
X_std = X.std()
X_norm = (X - X_mean) / X_std  # 标准化后的 X

Y_mean = Y.mean()
Y_std = Y.std()
Y_norm = (Y - Y_mean) / Y_std  # 标准化后的 Y

# 3. 数组合并 - 合并标准化后的 X 和 Y
data = np.concatenate((X_norm, Y_norm), axis=1)

# 4. 数组形状变换
# 假设我们需要将一维数组展平处理或者重塑为不同形状
X_flat = X_norm.flatten()  # 展平
Y_flat = Y_norm.flatten()

# 5. 条件筛选 - 筛选 X_norm 中大于 0 的数据
X_positive = X_norm[X_norm > 0]
Y_positive = Y_norm[:X_positive.shape[0]]  # 对应筛选出的 Y 数据

# 6. 统计运算 - 计算均值、方差、最大值、最小值
X_stats = {
    'mean': np.mean(X),
    'var': np.var(X),
    'max': np.max(X),
    'min': np.min(X)
}
Y_stats = {
    'mean': np.mean(Y),
    'var': np.var(Y),
    'max': np.max(Y),
    'min': np.min(Y)
}

# 7. 广播操作 - 对 Y 进行批量运算,将所有元素乘以一个常数
Y_scaled = Y_norm * 2.5

# 8. 线性回归拟合 - 使用标准化后的数据
model = LinearRegression()
model.fit(X_norm, Y_norm)
Y_pred = model.predict(X_norm)

# 设置图形大小
fig, axs = plt.subplots(22, figsize=(1210))
fig.suptitle('Advanced Data Analysis: Scatter Plot, Regression Line, Distribution and Operations', fontsize=16)

# 绘制散点图和线性回归线
axs[00].scatter(X_norm, Y_norm, color='red', label='Data Points (Normalized)', alpha=0.7)
axs[00].plot(X_norm, Y_pred, color='blue', label='Regression Line', linewidth=2)
axs[00].set_title('Normalized Scatter Plot with Regression Line')
axs[00].set_xlabel('X (Normalized)')
axs[00].set_ylabel('Y (Normalized)')
axs[00].legend()

# 绘制 X 的直方图
axs[01].hist(X_norm, bins=20, color='green', edgecolor='black', alpha=0.7)
axs[01].set_title('Distribution of X (Normalized)')
axs[01].set_xlabel('X Values')
axs[01].set_ylabel('Frequency')

# 绘制 Y 的直方图
axs[10].hist(Y_norm, bins=20, color='purple', edgecolor='black', alpha=0.7)
axs[10].set_title('Distribution of Y (Normalized)')
axs[10].set_xlabel('Y Values')
axs[10].set_ylabel('Frequency')

# 绘制残差图,展示真实值与预测值之间的差异
residuals = Y_norm - Y_pred
axs[11].scatter(X_norm, residuals, color='orange', label='Residuals', alpha=0.7)
axs[11].axhline(0, color='black', linestyle='--', linewidth=2)
axs[11].set_title('Residuals Plot (Normalized)')
axs[11].set_xlabel('X (Normalized)')
axs[11].set_ylabel('Residuals')
axs[11].legend()

# 调整布局以避免子图重叠
plt.tight_layout(rect=[0010.96])

# 展示图形
plt.show()

# 打印统计信息
print("X 的统计信息:", X_stats)
print("Y 的统计信息:", Y_stats)

1. 数据标准化 (Z-Score Normalization):

  • 我们计算了 X 和 Y 的均值和标准差,并将它们标准化为均值为 0,标准差为 1 的分布。
  • 这在数据分析和机器学习中非常常见,尤其是当特征具有不同量纲时,标准化可以提高模型的表现。
X_norm = (X - X_mean) / X_std
Y_norm = (Y - Y_mean) / Y_std

2. 数组合并 (concatenate):

  • 将标准化后的 X_norm 和 Y_norm 合并为一个二维数组,以便于后续处理和分析。
data = np.concatenate((X_norm, Y_norm), axis=1)

3. 数组展平 (flatten):

  • 使用 flatten() 将标准化后的 X_norm 和 Y_norm 变为一维数组,以便在某些情况下需要将多维数组展平为一维时处理。
X_flat = X_norm.flatten()
Y_flat = Y_norm.flatten()

4. 条件筛选 (boolean masking):

  • 筛选 X_norm 中大于 0 的数据,并提取相应的 Y_norm 值。条件筛选有助于对特定子集进行分析。
X_positive = X_norm[X_norm > 0]
Y_positive = Y_norm[:X_positive.shape[0]]

5. 统计运算

  • 计算了 X 和 Y 的均值、方差、最大值和最小值。这些汇总信息有助于理解数据的分布情况。
X_stats = {
    'mean': np.mean(X),
    'var': np.var(X),
    'max': np.max(X),
    'min': np.min(X)
}

6. 广播操作 (broadcasting):

  • 对 Y_norm 使用广播操作,将其所有元素乘以常数 2.5,演示如何对数组进行批量操作。
Y_scaled = Y_norm * 2.5

  • 散点图与回归线:展示了标准化后的 X 和 Y 的散点图,并绘制了回归线,直观展示特征间的线性关系。
  • X 和 Y 的分布直方图:展示了标准化后的数据分布。标准化将数据的均值调整为 0,标准差调整为 1,因此数据更加集中。
  • 残差图:残差图展示了回归模型的误差,帮助评估模型的拟合效果。

往期 Numpy 合集

Numpy 十大基础操作 

Numpy 十大高级操作 

NumPy 十大矩阵运算 

最后

以上就是今天所有的内容了。
如果对你来说比较有用,记得点赞、收藏,慢慢学习~
下期会有更多干货等着你!~


Python和机器学习初学者
Python和机器学习分享,只写干货,一起学习~
 最新文章