三行Python代码,让数据预处理速度提高2到6倍

通过Python的concurrent.futures模块,仅需3行代码即可利用多核处理器并行处理,显著提高数据预处理速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在 Python 中,我们可以找到原生的并行化运算指令。本文可以教你仅使用 3 行代码,大大加快数据预处理的速度。


Python 是机器学习领域内的首选编程语言,它易于使用,也有很多出色的库来帮助你更快处理数据。但当我们面临大量数据时,一些问题就会显现……


目前,大数据(Big Data)这个术语通常用于表示包含数十万数据点的数据集。在这样的尺度上,工作进程中加入任何额外的计算都需要时刻注意保持效率。在设计机器学习系统时,数据预处理非常重要——在这里,我们必须对所有数据点使用某种操作。


在默认情况下,Python 程序是单个进程,使用单 CPU 核心执行。而大多数当代机器学习硬件都至少搭载了双核处理器。这意味着如果没有进行优化,在数据预处理的时候会出现「一核有难九核围观」的情况——超过 50% 的算力都会被浪费。在当前四核处理器(英特尔酷睿 i5)和 6 核处理器(英特尔酷睿 i7)大行其道的时候,这种情况会变得更加明显。


幸运的是,Python 库中内建了一些隐藏的特性,可以让我们充分利用所有 CPU 核心的能力。通过使用 Python 的 concurrent.futures 模块,我们只需要 3 行代码就可以让一个普通的程序转换成适用于多核处理器并行处理的程序。


标准方法

让我们举一个简单的例子,在单个文件夹中有一个图片数据集,其中有数万张图片。在这里,我们决定使用 1000 张。我们希望在所有图片被传递到深度神经网络之前将其调整为 600×600 像素分辨率的形式。以下是你经常会在 GitHub 上看到的标准 Python 代码:

import glob
import os
import cv2


### Loop through all jpg files in the current folder 
### Resize each one to size 600x600
for image_filename in glob.glob("*.jpg"):
 ### Read in the image data
 img = cv2.imread(image_filename)

 ### Resize the image
 img = cv2.resize(img, (600, 600)) 


上面的程序遵循你在处理数据脚本时经常看到的简单模式:

  1. 首先从需要处理内容的文件(或其他数据)列表开始。
  2. 使用 for 循环逐个处理每个数据,然后在每个循环迭代上运行预处理。

让我们在一个包含 1000 个 jpeg 文件的文件夹上测试这个程序,看看运行它需要多久:

time python standard_res_conversion.py

在我的酷睿 i7-8700k 6 核 CPU 上,运行时间为 7.9864 秒!在这样的高端 CPU 上,这种速度看起来是难以让人接受的,看看我们能做点什么。


更快的方法

为了便于理解并行化的提升,假设我们需要执行相同的任务,比如将 1000 个钉子钉入木头,假如钉入一个需要一秒,一个人就需要 1000 秒来完成任务。四个人组队就只需要 250 秒。


在我们这个包含 1000 个图像的例子中,可以让 Python 做类似的工作:

  • 将 jpeg 文件列表分成 4 个小组;
  • 运行 Python 解释器中的 4 个独立实例;
  • 让 Python 的每个实例处理 4 个数据小组中的一个;
  • 结合四个处理过程得到的结果得出最终结果列表。

这一方法的重点在于,Python 帮我们处理了所有棘手的工作。我们只需告诉它我们想要运行哪个函数,要用多少 Python 实例,剩下的就交给它了!只需改变三行代码。实例:

import glob
import os
import cv2
import concurrent.futures


def load_and_resize(image_filename):
 ### Read in the image data
 img = cv2.imread(image_filename)

 ### Resize the image
 img = cv2.resize(img, (600, 600)) 


### Create a pool of processes. By default, one is created for each CPU in your machine.
with concurrent.futures.ProcessPoolExecutor() as executor:
 ### Get a list of files to process
 image_files = glob.glob("*.jpg")

 ### Process the list of files, but split the work across the process pool to use all CPUs
 ### Loop through all jpg files in the current folder 
 ### Resize each one to size 600x600
 executor.map(load_and_resize, image_files)

从以上代码中摘出一行:

with concurrent.futures.ProcessPoolExecutor() as executor:

你的 CPU 核越多,启动的 Python 进程越多,我的 CPU 有 6 个核。实际处理代码如下:

executor.map(load_and_resize, image_files)

「executor.map()」将你想要运行的函数和列表作为输入,列表中的每个元素都是我们函数的单个输入。由于我们有 6 个核,我们将同时处理该列表中的 6 个项目!


如果再次用以下代码运行我们的程序:

time python fast_res_conversion.py

我们可以将运行时间降到 1.14265 秒,速度提升了近 6 倍!


注意:在生成更多 Python 进程及在它们之间整理数据时会有一些开销,所以速度提升并不总是这么明显。但是总的来说,速度提升还是非常可观的。


它总是那么快吗?

如果你有一个数据列表要处理,而且在每个数据点上执行相似的运算,那么使用 Python 并行池是一个很好的选择。但有时这不是最佳解决方案。并行池处理的数据不会在任何可预测的顺序中进行处理。如果你对处理后的结果有特殊顺序要求,那么这个方法可能不适合你。


你处理的数据也必须是 Python 可以「炮制」的类型。所幸这些指定类别都很常见。以下来自 Python 官方文件:

  • None, True, 及 False
  • 整数、浮点数、复数
  • 字符串、字节、字节数组
  • 只包含可挑选对象的元组、列表、集合和字典
  • 在模块顶层定义的函数(使用 def ,而不是 lambda )
  • 在模块顶层定义的内置函数
  • 在模块顶层定义的类
  • 这种类的实例,其 dict 或调用__getstate__() 的结果是可选择的(参见「Pickling Class Instances」一节)。

