跳转至

P4-7.3 补充学习:区分预处理中的输入问题

Section ID: P4-7.3 Version: v2026.07.23

副标题: 缺失值、尺度与编码分别从什么输入问题出发?

在 P4-7.2 里,我们先抓住了 preprocessing 的大意: 把原始输入改造成 model 能计算的表达。但第一次学预处理时,很快就会出现一种混乱感。有的列是空的,有的列数值大小差别很大,有的列是字符串,于是就很难直觉地理解,为什么这三件事会被放在同一个“预处理”下面来讲。

这个补充学习的目的,不是继续增加更多预处理技术名称,而是先建立一个判断基准: 当前输入里到底出了什么问题,然后再按这个问题去区分该想到哪种预处理。

本补充学习的范围

这一节回答下面这些问题。

  • 缺失值处理、尺度调整、编码分别是在回应什么输入问题?
  • 看一列数据时,应该先检查什么?
  • 一列数据只需要一种预处理规则,还是可能要连续套上多种规则?
  • 就算已经把预处理种类分开了,为什么还是要重复使用 train 上学到的规则?

这一节先收束 缺失值处理、尺度调整、编码分别对应什么输入问题。filter、wrapper、embedded、降维的区分,会在下一节 P4-7.4 继续展开。

用补充学习: 缺失值、尺度、编码分别对应什么输入问题恢复的概念连接

  • 能把预处理种类区分成 输入问题的种类,而不是 技术名称
  • 看一列时,能先检查 是不是空的数值轴是不是在晃是不是不可计算的表达
  • 能解释同一列也可能像缺失值处理和编码那样,需要多条规则连续接上。
  • 能重新接回一点: 就算分清了预处理种类,规则学习也仍然只能发生在 train 上。

先抓大图景

预处理种类通常不是按列名来分,而是按 现在到底是什么在阻碍计算 来分。

输入里最先看到的问题 最先想到的预处理 核心问题
值是空的 缺失值处理(imputation) 这个空白要用什么规则处理
数值大小轴差太大 尺度调整(scaling) 这些数字要怎样公平比较
混有字符串、类别、等级 编码(encoding) 这个值要怎样改造成可计算表达

核心点是,预处理种类 的分法,不是看列的外表,而是看 到底是什么原因挡住了计算

例如,age 是数值列,但只要里面有空值,它也需要缺失值处理。membership_tier 是类别列,所以可能需要编码;如果里面也有空值,那么缺失值处理还会先一步接上去。也就是说,如果认为一列只能贴上一种预处理规则,很快就会卡住。

看一列数据时先问什么

第一次拆分预处理时,最稳妥的方式通常是按下面的顺序看一列并发问。

  1. 这个值是不是空的?
  2. 这个值能不能直接按数字计算?
  3. 如果它是数字,和其他列相比时,数值大小轴是不是差得过大?
  4. 这个值是有顺序的类别,还是没有顺序的类别?

如果把这个顺序套到客户表示例里,会变成下面这样。

最先看到的问题 最先接上的判断
age 有些值是空的 先看是否需要缺失值处理
monthly_spend 数值范围很大 先看是否需要尺度调整
city 它是字符串类别 需要编码
membership_tier 它是类别,而且可能带有顺序意义 先看编码方式是否要保留顺序意义

这张表的目的,不是让读者背下唯一正确的预处理答案,而是让读者抓到一种感觉: 每一列首先要问的问题都不一样

这里还值得再抓住一点。即使都是 数值列,它们也未必属于同一种处理对象。

看起来像数字的列 立刻要抓的问题 预处理判断示例
monthly_spend=3200, 6100 和其他数值列相比,大小轴差是不是很大 检查尺度调整
age=29, 35 有没有空值,单位差是不是过大 先看缺失值处理,尺度要按情况判断
zip_code=06236 这个值表示的是大小,还是类别标识符 即使看起来是数字,也可能是类别/标识符,所以要评估编码或排除

也就是说,预处理不是只看数据类型名来决定,而是要把 这个数字到底表达什么意义 一起读进去。

类别值也是同样的道理。如果一看到 字符串 就想成“全都用同一种编码”,很快就会混乱。

类别示例 最先要抓的问题 更自然的判断
city = Seoul, Busan, Incheon 它们之间有大小顺序吗 通常把它看成无顺序类别并编码
membership_tier = bronze, silver, gold 阶段顺序要不要保留 先评估是否要保留顺序意义
status = pending, approved, rejected 这里的差别是顺序,还是状态区分 先读业务含义,再评估编码方式

也就是说,编码判断也不能停在 它是字符串,而是还要再往下一层看: 这个类别只需要区分,还是连顺序也重要

同一列也可能会连续接上多条规则

第一次接触预处理时,很容易把它想成 这列是编码对象那列是缩放对象 这种一列只对应一种处理。实际并不是这样。

