数据预处理与质量控制方法归纳总结
数据预处理,说白了就是给原始数据“洗澡”。我做了这么多年QSAR,见过太多因为数据脏导致模型翻车的案例。今天就把这套洗澡流程给大家掰开揉碎了讲清楚。
核心原则:坏数据进,坏模型出。预处理不是可选步骤,是必须项。
数据清洗——把明显有问题的数据筛掉
拿到数据第一件事,不是急着建模。你得先看看数据长什么样。我个人习惯先用描述性统计扫一遍,看看有没有明显不对劲的地方。
| 问题类型 | 识别方法 | 处理方式 |
|---|---|---|
| 缺失值 | 统计每列的NA/NaN数量 | 删除(<5%)、插补(5-20%)、标记(>20%) |
| 重复样本 | 基于SMILES或结构指纹去重 | 保留活性值最极端的,或取平均 |
| 异常活性值 | Z-score > 3 或 IQR法 | 检查原始记录,确认后删除或修正 |
| 结构解析错误 | RDKit解析失败 | 手动检查SMILES,修复或丢弃 |
避坑:我曾经遇到过一批数据,SMILES看起来没问题,但用RDKit一解析就报错。后来发现是SMILES里混了中文字符。这种数据一定要用代码批量检查,肉眼看不出来。
要养成用脚本检查数据的习惯。下面是我常用的检查代码:
import pandas as pd from rdkit import Chem
df = pd.read_csv('training_data.csv')
# 检查缺失值
print(df.isnull().sum())
# 检查SMILES合法性
valid_smiles = df['smiles'].apply(lambda x: Chem.MolFromSmiles(x) is not None)
print(f'非法SMILES数目: {(~valid_smiles).sum()}')
# 检查重复
print(f'重复样本数目: {df.duplicated(subset=["smiles"]).sum()}')
缺失值处理——别让空缺影响判断
缺失值怎么处理?这得看情况。我个人把缺失值处理分成三类场景:
- 轻度缺失(<5%):直接删除,最简单粗暴,影响也不大
- 中度缺失(5-20%):用插补法。数值型用均值或中位数,类别型用众数。如果活性值缺失,我建议用相似化合物的活性做KNN插补
- 重度缺失(>20%):直接放弃这个特征。强行插补只会引入噪声,得不偿失
个人经验:对于描述符矩阵的缺失值,我更喜欢用迭代插补(IterativeImputer)。它考虑到了特征之间的关联性,效果比简单均值好不少。
异常值检测——揪出那个捣蛋鬼
异常值会让模型学偏。你想想看,一个离群点就能把线性回归的线拉歪,多可怕。我常用两种方法:
- Z-score法:计算每个值偏离均值的标准差数,>3的视为异常
- 箱线图法(IQR):Q1-1.5*IQR到Q3+1.5*IQR之外的算异常
实际项目中,我一般两种方法都跑,取交集。这样能减少误删正常数据的风险。
重要提醒:对于活性值(pIC50、pKi等)的异常值,不要轻易删除。先查原始文献,确认是不是实验误差。有时异常值反而是重要发现的前兆。
数据标准化——把不同尺度的数据拉到同一水平线
标准化有什么用?说白了,就是让描述符之间可以公平比较。一个描述符取值范围0-1,另一个0-1000,如果不标准化,模型会天然偏向数值大的那个。
| 方法 | 公式 | 适用场景 |
|---|---|---|
| Z-score标准化 | (x-μ)/σ | 数据近似正态分布,大部分情况适用 |
| Min-Max归一化 | (x-min)/(max-min) | 数据有明确边界,如[0,1]区间要求 |
| Robust标准化 | (x-median)/IQR | 数据含有较多异常值 |
我个人发展,做QSAR时Z-score用得最多。但要注意——先划分训练集和测试集,再用训练集的均值和标准差去标准化测试集。千万别放一起标准化,否则会造成数据泄露。
from sklearn.preprocessing import StandardScaler
# 正确做法:分开拟合
X_train, X_test = train_test_split(X, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test) # 用训练集的参数
血的教训:我曾经把整个数据集一起标准化,然后做PCA。结果模型在验证集上效果贼好,心里美滋滋。后来做了个外部测试,结果直接崩了。查了半天才发现是数据泄露的问题。从那以后,我每次做预处理都极其注意训练/测试集的分离。
质量控制指标——给数据打分
数据预处理完了,怎么判断质量好不好?不能光凭感觉。我建议用几个量化指标来评估:
- 数据覆盖率:有效描述符占总描述符的比例。低于70%要警惕
- 特征稳定性:多次实验测量值的变异系数(CV)。CV>0.3说明这个特征不稳定
- 样本代表性:训练集的化学空间能否覆盖测试集。用Tanimoto距离衡量
- 活性分布:看活性值是否均匀分布。太偏的分布会影响模型泛化能力
小技巧:做一个数据质量报告表,每次预处理完都自动生成。包括缺失率、异常值数、特征稳定性等。这样方便追踪数据版本之间的质量变化。
下面是我整个数据预处理与质量控制的流程图,把每个步骤串起来看更清楚:
这个流程看起来简单,但每一步都可能踩坑。我记得有个项目,数据清洗完觉得没问题了,结果建模后R²只有0.3。后来发现是异常值处理太保守,把一些变异大的但合法的结构给删了。从那以后,我每次处理异常值都会可视化看一下分布,再决定阈值。
总结一下关键点:
1. 数据清洗是基础,SMILES合法性检查必须做
2. 缺失值处理根据比例选择策略,别一刀切
3. 异常值检测结合Z-score和IQR,交叉验证
4. 标准化务必训练集和测试集分开
5. 质量控制要量化,用指标说话
1. 数据清洗是基础,SMILES合法性检查必须做
2. 缺失值处理根据比例选择策略,别一刀切
3. 异常值检测结合Z-score和IQR,交叉验证
4. 标准化务必训练集和测试集分开
5. 质量控制要量化,用指标说话
数据预处理做得好,建模就成功了一半。嗯,这个环节花再多时间都值得。毕竟我们做QSAR的,最后拼的就是数据质量。数据干净了,模型自然就能学到真正有意义的规律。