一文带你搞懂Python中数据预处理的全流程
作者:lbb 小魔仙
在机器学习和深度学习的整个项目流程中,数据预处理是最基础、也最关键的环节——它直接决定了模型训练的效果,甚至影响项目的成败。现实世界中的原始数据,从来都不是“干净可用”的:可能存在缺失值、异常值、重复项,特征之间量纲不一,样本量不足导致模型过拟合,这些问题都会让后续的模型训练陷入困境。
据行业统计,AI 工程师约 70% 的时间都用于数据预处理,而高质量的预处理的能让模型性能提升 20%~50%。对中级 Python 和 AI 学习者而言,掌握数据预处理的全流程,不仅能提升项目落地能力,更能理解“数据决定模型上限”的核心逻辑。本文将用通俗易懂的语言,结合可直接运行的 Python 代码,完整讲解数据清洗、标准化、增强三大核心环节,带你打通从原始数据到训练可用数据的全流程。
一、AI 数据预处理整体流程概述
数据预处理不是孤立的操作,而是一套连贯的流程,核心是将“杂乱无章”的原始数据,转化为“规范统一、优质可用”的训练数据。完整流程可分为 6 个关键步骤,环环相扣:
- 数据加载:读取原始数据(如 CSV 表格、图像文件、文本文件等),转换为 Python 程序可处理的格式(如 pandas 的 DataFrame、NumPy 数组、PIL 图像对象);
- 数据探索:通过统计指标(均值、中位数、方差)、可视化(直方图、散点图)等方式,了解数据的分布规律、缺失情况、异常值范围(本文聚焦核心处理环节,略去详细探索步骤);
- 数据清洗:解决数据“脏”的问题——删除重复项、填充/删除缺失值、识别并修正异常值,让数据变得“干净规整”;
- 数据标准化/归一化:将不同量纲、不同范围的特征(如“年龄”的 0~120 和“收入”的 0~100000)统一到相同尺度,避免模型被数值范围大的特征主导;
- 数据增强:针对样本量不足、模型过拟合的场景,通过人工生成新样本的方式扩充数据集(如图像旋转、翻转,表格数据的特征扰动);
- 数据输出:将处理后的数据集拆分为训练集、验证集、测试集,保存为模型可直接读取的格式(如 numpy 数组、CSV 文件),供后续模型训练使用。
简单来说,整个流程就是“加载原始数据 → 清理杂质 → 统一尺度 → 扩充样本 → 输出可用数据”,每个步骤都有明确的目标和对应的实现方法。
二、数据预处理全流程流程图
为了更清晰地展示各环节的逻辑关系,以下用 Mermaid 语法绘制流程图,直观呈现从原始数据到训练可用数据的完整路径:
渲染错误: Mermaid 渲染失败: Parse error on line 2: ...wchart TD A[原始数据(CSV/图像/文本)] --> B[数 ----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'PS'
注:流程图中标记为浅蓝色的环节,是本文重点讲解的核心操作;绿色标记的是最终目标——得到可用于模型训练的数据。
三、核心环节代码实现(附可运行示例)
以下所有代码均基于 Python 3.8+ 实现,配合 pandas、scikit-learn、albumentations 等常用库,每个代码块都附带详细注释,复制即可运行。先执行以下命令,安装所需依赖库:
# 基础数据处理库(表格数据清洗、标准化) pip install pandas numpy scikit-learn # 图像处理与增强库(核心用于图像增强) pip install albumentations opencv-python pillow # 可视化库(辅助验证处理效果,可选) pip install matplotlib
3.1 数据清洗:处理缺失值、异常值、重复项
数据清洗是预处理的第一步,核心是“去除杂质”。我们以最常见的表格数据(如用户特征、业务数据)为例,演示如何处理缺失值、异常值和重复项——这些问题在结构化数据中最为普遍。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 1. 构造模拟原始数据(模拟真实场景,含缺失值、异常值、重复项)
data = {
"age": [25, 30, np.nan, 40, 35, 30, 150, 28, 30, np.nan], # 缺失值(np.nan)、异常值(150岁,不符合常理)
"income": [5000, 6000, 7000, np.nan, 8000, 6000, 9000, 5500, 6000, 7500], # 缺失值、重复项(6000出现3次)
"gender": ["M", "F", "M", "F", np.nan, "F", "M", "F", "F", "M"] # 缺失值
}
# 转换为DataFrame,方便后续处理
df = pd.DataFrame(data)
print("原始数据(含缺失值、异常值、重复项):")
print(df)
# 2. 处理重复项:删除完全重复的行(若需按特定列去重,可添加subset参数,如subset=["age","income"])
df = df.drop_duplicates()
print("\n删除重复项后的数据:")
print(df)
# 3. 处理缺失值:分类型特征和数值型特征分开处理(更合理)
# 数值型特征(age、income):用中位数填充(避免极值影响,比均值更鲁棒)
df["age"] = df["age"].fillna(df["age"].median())
df["income"] = df["income"].fillna(df["income"].median())
# 分类型特征(gender):用众数填充(出现次数最多的值,最贴合分类逻辑)
df["gender"] = df["gender"].fillna(df["gender"].mode()[0]) # mode()返回众数列表,取第一个
print("\n填充缺失值后的数据:")
print(df)
# 4. 处理异常值:以age为例,用IQR法(四分位数范围)识别并修正(通用且不易受极值影响)
def handle_outliers(df, column):
"""
用IQR法处理数值型特征的异常值
参数:df-数据集,column-需要处理的数值型特征列名
返回:处理异常值后的数据集
"""
# 计算四分位数
q1 = df[column].quantile(0.25) # 第一四分位数(25%分位数)
q3 = df[column].quantile(0.75) # 第三四分位数(75%分位数)
iqr = q3 - q1 # 四分位距
# 计算异常值的边界(超出此范围的视为异常值)
lower_bound = q1 - 1.5 * iqr
upper_bound = q3 + 1.5 * iqr
# 将异常值替换为边界值(也可选择删除,此处替换更保留数据量)
df[column] = np.where(df[column] < lower_bound, lower_bound, df[column])
df[column] = np.where(df[column] > upper_bound, upper_bound, df[column])
return df
# 处理age列的异常值
df = handle_outliers(df, "age")
print("\n处理异常值(age列)后的数据:")
print(df)
# 5. 验证:可视化age分布,查看异常值是否已修正
plt.hist(df["age"], bins=5, edgecolor="black")
plt.title("Age Distribution After Outlier Handling")
plt.xlabel("Age")
plt.ylabel("Count")
plt.show()
关键说明:
- 重复项:
drop_duplicates()可直接删除完全重复的行,若需按特定列去重(如仅按“age”去重),添加subset=["age"]即可; - 缺失值:数值型用中位数/均值,分类型用众数,避免“一刀切”;若缺失值过多(如超过30%),可考虑删除该列;
- 异常值:IQR 法适合大多数场景,也可根据业务规则直接过滤(如年龄范围限制为 0~120 岁)。
3.2 数据标准化/归一化:统一特征尺度
原始数据中,不同特征的量纲和范围差异很大(如“age”是 0~120,“income”是 0~100000),模型训练时会优先关注数值大的特征,导致训练偏差。标准化和归一化的核心作用,就是将所有特征统一到相同尺度,消除量纲影响。
以下用 scikit-learn 中的 StandardScaler(标准化)和 MinMaxScaler(归一化),演示两种最常用的尺度统一方法:
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# 1. 提取需要进行标准化/归一化的数值特征(排除分类型特征gender)
numeric_features = df[["age", "income"]]
# 2. 标准化(StandardScaler):将特征转换为“均值=0,方差=1”的分布
# 适合场景:特征接近正态分布、线性模型(如线性回归、逻辑回归)、神经网络
scaler_standard = StandardScaler()
# 注意:fit_transform()仅用于训练集,测试集需用transform(),避免数据泄露
data_standardized = scaler_standard.fit_transform(numeric_features)
# 转换为DataFrame,方便查看
df_standardized = pd.DataFrame(
data_standardized,
columns=["age_standard", "income_standard"]
)
print("标准化后的数据(均值≈0,方差≈1):")
print(df_standardized)
print(f"age标准化后均值:{df_standardized['age_standard'].mean():.4f},方差:{df_standardized['age_standard'].var():.4f}")
# 3. 归一化(MinMaxScaler):将特征缩放到[0,1]区间
# 适合场景:特征分布无规律、需要固定范围(如图像像素值、决策树类模型)
scaler_minmax = MinMaxScaler()
data_normalized = scaler_minmax.fit_transform(numeric_features)
df_normalized = pd.DataFrame(
data_normalized,
columns=["age_minmax", "income_minmax"]
)
print("\n归一化后的数据(范围[0,1]):")
print(df_normalized)
print(f"age归一化后最小值:{df_normalized['age_minmax'].min():.4f},最大值:{df_normalized['age_minmax'].max():.4f}")
# 4. 将处理后的特征合并到原数据集,得到完整的清洗+标准化/归一化数据集
df_final = pd.concat([df, df_standardized, df_normalized], axis=1) # axis=1表示按列合并
print("\n最终处理后的完整数据集:")
print(df_final)
关键说明:
- 标准化公式:x′=(x−μ)/σ(μ 是均值, σ 是方差),适合大多数机器学习模型;
- 归一化公式: x′=(x−min)/(max−min),适合对特征范围有明确要求的场景(如图像预处理);
- 核心禁忌:不要用训练集的
fit_transform()处理测试集,需先用训练集的 scaler 拟合,再用transform()处理测试集,避免数据泄露。
3.3 数据增强:以图像为例(albumentations 实现)
数据增强的核心目的是“扩充样本量”,避免模型过拟合——尤其是在深度学习图像任务中,样本量不足会导致模型无法学习到足够的特征规律。本文默认以图像为例,使用 albumentations 库(比 imgaug 更高效、兼容性更好)演示常见的图像增强操作。
import cv2
import albumentations as A
from PIL import Image
import numpy as np
# 1. 加载测试图像(替换为你的本地图像路径,如"test.jpg")
image_path = "test.jpg"
# 用cv2读取图像(注意:cv2默认读取为BGR格式,需转换为RGB)
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 转换为RGB格式(albumentations默认处理RGB)
print(f"原始图像形状(高、宽、通道数):{image.shape}")
# 2. 定义图像增强流水线(组合多种增强操作,可根据需求调整)
# p表示操作执行的概率(0~1),避免过度增强导致数据失真
transform = A.Compose([
A.Resize(height=224, width=224), # 统一图像尺寸(适配大多数CNN模型输入)
A.HorizontalFlip(p=0.5), # 水平翻转(50%概率执行)
A.VerticalFlip(p=0.2), # 垂直翻转(20%概率执行)
A.RandomRotate90(p=0.3), # 随机旋转90度(30%概率执行)
A.RandomBrightnessContrast(p=0.2), # 随机调整亮度和对比度(20%概率执行)
A.GaussianBlur(blur_limit=(3, 7), p=0.1), # 高斯模糊(10%概率执行,模糊程度3~7)
# 图像归一化(适配PyTorch预训练模型,如ResNet、ViT,均值和标准差为行业通用值)
A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
# 3. 执行增强并保存结果(生成5个增强后的样本,可调整数量)
for i in range(5):
# 执行增强操作
augmented = transform(image=image)
aug_image = augmented["image"] # 得到增强后的图像数组
# 反归一化(仅用于可视化,因为归一化后的图像像素值为浮点数,无法直接显示)
aug_image_visual = (aug_image * np.array([0.229, 0.224, 0.225]) + np.array([0.485, 0.456, 0.406]))
aug_image_visual = (aug_image_visual * 255).astype(np.uint8) # 转换为0~255的整数(图像像素值范围)
# 转换为PIL图像并保存(方便查看增强效果)
aug_image_pil = Image.fromarray(aug_image_visual)
aug_image_pil.save(f"augmented_image_{i+1}.jpg")
print(f"已保存增强图像 {i+1}:augmented_image_{i+1}.jpg")
# 4. 可视化原始图像和第一个增强图像(直观对比效果)
plt.figure(figsize=(10, 5))
# 原始图像
plt.subplot(1, 2, 1)
plt.imshow(Image.fromarray(image))
plt.title("Original Image")
plt.axis("off") # 隐藏坐标轴
# 增强后图像
plt.subplot(1, 2, 2)
plt.imshow(aug_image_pil)
plt.title("Augmented Image (Example)")
plt.axis("off")
plt.show()
关键说明:
- albumentations 支持多种增强操作,可根据任务调整(如目标检测任务需添加
bboxes参数,避免破坏目标位置); - 增强概率(p)建议控制在 0.1~0.5 之间,过度增强(如100%概率翻转)会导致数据失真;
- 若处理表格数据,增强可采用“特征扰动”(如给数值特征加微小噪声:
df["age"] += np.random.normal(0, 0.5, len(df)))。
四、结语
数据预处理的核心,从来都不是“机械执行操作”,而是“让数据适配模型”。干净、标准化的数据,能让模型聚焦于特征规律而非数据噪声,避免因缺失值、异常值导致的训练偏差;合理的数据增强,能弥补样本量不足的短板,显著提升模型的泛化能力——即使是简单的模型,在优质数据的支撑下,也能取得远超“顶级模型+劣质数据”的效果。
需要注意的是,本文演示的是通用流程,实际应用中需根据具体任务定制:
- 表格数据:重点关注缺失值、异常值的处理,标准化/归一化需结合特征分布选择,增强可采用特征扰动;
- 图像数据:重点关注增强策略(避免破坏关键特征,如人脸图像不适合过度旋转),归一化需适配模型要求;
- 文本数据:需额外添加分词、停用词删除、词向量转换等环节,清洗重点是处理错别字、特殊符号。
对中级 Python 和 AI 学习者而言,建议多动手实践——尝试用不同的方法处理同一批数据,观察数据变化和后续模型训练效果,逐步积累经验。记住:数据的质量决定了模型的上限,算法只是逼近这个上限的工具,花足够的时间打磨数据预处理流程,是 AI 项目成功的关键。
关键点回顾
- 数据清洗:重复项直接删除,缺失值按特征类型(数值/分类)选中位数/众数填充,异常值用 IQR 法或业务规则处理;
- 标准化/归一化:标准化(均值0、方差1)适合线性模型,归一化(0~1范围)适合固定范围需求,仅在训练集拟合;
- 图像增强:用 albumentations 组合翻转、旋转、亮度调整等操作,控制增强概率,避免数据失真。
到此这篇关于一文带你搞懂Python中数据预处理的全流程的文章就介绍到这了,更多相关Python数据预处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