推荐阅读:极简Python带你探索分类与回归的奥秘

<think>好的,用户现在想要了解关于Python数据预处理代码。我需要先回顾之前的对话历史,看看用户之前问了什么。之前用户问的是关于untitledd.ipynb文件,我解释了Jupyter Notebook的基本信息和相关操作。现在用户转向数据预处理,这可能是他们在进行数据分析或机器学习项目时的需求。 首先,用户可能正在开始一个数据科学项目,需要处理数据,但还不熟悉具体的步骤和代码。他们可能希望得到一个结构化的指导,包括常用的库和步骤,比如处理缺失值、数据转换、特征工程等。此外,用户可能希望代码示例可以直接在Jupyter Notebook中运行,这可能与他们之前提到的.ipynb文件有关。 接下来,我需要确定用户的需求层次。他们可能是一个刚入门的数据科学学习者,需要基础的数据预处理代码示例。或者,他们可能有特定的数据处理问题,比如处理缺失值或分类变量,但没有明确说明。考虑到用户的问题比较广泛,我应该覆盖数据预处理的主要步骤,并提供示例代码,这样他们可以有一个全面的参考。 同时,用户之前的相关问题涉及创建Jupyter Notebook、修改文件结构和转换格式,所以可能需要确保代码示例在Jupyter环境中运行顺畅,并提及如何保存和分享这些预处理步骤的结果,比如导出为HTML或PDF。 需要注意用户的潜在需求,比如他们可能在处理真实数据时遇到问题,如数据清洗、特征缩放或编码分类变量。因此,我需要确保提供的代码示例涵盖这些常见任务,并解释每个步骤的目的,帮助他们理解为什么需要这些预处理步骤。 另外,用户可能希望代码简洁明了,使用流行的库如Pandas、NumPy和Scikit-learn,这些是数据预处理的标准工具。我需要确认代码的正确性,并提醒安装这些库的必要性,尽管在Jupyter环境中可能已经预装。 最后,我应该结构化回答,分步骤解释每个预处理任务,提供代码示例,并可能给出注意事项或进一步学习的建议,比如推荐文档或教程链接。这样用户不仅能复制代码,还能理解每个步骤的意义,促进他们的学习过程。</think>以下是 Python 数据预处理的典型代码框架和关键步骤,涵盖数据清洗、特征工程等核心操作: --- ### 一、基础库导入 ```python import pandas as pd import numpy as np from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.impute import SimpleImputer from sklearn.compose import ColumnTransformer ``` --- ### 二、数据加载 ```python # 读取 CSV 文件 df = pd.read_csv('your_data.csv') # 查看前 5 行数据 print(df.head()) # 查看数据基本信息 print(df.info()) ``` --- ### 三、缺失值处理 #### 1. 删除缺失值 ```python # 删除包含缺失值的行 df.dropna(axis=0, inplace=True) # 删除缺失值超过 50% 的列 df = df.loc[:, df.isnull().mean() < 0.5] ``` #### 2. 填充缺失值 ```python # 数值列用均值填充 df['age'].fillna(df['age'].mean(), inplace=True) # 分类列用众数填充 df['gender'].fillna(df['gender'].mode()[0], inplace=True) ``` --- ### 四、数据类型转换 ```python # 字符串转日期 df['date'] = pd.to_datetime(df['date']) # 数值转分类 df['age_group'] = pd.cut(df['age'], bins=[0,18,35,60,100], labels=['child', 'young', 'adult', 'senior']) ``` --- ### 五、异常值处理 ```python # 通过标准差识别异常值 mean = df['income'].mean() std = df['income'].std() df = df[(df['income'] > mean - 3*std) & (df['income'] < mean + 3*std)] # 或使用分位数处理 Q1 = df['income'].quantile(0.25) Q3 = df['income'].quantile(0.75) IQR = Q3 - Q1 df = df[~((df['income'] < (Q1 - 1.5*IQR)) | (df['income'] > (Q3 + 1.5*IQR)))] ``` --- ### 六、特征编码 #### 1. 独热编码 ```python df = pd.get_dummies(df, columns=['city'], prefix='city') ``` #### 2. 标签编码 ```python from sklearn.preprocessing import LabelEncoder le = LabelEncoder() df['education'] = le.fit_transform(df['education']) ``` --- ### 七、特征缩放 ```python # 标准化(适合大多数情况) scaler = StandardScaler() df[['age', 'income']] = scaler.fit_transform(df[['age', 'income']]) # 归一化(将数据压缩到 0-1 范围) from sklearn.preprocessing import MinMaxScaler minmax = MinMaxScaler() df[['height', 'weight']] = minmax.fit_transform(df[['height', 'weight']]) ``` --- ### 八、管道操作(推荐) ```python # 定义数值/分类列 numeric_features = ['age', 'income'] categorical_features = ['gender', 'education'] # 创建预处理管道 preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), numeric_features), ('cat', OneHotEncoder(), categorical_features) ]) # 应用预处理 processed_data = preprocessor.fit_transform(df) ``` --- ### 九、保存预处理结果 ```python # 保存为 CSV df.to_csv('cleaned_data.csv', index=False) # 保存预处理管道(用于后续新数据) import joblib joblib.dump(preprocessor, 'preprocessor.pkl') ``` --- ### 注意事项: 1. 预处理步骤需根据数据分布特点调整 2. 分类变量处理前需检查类别一致性 3. 特征工程后建议进行相关性分析 4. 训练集/测试集的预处理应使用相同参数 如果需要具体场景的代码示例(如时间序列处理、文本数据预处理等),可以补充说明需求细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值