1-数据清洗与采样策略

1. 为什么数据质量往往比模型复杂度更重要

1.1 机器学习的根本约束

机器学习的核心假设是训练数据 独立同分布(i.i.d.)。模型从数据中学到的,本质上是数据中蕴含的统计规律。若数据本身存在问题,无论模型多复杂、学到的参数都与真实目标产生偏差。

一个粗略的量化关系:

  • 数据质量:影响模型能够学到的上限( Bayes Error Rate 附近)
  • 模型复杂度:影响模型能否逼近这个上限
  • 数据规模:在固定质量下,规模越大,模型越能覆盖真实分布

当数据质量低下时,增加模型复杂度和训练数据规模只能放大噪声,而非学到真正有用的模式。

1.2 错误数据对训练的伤害

以二分类为例,设训练样本中有一小部分标签是随机错误的(label noise)。若不加处理:

  • SGD 场景:模型会在这些错误样本上浪费宝贵的梯度更新,导致整体收敛速度变慢
  • 深度网络场景:由于深度网络强大的拟合能力,模型会记忆这些错误标签,在正确标签的样本上泛化性能反而下降
  • 对比学习场景:错误标签导致正样本对构造错误,模型学到的是错误样本之间的关系而非语义关系

经验上常见(empirical common practice):在真实工业数据中,5%10% 的标签噪声率并不罕见。若不加处理,最终模型性能可能下降 515 个百分点。


2. 数据质量问题详解

2.1 噪声标签(Noisy Labels)

来源

  • 人工标注错误:标注员疲劳或专业知识不足,尤其在细粒度分类中(如不同鸟类的区分)
  • 自动标注的遗留问题:用规则或弱模型自动标注后未做人工校验(如用关键词匹配做情感分类)
  • 标签模糊性:样本本身可能属于多个类别,但被迫分配单一标签

对训练的影响

对于随机标签噪声(symmetric noise),模型学到的条件概率 会被噪声转移矩阵(noise transition matrix)混淆。设噪声转移概率为 ,则经验风险最小化是在噪声分布而非真实分布上的优化。

处理方法

