3、数据预处理:数据清洗、缺失值处理、异常值检测、数据标准化与归一化

各位同学,咱们直接进入正题。

数据预处理,说白了就是给原始数据「洗澡」。你想想看,从生产环境捞出来的监控数据,那叫一个脏。我见过太多人,模型建得花里胡哨,结果数据没洗干净,最后全白干。嗯,咱们今天就把它捋清楚。

3.1 数据清洗:把垃圾筛出去

数据清洗,核心就四个字:去重、纠错。

我在项目中遇到过最典型的场景——某次磁盘IO监控,同一台机器在同一个时间戳上报了两次数据。你说这算不算脏数据?当然算。如果不处理,后续的均值计算、趋势分析全都会偏。

常见脏数据类型:

  • 重复数据:同一时间戳、同一指标,出现多条记录
  • 格式错误:比如时间戳写成 "2024-01-01 00:00:00" 和 "2024/01/01 00:00:00" 混在一起
  • 逻辑错误:CPU使用率超过100%,或者内存剩余为负数
  • 无关字段:比如日志里混入了调试信息、乱码字符

我个人习惯,清洗的第一步永远是「看一眼原始数据」。别急着写脚本,先抽样看看长什么样。你可能会发现一些意想不到的问题。

# 一个简单的去重示例(Python)
import pandas as pd

df = pd.read_csv('monitor_data.csv')
# 按时间戳和机器ID去重,保留第一条
df_clean = df.drop_duplicates(subset=['timestamp', 'host_id'], keep='first')

小技巧:去重时别光看行数。我建议你打印出去重前后的行数对比,心里有个数。如果去重率超过5%,那说明上游采集逻辑有问题,得去修。

3.2 缺失值处理:别让空值坑了你

缺失值,几乎是每个运维系统都逃不过的坎。为什么会这样?网络抖动、采集器重启、数据管道延迟……原因太多了。

处理缺失值,我把它分成三步走:

  1. 先定位:哪些字段有缺失?缺失率多少?
  2. 再判断:这个缺失是随机的,还是系统性的?
  3. 最后处理:选合适的方法填上或删掉。

注意:千万别一上来就全删了。我曾经有个同事,看到缺失值直接 dropna(),结果把故障发生前5分钟的关键数据全删了。那叫一个惨。

常用的缺失值处理方法,我整理了一张表:

方法 适用场景 我的建议
直接删除 缺失率 < 1%,且随机分布 简单粗暴,但慎用
均值/中位数填充 数值型指标,数据波动不大 CPU、内存这类可以用
前向填充(ffill) 时序数据,短时间缺失 我个人最常用,符合直觉
插值法 数据有趋势,缺失段不长 比如网络流量曲线,效果不错
模型预测 缺失率较高,且有关联特征 杀鸡不用牛刀,慎用
# 前向填充示例
df['cpu_usage'] = df['cpu_usage'].ffill()

# 插值法示例
df['network_traffic'] = df['network_traffic'].interpolate(method='linear')

避坑指南:我曾经处理过一个K8s集群的监控数据,发现某个节点的内存指标连续缺失了2小时。一开始我以为是采集器挂了,后来一查——那台机器被重启了,期间根本没数据。这种情况下,前向填充就不合适了,我最后选择了标记为「异常区间」。

3.3 异常值检测:揪出那些「不对劲」的数据

异常值检测,说白了就是找「刺头」。但你要搞清楚——异常值不等于错误值。有时候,异常值恰恰是故障的前兆。

我常用的方法有三种:

  • 3σ原则:假设数据服从正态分布,超出均值±3倍标准差的就是异常。简单,但要求数据分布比较规整。
  • 箱线图法(IQR):用四分位数来界定。Q1 - 1.5*IQR 到 Q3 + 1.5*IQR 之外的就是异常。这个对分布要求没那么严格。
  • 孤立森林:机器学习方法,适合高维数据。我一般在做大规模异常检测时才用。
# 3σ 检测示例
import numpy as np

mean = df['cpu_usage'].mean()
std = df['cpu_usage'].std()
threshold = 3

df['is_anomaly'] = (np.abs(df['cpu_usage'] - mean) > threshold * std).astype(int)

重要提醒:异常值检测的阈值不是死的。我建议你根据业务场景动态调整。比如,白天业务高峰期,CPU冲到90%是正常的;凌晨3点CPU冲到90%,那大概率有问题。

3.4 数据标准化与归一化:让数据站在同一起跑线

这一步,很多人容易忽略。你想想看,CPU使用率是0~100,内存使用量是GB级别,网络延迟是毫秒级。这些数据量纲都不一样,直接丢进模型里,结果肯定被大数值的指标带偏。

标准化和归一化,我简单区分一下:

  • 归一化(Min-Max Scaling):把数据缩放到 [0, 1] 区间。适合数据有明确上下界的场景,比如CPU使用率。
  • 标准化(Z-score):把数据变成均值为0、标准差为1的分布。适合数据分布未知、有离群点的场景。
# 归一化
from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
df['cpu_normalized'] = scaler.fit_transform(df[['cpu_usage']])

# 标准化
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
df['cpu_standardized'] = scaler.fit_transform(df[['cpu_usage']])

注意:标准化和归一化,一定要先拆分训练集和测试集,再用训练集的参数去变换测试集。我见过有人把全量数据一起标准化,然后做模型评估——那结果根本不能反映真实情况。

我个人习惯,在故障识别场景中,优先用标准化。因为运维数据里经常有突发峰值,归一化会被这些峰值压扁,导致正常数据之间的差异变小。

知识体系总览

下面这张图,把数据预处理的四个核心步骤串起来了。你可以把它当作一个检查清单:

数据预处理流程 原始监控数据 步骤1:数据清洗(去重、纠错) 步骤2:缺失值处理(填充/删除) 步骤3:异常值检测(3σ/IQR/孤立森林) 步骤4:标准化/归一化(Z-score/Min-Max)

嗯,数据预处理这块,说难不难,说简单也不简单。关键是要养成习惯——拿到数据先看、先洗、先处理,别急着建模。我在项目里吃过太多亏了,希望你少走这些弯路。


公众号:蓝海资料掘金营,微信deep3321