例如,如果 membership_tier 既是字符串类别,又有部分空值,那么应该这样读。

  1. 先决定空值怎么处理。
  2. 然后再决定类别表达要怎么编码。

数值列也一样。

  1. 如果有空值,先决定要不要做缺失值处理。
  2. 如果数值轴差异很大,再去评估尺度调整。

也就是说,预处理种类不是 互斥菜单,而是 可以按顺序接到同一行输入上的规则集合

flowchart TD
  A["某一列"]
  B["它有缺失吗?"]
  C["它能作为数值计算吗?"]
  D["它的尺度差异是否过大?"]
  E["填补规则"]
  F["编码规则"]
  G["缩放规则"]
  H["在 验证 / 测试 上复用同样学到的规则"]

  A --> B
  B -->|是| E --> C
  B -->|否| C
  C -->|否| F --> H
  C -->|是| D
  D -->|是| G --> H
  D -->|否| H

这个流程展示的是: 预处理种类该怎么分 这个问题,归根到底就是 输入问题应该按什么顺序诊断 这个问题。

预处理种类选错时会出现什么误解

预处理区分之所以容易混乱,是因为就算把问题读错了,表面上也还是可能看起来像“已经处理过了”。

错误读法 实际问题 为什么危险
既然是字符串列,随便给个数字就行 这是把类别意义表达错了的编码问题 model 可能会读出并不存在的顺序
既然是数值列,只要调好尺度就行 实际上还残留着缺失值问题 计算仍可能中断或发生扭曲
值是空的,就先用平均值补掉 实际上空值本身可能就是重要信号 缺失的意义可能被直接抹掉

这张表说明的核心很简单。预处理中真正重要的,不是 已经处理过了,而是 你判断自己到底处理了什么问题

不要先看 model,先看输入问题

读预处理说明时,常常很快就会看到 这个 model 对尺度敏感那个 model 没那么敏感 之类的话。这些信息当然重要,但对初学者来说,它不该是第一个问题。

更应该先看的,是 输入问题到底是什么

  • 有空值,就先看缺失值处理。
  • 有字符串类别,就先看编码。
  • 数值轴差很大,就评估尺度调整。

然后再加上 哪些 model 对这个问题更敏感,这种顺序会更稳。比如基于距离(distance)的 model 或基于梯度的优化,可能会更直接地受到尺度影响,但在那之前,首先得知道 问题本身是不是数值尺度差异

也就是说,预处理的第一顺序不是 model 名称 -> 技术选择,而是 输入问题 -> 预处理种类 -> 检查 model 敏感度

为什么“复用 train 上学到的规则”在这里也同样重要

即使把预处理种类分得很清楚,只要规则学习的位置错了,问题还是会重新出现。

例如:

  • 如果缺失值的中位数不是只在 train 上算,而是把 test 也混进去,评价就会泄漏。
  • 如果编码类别列表是先用全体数据建出来的,那就等于提前看到了真实部署场景里本不该提前知道的信息。
  • 如果尺度基准用的是全体数据的平均值和方差,比较就不再公平。

因此,区分预处理种类的判断,和规则是在哪里学出来的,这两件事要分开记。

问题 应该在哪一层回答
需要什么预处理种类 在当前这节里,靠读取输入问题来回答
这个规则应该在哪里学 在 P4-7.2 的“按 train 学规则并复用”原则里回答

这样分开之后,读者就不容易把 需要什么规则这个规则是从哪里学出来的 混在一起。

案例及示例

示例 1. 即使是同一张客户表,各列最先接上的预处理问题也不同

再看一次这张简单的客户表。

age monthly_spend city membership_tier
29 3200 Seoul gold
6100 Busan silver
35 Incheon

看这张表时,预处理判断通常会这样分开。

输入问题 最先想到的规则
age 有空值 缺失值处理
monthly_spend 有空值,而且数值范围可能很大 先缺失值处理,再评估尺度
city 它是字符串类别 编码
membership_tier 它有空值、是类别,而且还要评估顺序意义 先缺失值处理,再评估编码方式

这里重要的,不是 记住 4 个预处理技术,而是即使看的是同一张表,不同列最先接上的问题也会不一样。

检查清单

  • 你是否不是按列名,而是按 输入问题的种类 来区分预处理种类?
  • 你现在看到的这列,最先出问题的是 空值数值轴 还是 不可计算表达
  • 你是否理解同一列也可能像缺失值处理和编码那样,顺次接上多条规则?
  • 你能不能把预处理的第一顺序解释成 输入问题 -> 预处理种类 -> 检查 model 敏感度
  • 你是不是把“一列只会接上一种预处理”这件事过度简化了?
  • 你有没有把 需要什么规则这个规则是从哪里学出来的 分开?
  • 你有没有忽略预处理规则仍然只能在 train 上学习这一点?

出处与参考资料