方法原理适用场景
Label Smoothing将硬标签软化为 轻度噪声(
Co-teaching两个网络互相过滤对方认为是噪声的样本中度噪声(
置信度学习(Confident Learning)通过模型预测置信度识别可能的噪声样本可与任何训练流程结合
数据重标注对被识别为噪声的样本重新标注噪声比例低、但每条数据价值高

2.2 重复样本(Duplicate Samples)

来源

  • 爬虫重复抓取:同一页面被多次存入数据库
  • 数据拼接错误:不同来源的数据合并时出现完全相同的行
  • 数据增强副作用:某些流水线对同一原始样本做了数据增强后多次加入训练集,但记录方式导致视为不同样本

对训练的伤害

重复样本的危害不来自”样本本身”,而来自其对采样分布的扭曲

  • 若某样本重复 100 次,则在随机梯度采样(SGD)中该样本被选中的概率是其他样本的 100 倍
  • 这相当于对这类样本做了隐性加权,使模型过度拟合到重复样本的模式
  • 在极端情况下,重复样本可能导致模型只学会识别少数”被重复”的模式,而忽略真正具有判别性的特征

检测方法

方法实现适用场景
精确哈希对完整样本计算 MD5/SHA 哈希,完全相同的视为重复结构化数据(数值/类别特征)
近似最近邻对 embedding 向量建立ANN索引,找出 cosine similarity > 0.99 的样本对非结构化数据(文本/图像 embedding)
MinHash / SimHash用于大规模网页去重,LSH(局部敏感哈希)族十亿级网页去重

2.3 脏数据(Dirty Data)

类型

  • 格式错误:如数值字段出现文本、日期字段格式不统一
  • 范围异常:如年龄字段出现 999-1,或评论长度为 0
  • 注入攻击:如爬取的文本中包含 HTML 标签、SQL 注入片段、特殊控制字符
  • 编码错误:如文本以 UTF-8 读取后出现乱码(

对训练的影响

脏数据进入训练后,模型的梯度更新会受到污染。在深度网络中,脏数据可能导致激活值出现极端值(outlier),进而影响 batch normalization 的统计量估计,或在 attention 计算中引入噪声。

2.4 长尾分布(Long-Tail Distribution)

定义

长尾分布指少数类别(head classes)拥有极大量的样本,而多数类别(tail classes)只有少量样本。这种分布在自然语言处理(话题分类)和计算机视觉(细粒度识别)中普遍存在。

若不加以处理,模型会在 head classes 上表现良好,在 tail classes 上几乎无法工作。

量化指标

其中 是第 个类的样本数。当比率 时,长尾问题通常已经严重。

2.5 类别不平衡(Class Imbalance)

长尾分布是类别不平衡的一种形式,但两者有细微区别:

  • 类别不平衡:各类别样本数量不均,可能有明确的头部和尾部,但不一定是”长尾”
  • 长尾分布:头部与尾部之间的差距极大,呈幂律分布特征

3. 数据清洗流程

3.1 四阶段清洗框架

工业级数据清洗通常分为四个阶段,由浅入深:

原始数据 → 规则过滤 → 统计过滤 → 模型过滤 → 人工抽检

3.2 规则过滤(Rule-based Filtering)

规则过滤是最快速、成本最低的清洗手段,适用于明确的”坏样本”定义。

常用规则

规则类型示例作用
长度过滤文本长度 tokens 或 tokens去除过短/过长的无意义样本
格式过滤包含 HTML 标签、特殊控制字符(\x00去除注入攻击和编码错误
词汇过滤包含”undefined”、“null”、“NaN” 等占位符去除未填充的占位符内容
来源过滤来自已知质量差的站点/用户去除可信度低的来源
时间过滤超出合理时间范围的样本(如未来日期)去除时间戳错误数据

特点:速度快,可并行处理;但只能过滤明确的”坏样本”,无法处理”有问题但不明确”的边界样本。

3.3 统计过滤(Statistical Filtering)

统计过滤基于样本在某些统计量上的异常来识别潜在问题。

方法 1:分布检验

对关键数值特征(如文本长度、token 数量、图片尺寸)计算分布。若某样本的数值落在分布的极端尾端(如超出 ),标记为可疑。

方法 2:TF-IDF 异常检测

对文本数据,计算每个样本的 TF-IDF 向量与整体 centroids 的距离。若某样本的最近邻距离异常大(> 某阈值),可能是脏数据或非目标语言。

方法 3:Embedding 异常检测

对文本/图像训练 embedding,然后做 UMAP/t-SNE 可视化,检查是否存在离群点(outlier)。也可用 Isolation Forest 等无监督方法检测 embedding 空间中的离群点。

3.4 模型过滤(Model-based Filtering)

模型过滤使用轻量级的可训练模型来识别”低质量”样本。

方法 1:语言模型困惑度过滤

用语言模型对文本样本计算困惑度(perplexity)。困惑度异常高的样本(如 量级)通常是乱码或无意义内容;困惑度异常低的样本可能是重复内容或过于模板化的文本。

方法 2:置信度过滤(Confident Learning)

以交叉验证方式训练模型,对每个样本记录模型预测的置信度。若某样本的标签与模型高置信度预测不符,标记为潜在噪声标签。

# Confident Learning 的简化实现
for sample in dataset:
    pred_label, pred_confidence = model.predict(sample)
    if pred_confidence > threshold and pred_label != sample.label:
        # 可能是标签噪声
        noise_candidates.append(sample)

方法 3:文本质量分类器

训练一个文本质量分类器(如”高质量新闻 vs 低质量新闻”),对每个样本预测质量分数,过滤掉分数低于阈值的样本。

3.5 人工抽检(Manual Inspection)

所有自动化清洗后,必须进行人工抽检作为最终质量把关。抽检方式:

  • 随机抽检:从清洗后的数据中随机抽取 条,人工评估是否符合预期
  • 分层抽检:从不同类别、不同质量区间各抽取一定比例,确保各层都经过评估
  • 边界样本抽检:重点检查被规则过滤、统计过滤、模型过滤标记为”可疑”的样本,确认过滤是否准确

4. 采样策略

4.1 随机采样(Random Sampling)

从数据集 中以相等的概率独立抽取 个样本构成 mini-batch。

在 i.i.d. 假设下,随机采样使得每个样本被选中的概率均为 ,经验风险是期望风险的无偏估计:

优点:实现简单;在大数据集 i.i.d. 场景下是标准做法。

缺点:在类别不平衡场景下,mini-batch 中 head classes 出现频率远高于 tail classes,tail classes 的梯度更新机会极少。

4.2 分层采样(Stratified Sampling)

分层采样保证每个 mini-batch 中各类别样本的比例与整体数据集一致:

  1. 将数据集按类别标签划分为 个子集
  2. 在每个子集 中独立随机抽取 个样本

这与真实数据分布 保持一致。

优点:解决了 head/tail 不平衡问题;每个 epoch 中 tail classes 有稳定的梯度更新机会。

缺点:在极端不平衡()时,分层采样仍无法保证 tail classes 有足够多的样本参与训练(每个 batch 中 tail class 的期望样本数为 ,若 ,则该类可能连续多个 batch 不出现)。

4.3 重采样(Resampling)

当 tail classes 样本过少时,可以对 tail classes 做过采样(oversampling),或对 head classes 做欠采样(undersampling),使各类别样本数均衡。

过采样(Oversampling)

对 tail classes 的样本重复采样,使每个类的样本数达到

问题:过采样会导致模型对 tail classes 过拟合——因为同一个样本被多次看到,模型记忆了这些样本而非学习到泛化特征。

改进:SMOTE(Synthetic Minority Over-sampling Technique):对 tail classes 的样本在特征空间做插值,生成合成样本,而非简单重复。

欠采样(Undersampling)

从 head classes 中随机抽取 个样本,丢弃其余。

问题:可能丢失 head classes 中有价值的样本;若 过小,还会导致模型欠拟合。

4.4 Class-Balanced Sampling(类别平衡采样)

Class-balanced sampling 的核心思想不是让 batch 内各类别比例均衡,而是让模型在每个 epoch 中对每个类别都有大致相等的梯度更新次数

具体做法:

  1. 计算每个类别的采样权重:(或 的归一化形式)
  2. 按照权重 采样类别 ,再在该类别内随机采样样本

这相当于将均匀采样转变为”类别级别”的加权采样,保证 tail classes 的梯度更新机会。

4.5 Hard Example Mining(困难样本挖掘)

Hard example mining 的核心思想是:模型最需要学习的不是”已经会的简单样本”,而是”当前还不会的困难样本”。

在线困难样本挖掘(OHEM,Online Hard Example Mining)

在每个 mini-batch 中,先让模型对所有候选样本做前向传播,计算 loss,然后将 loss 最大的 个样本()保留用于反向传播

为什么 OHEM 有效

模型在简单样本上的 loss 很小 → 梯度也小 → 对参数更新贡献有限。困难样本的 loss 大 → 梯度大 → 对参数更新贡献更多。OHEM 相当于在每个 batch 中优先处理困难样本,加速收敛。

但注意:OHEM 增加了训练的计算成本(需要先跑一遍前向传播算 loss);且如果困难样本中含有噪声标签,过度关注这些样本可能导致过拟合到噪声。


5. 非均匀采样与偏差问题

5.1 经验风险最小化在非均匀采样下的偏差

设从真实分布 中采样得到数据集 ,但采样分布 (非均匀采样)。经验风险定义为

其中 重要性权重(importance weight)。若直接最小化经验风险而不加权,则实际优化的目标是 而非 ,两者存在系统性偏差。

5.2 Importance Sampling / Reweighting 的基本思想

Importance sampling 的核心思想是:如果采样分布 与真实分布 不同,则需要在损失函数中引入权重来修正这种差异。

设样本 的重要性权重:

则加权经验风险为

(均匀采样)时 ,退化为标准 ERM。

问题:真实分布 通常未知,无法直接计算 。实践中用采样权重替代,如 class-balanced sampling 中的 ,或 Focal Loss 中的

5.3 为什么 class-balanced sampling 本质上是 importance reweighting

设类别 的样本数为 ,类别 的采样概率为 (随机采样),真实分布概率为 。若我们希望以类别频率 来优化,则重要性权重为

当各类的真实频率 接近 (即采样反映了真实分布)时,;当 远小于其真实频率时(如 tail class),,相当于对该类做了加权。


6. 数据增强为什么能提升泛化

6.1 数据增强的本质

数据增强(Data Augmentation)在不增加真实样本的情况下,通过对已有样本施加语义保留的变换,扩大有效训练集。具体来说,对于一个样本 ,增强变换 满足:

理想情况下, 同分布,则增强样本与真实样本分布一致,模型看到的是更丰富的采样。

6.2 为什么增强能提升泛化

理论视角:增强相当于在样本级引入了随机噪声,模型在训练时会学到对这些变换的不变性(invariance)。例如:

  • 图像水平翻转增强 → 模型学到的表示不受水平翻转影响(空间位置不变性)
  • 颜色抖动增强 → 模型不过度依赖特定颜色(颜色不相关性)
  • 随机掩码增强(BERT style)→ 模型学会从部分信息恢复完整语义(遮蔽不相关性)

这些不变性正是模型在新数据上泛化的基础——真实世界的测试数据也会经历各种变换干扰,模型若已学会忽略这些干扰,自然泛化更好。

经验观察:在 CIFAR-10 上,不使用数据增强的错误率约为 ;使用 CutOut、CutMix、AutoAugment 等增强后,错误率可降至 以下。


7. 数据集泄漏的避免

7.1 泄漏的定义与危害

数据集泄漏(data leakage)指训练数据中包含了本不应该被模型看到的信息,导致模型在训练和测试时性能指标虚高,但实际部署时性能骤降。

典型案例

案例 1:验证集信息泄漏到训练集

若训练集和验证集在构造时来自同一时间窗口,而测试集来自不同时间窗口(如时间序列预测),则模型学到的是时间相关性而非真实规律。

案例 2:特征中包含未来信息

某特征 的计算公式中包含了 时间点之后的信息(如 的值),模型在训练时会直接利用这个”作弊特征”,而测试时该信息不可用。

案例 3:归一化统计量泄漏

若归一化参数(均值、方差)在计算时包含了测试集的数据,则测试集的归一化实际上使用了”来自未来的信息”。正确做法是:归一化参数仅从训练集计算,再应用于验证集和测试集。

7.2 如何避免泄漏

检查项操作
数据分割是否按时间/来源正确分层确认训练集和测试集来自不同时间段/不同来源
特征构造是否有”未来信息”审查每个特征的公式,确认只使用了当前时刻可用的信息
归一化参数是否仅从训练集计算将数据分割后,先用训练集 fit 归一化参数,再 transform 验证/测试集
数据增强是否在 train 模式下进行推理时的数据增强应与训练时一致,不能在 transform 中使用 label 信息
pipeline 中是否有”用测试集选模型”的操作所有超参数选择应在验证集上进行,而非测试集

8. 去重与近重复检测的意义

8.1 为什么去重不只是”省数据”

如第 2.2 节所述,重复样本的危害不在于”数据量虚高”,而在于其对采样分布的扭曲。设想一个场景:

  • 数据集有 10000 个独特样本,其中某 100 个样本各被重复了 100 次
  • 总数据集大小看似 100000,实际独特样本只有 10000
  • 随机采样概率中,这 100 个重复样本的概率是其他样本的 100 倍
  • 模型在训练时过度拟合到这 100 个”被重复”的模式

去重后,模型需要学会区分真正不同的样本,泛化到新的测试数据时才更鲁棒。

8.2 近重复检测(Near-Duplicate Detection)

完全精确的重复(exact duplicate)只是问题的一小部分。更大、更难处理的问题是近重复(near-duplicate)——内容高度相似但不完全相同,如同一篇文章的稍作改写版本。

方法:MinHash + LSH

MinHash 是一种近似集合相似度算法,用于在大规模语料中高效找出 Jaccard 相似度 的文档对:

  1. 对每个文档计算 shingle(token n-gram)集合
  2. 对所有 shingle 计算 MinHash 签名
  3. 用 LSH(Locality Sensitive Hashing)对 MinHash 签名分区,使相似文档大概率落入同一桶
  4. 在桶内精确计算 Jaccard 相似度

参数选择:shingle 大小通常为 ;LSH 的 band 数和每 band 行数决定相似度阈值(经验上,b=50, r=5 对应相似度阈值约 0.9)。


9. 工程流程

9.1 数据管线设计

一个完整的数据管线分为四个模块:

原始数据 → 清洗模块 → 采样模块 → 训练模块

清洗模块(数据清洗管线的输出)

  • 输出:经过四阶段清洗后的干净数据集 + 清洗报告
  • 报告内容:各阶段过滤掉多少样本(占比),每类过滤的典型样例

采样模块(训练时的采样策略)

  • 输出:带采样权重的 mini-batch
  • 关键点:采样权重应与模型训练解耦——采样模块提供 batch,训练模块只负责前向/反向,不要在训练循环中混合采样逻辑

训练模块(与数据管线的交互)

  • 训练前:接收清洗后的数据集 + 采样配置
  • 训练中:从 dataloader 持续获取 batch
  • 训练后:输出训练日志 + 模型 checkpoint

9.2 如何检查标签分布、样本长度分布、异常值

标签分布检查

from collections import Counter
label_counts = Counter([sample['label'] for sample in dataset])
for label, count in sorted(label_counts.items(), key=lambda x: -x[1]):
    print(f"Label {label}: {count} ({count/len(dataset)*100:.2f}%)")
  • 检查各类的样本数差距是否在合理范围(
  • 检查是否有类只有极少量样本(如 个),这类样本无法支撑模型学习,标注为”长尾问题类”

样本长度分布检查

lengths = [len(sample['text'].split()) for sample in dataset]
import numpy as np
lengths_mean = np.mean(lengths)
lengths_std = np.std(lengths)
lengths_p50 = np.median(lengths)
lengths_p95 = np.percentile(lengths, 95)
lengths_p99 = np.percentile(lengths, 99)
# 可视化:histogram of lengths
  • 检查长度分布是否呈长尾(若 p99 远超 p95,说明有极端长样本)
  • 决定是否截断(truncation):若 p99 长度是 p95 的 10 倍,可将超过 p95 的样本截断或过滤

异常值检测

import pandas as pd
features = pd.DataFrame([sample['features'] for sample in dataset])
# 检查每列的统计量
print(features.describe())
# 找出异常值(超出 3 sigma 的样本)
for col in features.columns:
    mu, sigma = features[col].mean(), features[col].std()
    outliers = features[abs(features[col] - mu) > 3*sigma]
    if len(outliers) > 0:
        print(f"Column {col}: {len(outliers)} outliers")

9.3 训练前数据审计

在正式训练前,应完成以下审计步骤:

审计项目标工具
样本总量确认数据规模符合预期(如 len(dataset)
标签分布确认无极端不平衡(头尾比 Counter
长度分布确认无极端长样本(截断或过滤)np.percentile
去重检查确认无大量重复样本(重复率 hash / annoy
近重复检查确认无大量近重复文档(相似度 的对 MinHash + LSH
缺失值检查确认各字段无大量缺失(缺失率 pandas.isnull
脏数据检查确认无 HTML 标签、乱码、异常字符正则表达式过滤
训练/验证分割确认分割比例正确(通常 验证标签分布一致性
数据来源追溯确认训练/验证/测试数据来源不同metadata 检查

10. 数据上线前检查清单

训练开始前,必须确认以下所有项目已完成:

  • 标签分布审计:打印所有类别的样本数,检查头尾比是否在可接受范围
  • 去重完成:精确哈希去重完成,近重复检测(如有必要)完成,重复率
  • 脏数据过滤:HTML 标签、控制字符、乱码已被过滤;正则规则已覆盖已知脏数据类型
  • 长度截断/过滤:超长样本已截断或过滤;截断长度已确认(如 tokenizer max length = 512)
  • 缺失值处理:所有必要字段的缺失值已处理(过滤或填补);已记录填补策略
  • 数据集分割:训练/验证/测试分割已完成;分割比例已记录;分割时使用了相同的采样策略(分层分割)
  • 归一化参数:如使用归一化,参数(均值/方差/词频等)仅从训练集计算,不涉及验证/测试集
  • 数据来源验证:训练集和测试集来自不同的物理来源/时间窗口,无跨集污染
  • 数据审计报告:已完成完整审计报告,记录了过滤各阶段的样本数和过滤原因
  • 种子可复现:数据加载 pipeline 在相同种子下可复现相同的数据顺序

11. 常见数据问题与处理方式对照表

数据问题诊断方法处理方式
噪声标签(轻度 交叉验证置信度分析;人工抽检Label Smoothing;置信度过滤
噪声标签(中度 Confident LearningCo-teaching;数据重标注
重复样本MD5 哈希精确匹配直接去重
近重复文档MinHash + LSH(相似度阈值 0.8~0.95)去重或合并
脏数据(HTML/乱码/特殊字符)正则表达式匹配规则过滤
极端长尾分布类别样本数统计类别平衡采样;Focal Loss;过采样
缺失特征值pandas.isnull() 检查删除该特征;均值填补;标记为特殊值
分布外样本(Out-of-distribution)embedding 空间异常检测; perplexity 检测过滤该样本
时间序列数据中包含未来信息特征审计(检查特征定义)重新构造特征,移除未来信息
训练/测试集来源重叠metadata 追溯检查重新分割数据,确保来源不重叠
标注模糊性(多标签)人工抽检;标签共现分析使用多标签分类;将模糊标签标记为 unsure
不平衡数据集类别样本数统计类别平衡采样;class weight;Focal Loss
注入攻击内容(XSS/SQL injection)安全扫描(OWASP 规则)过滤或转义
非目标语言语言检测(langdetect)过滤目标语言外的样本
低质量文本(自动生成/模板化)语言模型困惑度;perplexity 检测阈值过滤;语言质量分类器