3、数据预处理基础:缺失值处理、异常值检测、数据标准化与归一化
大家好,我是你们的老朋友。今天咱们聊聊数据预处理。
说实话,很多刚入行的同学觉得建模就是调参、选算法。但我得说句大实话:数据预处理做不好,后面全是白忙活。我在工业界摸爬滚打这些年,见过太多模型跑出来效果差,最后发现是数据没洗干净。嗯,今天就把这块硬骨头啃下来。
核心观点:数据预处理占整个建模流程的60%-80%时间,它决定了模型性能的上限。
3.1 缺失值处理:别让空值毁了你的模型
缺失值,说白了就是数据里某些字段是空的。为什么会这样?可能是传感器故障、人工录入遗漏、或者数据本身就不存在。
我常用的三种处理方式:
- 直接删除:如果缺失比例很小(比如<5%),而且数据量够大,直接删掉那几行。简单粗暴,但有效。
- 填充法:用均值、中位数、众数去填。我个人习惯用中位数,因为它对异常值不敏感。我在做轴承寿命预测时,振动数据的缺失值就是用中位数填的,效果不错。
- 模型预测填充:把缺失字段当目标变量,用其他字段去预测它。这个方法精度高,但计算量大。适合关键字段缺失较多的情况。
小技巧:填充前先看看数据分布。如果是正态分布,用均值;如果是偏态分布,用中位数。别问为什么,问就是经验。
# 代码示例:缺失值处理
import pandas as pd
import numpy as np
# 读取数据
df = pd.read_csv('sensor_data.csv')
# 查看缺失情况
print(df.isnull().sum())
# 用中位数填充数值列
for col in ['temperature', 'vibration', 'pressure']:
df[col].fillna(df[col].median(), inplace=True)
# 用众数填充类别列
df['fault_type'].fillna(df['fault_type'].mode()[0], inplace=True)
print("缺失值处理完成!")
避坑指南:我曾经在一个项目中,直接用0填充了所有缺失值。结果模型学出来全是错的——因为0在物理意义上代表“无信号”,而不是“缺失”。记住:填充值必须符合业务逻辑。
3.2 异常值检测:揪出那些“捣乱”的数据点
异常值,就是那些明显偏离正常范围的数据点。比如传感器突然跳变、人为录入错误。它们会严重干扰模型训练。
我常用的检测方法:
| 方法 | 适用场景 | 优缺点 |
|---|---|---|
| 3σ原则 | 数据近似正态分布 | 简单快速,但对非正态数据效果差 |
| 箱线图法(IQR) | 任意分布 | 鲁棒性强,不受极端值影响 |
| 孤立森林 | 高维数据 | 适合大规模数据,但解释性差 |
我个人最常用的是箱线图法。为什么?因为它不假设数据分布,而且直观。你想想看,Q1-1.5*IQR到Q3+1.5*IQR这个区间,基本能覆盖99%的正常数据。
# 代码示例:箱线图法检测异常值
def detect_outliers_iqr(data, column):
Q1 = data[column].quantile(0.25)
Q3 = data[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = data[(data[column] < lower_bound) | (data[column] > upper_bound)]
return outliers
# 检测振动数据的异常值
outliers = detect_outliers_iqr(df, 'vibration')
print(f"发现 {len(outliers)} 个异常值")
# 处理方式:要么删除,要么用上下界替换
df['vibration'] = df['vibration'].clip(lower=lower_bound, upper=upper_bound)
重要提醒:异常值不一定是“坏”的。在寿命预测中,设备故障前的异常波动恰恰是重要信号。所以,先理解业务,再决定是否处理。
3.3 数据标准化与归一化:让所有特征站在同一起跑线
标准化和归一化,说白了就是把不同量纲的数据拉到同一个尺度。比如温度是0-100℃,振动是0-0.5mm,如果不处理,模型会天然偏向数值大的特征。
两种主流方法:
- 归一化(Min-Max Scaling):把数据缩放到[0,1]区间。公式:x' = (x - min) / (max - min)。适合数据有明确上下界的场景。
- 标准化(Z-score):把数据变成均值为0、标准差为1的分布。公式:x' = (x - μ) / σ。适合数据近似正态分布的场景。
我建议:如果后续要用PCA、SVM、神经网络,优先用标准化。为什么?因为这些算法假设数据服从正态分布。归一化会破坏分布形态。
# 代码示例:标准化与归一化
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# 标准化
scaler_std = StandardScaler()
df_scaled = scaler_std.fit_transform(df[['temperature', 'vibration', 'pressure']])
# 归一化
scaler_mm = MinMaxScaler()
df_normalized = scaler_mm.fit_transform(df[['temperature', 'vibration', 'pressure']])
print("标准化后均值:", df_scaled.mean(axis=0))
print("归一化后范围:", df_normalized.min(axis=0), df_normalized.max(axis=0))
实战经验:我在做锂电池寿命预测时,发现容量衰减数据用标准化效果更好,而电压数据用归一化更稳定。所以,不同特征可以不同处理,别一刀切。
3.4 知识体系总览
下面这张图,是我自己总结的数据预处理核心流程。你看一遍,基本就明白今天讲的内容怎么串起来了。
好了,今天的内容就到这里。数据预处理这块,说白了就是“磨刀不误砍柴工”。你花时间把数据洗干净,后面建模会顺畅很多。记住:垃圾进,垃圾出——这是机器学习领域最朴素的真理。