假设你是一位主厨,今晚要做一道红烧牛肉。后厨案板上堆着大小悬殊的食材:拳头大的土豆、指甲盖大的蒜瓣、咬不动的牛筋、长短不一的胡萝卜。你会直接把它们扔进锅里吗?不会。你会先切丁、拍蒜、给牛筋改刀——这个“备菜”环节,就是让一锅菜熟得均匀、入味彻底的关键。 机器学习模型就像一口锅,原始特征就像没处理的食材:有的数值动辄上千,有的只在 0 到 1 之间打转;有的分布歪歪扭扭像个长尾巴的怪兽;有的类别值根本分不出大小顺序。若不做“备菜”——也就是特征变换——模型要么学得慢,要么被个别极端值带偏,要么把“颜色标签”硬当成“数值大小”来比较。本文就用这套备菜功夫,带你学会 Min-Max 归一化、Z-Score 标准化、对数与 Box-Cox 变换、独热编码、分箱这五把“菜刀”,并告诉你在什么菜(模型)面前该用哪一把。

岗位关联

特征变换是特征工程里性价比最高的一课:它不增加新数据,却能显著加快模型收敛、提升精度与稳定性,是每个 AI 从业者必须练熟的基本刀工。

目录
  1. 可视化演示
  2. 为什么要特征变换
  3. Min-Max归一化
  4. Z-Score标准化
  5. 对数与Box-Cox变换
  6. 独热编码
  7. 分箱与离散化
  8. 实战选择策略
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示Min-Max归一化、Z-Score标准化、对数变换、分箱独热编码等特征变换方法的效果对比,点击切换不同变换。

本节配有交互动效(进入视口后自动加载,约 3KB)。

归一化与标准化对比 Min-Max:缩放到[0,1]区间保持分布形状 Z-Score:均值为0标准差为1适合离群值 x\'=(x-min)/(max-min) x\'\'=(x-μ)/σ 不同变换方法适配不同数据分布与模型需求

为什么要特征变换

备菜的第一步,是认清食材的“脾气”:土豆皮厚、蒜瓣个小、牛筋倔强。如果不加以处理就下锅,结果必然是——小蒜瓣烧成了炭,大土豆还夹生。机器学习特征也有同样的“脾气”。一个特征是 0.001 到 0.01 的小数,另一个特征是 1000 到 99999 的大数,两者一起参与距离计算时,大数特征会像一块巨石碾压蝼蚁,小特征完全失去话语权。

模型学习的本质是寻找规律,而许多算法(如 K 近邻、线性回归、神经网络)依赖特征之间的相对距离和梯度。当特征尺度悬殊时,梯度下降会在“陡坡”和“缓坡”之间反复震荡,收敛慢得像在泥地里骑车。当数据分布严重偏态(长尾)时,大部分样本挤在一小块区域,模型很难看清细节,个别离群点还会把决策边界拽得东倒西歪。

特征变换就是针对这三类“食材脾气”的备菜刀工:统一尺度、缓解偏态、削弱离群点。先看一个最直观的例子——欧氏距离:

回到厨房:高明的师傅不会让牛筋和蒜瓣在同一条标准线上较量,而是先各自处理妥当再入锅。特征变换的意义正是如此——它不改变数据本身的信息,只改变数据“摆在模型面前的样子”,让学习过程又快又稳。

d=(x1−y1)2+(x2−y2)2\displaystyle d = \sqrt{(x_1 - y_1)^2 + (x_2 - y_2)^2}
这个公式告诉你:如果某个特征的数值范围更大,它的平方项就会在距离里“喧宾夺主”。因此先让所有特征站在同一起跑线上,模型才能公平地看待每个特征。
  1. 两坐标相减先看两个样本在某个特征上的差值 $(x_1 - y_1)$、$(x_2 - y_2)$,差值越大说明在这个维度上离得越远。
    x1−y1,x2−y2x_1 - y_1, \quad x_2 - y_2
  2. 逐项平方对每个差值取平方 $(x_1-y_1)^2$,消除正负号,同时让大差值被进一步放大——这正是尺度大的特征喧宾夺主的原因。
    (x1−y1)2+(x2−y2)2(x_1 - y_1)^2 + (x_2 - y_2)^2
  3. 开根号最后对总和开平方 $\sqrt{\cdot}$,把平方的量纲还原,得到两个样本间的直线距离 $d$。
    d=(x1−y1)2+(x2−y2)2d = \sqrt{(x_1 - y_1)^2 + (x_2 - y_2)^2}

Min-Max归一化

备菜里最常用的一招是“切丁”:管你土豆是方的还是圆的,统一切成 1 厘米见方的小块。这样下锅后受热均匀、熟得同步。Min-Max 归一化就是特征世界里的“切丁机”,它把所有数值按比例压缩到 [0, 1] 区间,让每个特征都在同一把尺子下量长度。

它的做法非常朴素:先找出这个特征的最小值和最大值,然后把每个数值减去最小值、再除以“最大值减最小值”这个跨度。公式如下:

Min-Max 的优点是简单直观、保留原始分布的形状,特别适合取值范围有明确上下界的特征(比如像素值 0~255、考试分数 0~100),对稀疏数据也很友好——大量为 0 的值变换后仍然为 0。但它有个致命软肋:如果数据里混入一个巨大的离群值,最大值被瞬间拉高,其余正常数据会被“挤”到紧贴 0 的一小段区间里,就像一锅菜里混进一颗巨型土豆,其他食材被迫挤在锅边。此时该换一把刀了。

X′=X−Xmin⁡Xmax⁡−Xmin⁡\displaystyle X' = \frac{X - X_{\min}}{X_{\max} - X_{\min}}
一句话:分子把数据“搬”到从 0 开始的位置,分母把跨度“压”成 1,于是所有值都落在 [0, 1] 之间,顺序和相对距离保持不变。
  1. 减去最小值$X - X_{\min}$ 把整个分布向左平移,让最小值恰好落在 0 点。
    X−Xmin⁡X - X_{\min}
  2. 计算跨度$X_{\max} - X_{\min}$ 是数据的取值范围,也就是“切丁”前要量出的整根食材长度。
    Xmax⁡−Xmin⁡X_{\max} - X_{\min}
  3. 除法压缩用平移后的值除以跨度,把“绝对长度”换算成“占全长的比例”,于是所有数据被压缩进 [0, 1]。
    X′=X−Xmin⁡Xmax⁡−Xmin⁡X' = \frac{X - X_{\min}}{X_{\max} - X_{\min}}

Z-Score标准化

如果食材个头差异极大,且偶有“巨型土豆”捣乱,切丁反而坏事。有经验的师傅会改用“称重校准”:不再盯着单个食材的绝对大小,而是看它相对这堆食材的平均水平偏离了多少。Z-Score 标准化的思路正是如此——它用均值和标准差来重塑数据,变换后均值为 0、标准差为 1。

具体来说,先算出所有数据的平均值 $\mu$ 和标准差 $\sigma$,然后每个数值减去均值(相当于把数据中心化到 0),再除以标准差(相当于把数据的“离散幅度”规整为 1)。公式如下:

与 Min-Max 不同,Z-Score 不依赖最大值和最小值,因此受离群点影响更小,也更适合“不知道边界在哪里”的数据。它和切丁一样不改变分布的形态——只是改变了尺子上的刻度。需要留意的是,它要求数据近似对称时才更有意义;若分布严重偏态,单纯标准化后数据依然歪着,这时候就要请出下一把刀——拍蒜的刀。

X′=X−μσ\displaystyle X' = \frac{X - \mu}{\sigma}
通俗地说:Z-Score 不关心你有多大,只关心你“比平均大几个标准差”——这就是把绝对尺寸换算成了相对位置。
  1. 求解均值$\mu = \dfrac{1}{n}\sum_{i=1}^{n} X_i$,先算出这批数据的平均水平,作为校准的“基准秤砣”。
    μ=1n∑i=1nXi\mu = \frac{1}{n}\sum_{i=1}^{n} X_i
  2. 计算标准差$\sigma = \sqrt{\dfrac{1}{n}\sum_{i=1}^{n} (X_i - \mu)^2}$,衡量数据整体偏离均值的程度,作为“刻度单位”。
    σ=1n∑i=1n(Xi−μ)2\sigma = \sqrt{\frac{1}{n}\sum_{i=1}^{n} (X_i - \mu)^2}
  3. 中心化$X - \mu$ 让均值变成 0,数据围绕 0 上下波动。
    X−μX - \mu
  4. 标准化$(X - \mu) / \sigma$ 把波动幅度压缩成以 1 为单位,变换后约 68% 的数据落在 [-1, 1] 之间。
    X′=X−μσX' = \frac{X - \mu}{\sigma}

对数与Box-Cox变换

有些食材天生“倔强”:牛筋越煮越韧,大蒜拍一下才出味。数据里也有这样的顽固分子——长尾偏态分布。比如用户收入、网页访问量、城市人口,绝大多数样本挤在低值区,少数样本拖着一条长长的尾巴。这时无论切丁还是称重都无济于事,因为问题不在尺度,而在形状。正确的做法是“拍蒜”——用非线性变换把长尾压平。

最常用的拍蒜手法是对数变换:对每个正数取自然对数,原本 1、10、100、1000 这种成倍拉开的差距,变换后变成 0、2.3、4.6、6.9 这样均匀的台阶,长尾被大幅压缩:

对数变换虽好,但“拍多少下”全凭经验。于是有了更智能的 Box-Cox 变换——它引入一个参数 $\lambda$,自动搜索最合适的变换强度,当 $\lambda=0$ 时自动退化为对数变换:

经过 Box-Cox 处理后的数据往往更接近正态分布,后续无论是线性回归还是距离类模型,都能学得更轻松。但要记住:Box-Cox 同样要求数据为正数;如果数据含负数,需要先平移(加上一个常数)再变换,相当于先给食材“化冻”再拍。拍完蒜,该考虑怎么摆盘了。

X′=ln⁡(X),X>0\displaystyle X' = \ln(X), \quad X > 0
Box-Cox 是“智能拍蒜机”,它不固定拍几下,而是通过极大似然估计找到最让数据接近正态的那个力度 $\lambda$。
  1. 参数分支当 $\lambda \neq 0$ 时使用公式 $\dfrac{X^\lambda - 1}{\lambda}$;当 $\lambda = 0$ 时退化为 $\ln(X)$,两者无缝衔接。
    λ≠0vsλ=0\lambda \neq 0 \quad \text{vs} \quad \lambda = 0
  2. 幂次变换$X^\lambda$ 对数据做幂运算,$\lambda = 0.5$ 相当于开方,$\lambda = 2$ 相当于平方,改变分布的形状。
    XλX^\lambda
  3. 减一除λ$\dfrac{X^\lambda - 1}{\lambda}$ 这一步是为了让函数在 $\lambda$ 附近连续光滑,便于计算机自动搜索最优参数。
    Xλ−1λ\frac{X^\lambda - 1}{\lambda}

独热编码

备菜时最忌讳串味:辣椒不能和香菜混在一个碗里,每种配料要单独装盘、贴上标签。类别特征也有类似的讲究。颜色有“红”、“绿”、“蓝”,城市有“北京”、“上海”、“广州”,如果粗暴地编码成 0、1、2,模型就会误以为“蓝”是“红”的三倍——这纯粹是虚假的顺序,就像把辣椒、香菜、葱花按 1、2、3 编号,然后宣称香菜比辣椒大两号。

独热编码(One-Hot Encoding)解决的就是这个“假顺序”问题。它的做法是:先列出这个类别特征的所有可能取值,每个取值单独占一列,样本属于哪一类,就在那一列写 1,其余列写 0。公式表达如下:

独热编码的代价是维度爆炸:如果某个类别特征有 1000 个取值,就会新增 1000 列,其中绝大多数是 0,矩阵变得极度稀疏。这就像为 1000 种食材各备一个碗,厨房根本摆不下。因此,在工程实践中,对高基数类别特征(比如上万的用户 ID)要谨慎使用独热编码,通常需要先做频率筛选、哈希压缩,或换用更紧凑的编码方案。摆好盘之后,还有最后一道工序——按大小分级装篮。

OneHot(x)j={1,x=cj0,x≠cj,j=1,2,…,k\displaystyle \mathrm{OneHot}(x)_j = \begin{cases} 1, & x = c_j \\ 0, & x \neq c_j \end{cases}, \quad j = 1, 2, \dots, k
相当于给每个类别单独准备一个小碗:是这道菜,就在对应碗里放一颗黄豆,其它碗空着。类别之间从此互不干扰,没有大小之分。
  1. 枚举类别类别集合为 $\{c_1, c_2, \dots, c_k\}$,共 $k$ 个不同取值,对应 $k$ 个新列。
    c1,c2,…,ckc_1, c_2, \dots, c_k
  2. 命中置一当样本的类别 $x$ 恰好等于第 $j$ 个类别 $c_j$ 时,第 $j$ 位取 1。
    x=cj⇒1x = c_j \Rightarrow 1
  3. 未中置零其余不相等的列都取 0,于是每个样本得到一个“只有一个 1 的 0-1 向量”。
    x≠cj⇒0x \neq c_j \Rightarrow 0

分箱与离散化

买回一筐苹果,个头参差不齐。聪明的做法不是每个苹果单独定价,而是分成大、中、小三篮,按级售卖。分箱(Binning)就是这个思路:把连续型特征切成若干个区间,每个区间当作一个离散等级。这样做的好处是,模型不再纠结于“差 0.1 就是不同”,抗噪能力更强,还能捕捉非线性关系。

最常见的两种分法是等宽分箱和等频分箱。等宽分箱按数值范围均匀切割,公式如下:

等宽分箱实现简单,但遇到长尾偏态数据时,大部分样本会挤进头几个箱子,后面的箱子几乎为空——就像把一堆葡萄和几个西瓜按个头平分,西瓜独占了大半箱。这时应改用等频分箱:按分位数(如十分位、五分位)切分,保证每箱样本量接近,缺点是箱子的边界不再是整齐的数值。此外还有业务意义分箱,比如年龄按“未成年 / 青年 / 中年 / 老年”划分,完全基于业务常识,可解释性最强。食材分级完毕,最后就看大厨怎么根据菜谱下刀了。

bi=⌊xi−xmin⁡w⌋,w=xmax⁡−xmin⁡k\displaystyle b_i = \left\lfloor \frac{x_i - x_{\min}}{w} \right\rfloor, \quad w = \frac{x_{\max} - x_{\min}}{k}
等宽分箱就像拿一把长尺把苹果按个头平均分成 $k$ 段;等频分箱则是先数人头,让每个箱子里的苹果数量一样多。
  1. 计算箱宽$w = \dfrac{x_{\max} - x_{\min}}{k}$,把整个取值范围除以箱子个数 $k$,得到每个箱子的宽度。
    w=xmax⁡−xmin⁡kw = \frac{x_{\max} - x_{\min}}{k}
  2. 计算偏移$x_i - x_{\min}$ 算出当前值距离最小值的距离,确定它落在第几个宽度区间。
    xi−xmin⁡x_i - x_{\min}
  3. 向下取整$\left\lfloor \cdot \right\rfloor$ 把商向下取整,得到箱号 $b_i$(0 到 $k-1$ 的整数)。
    bi=⌊xi−xmin⁡w⌋b_i = \left\lfloor \frac{x_i - x_{\min}}{w} \right\rfloor

实战选择策略

同样是土豆,做沙拉要切块、做汤要切丝、炖肉要切大块——好厨子永远看菜下刀。特征变换的选择同样要“看成菜(模型)下刀(变换)”,没有放之四海皆准的银弹。

距离类模型优先缩放。K 近邻、SVM、线性回归、神经网络这类模型依赖特征间的距离或梯度,必须做 Min-Max 或 Z-Score。否则量纲大的特征会直接主导距离计算,模型等于“睁眼瞎”。其中,数据分布近似均匀、边界明确时选 Min-Max;分布未知或偶有离群点时,Z-Score 更稳。

树模型可以跳过缩放。决策树、随机森林、梯度提升树(XGBoost、LightGBM)在分裂时只关心特征的相对排序,对每个特征做单调变换(无论是归一化还是标准化)都不会改变分裂点,因此缩放对它们几乎无意义。但分箱、独热编码等离散化操作对树模型依然有用——它们能帮树模型更好地捕捉非线性,也能将缺失值作为一个独立分箱处理。

偏态特征先做对数。无论用什么模型,遇到收入、点击量这类长尾数据,都建议先用对数或 Box-Cox 变换压平尾巴。这一步往往比缩放带来的收益更大,因为形状问题比尺度问题更伤模型。最后记住一个经验法则:先把数据画出来看一眼分布,再决定上哪把刀;如果时间只够做一件事,请先处理尺度差异最大的特征。

回到厨房,整套备菜流程浑然一体:认清食材脾气(为什么要变换)→ 切丁(Min-Max)→ 称重校准(Z-Score)→ 拍蒜压泥(对数/Box-Cox)→ 分类装盘(独热编码)→ 分级装篮(分箱)→ 看菜下刀(实战选择)。刀工不在多,而在用得准。

AI 应用场景

电商推荐系统的用户行为特征归一化

阶段:特征工程

解决的问题:原始特征中,“浏览时长”以秒计(几百到几万),“收藏次数”只有 0 到 5,“购买金额”跨几个数量级。若不处理,协同过滤和 K 近邻计算用户相似度时,“浏览时长”会完全碾压“收藏次数”,推荐结果失真。归一化后各特征平等参与相似度计算,推荐准确率显著提升。

具体案例:某电商平台对 10 万用户的“周浏览时长、加购次数、下单金额”做 Z-Score 标准化后构建用户向量,再计算余弦相似度做“看了又看”推荐。上线后推荐点击率提升 12%,且数值稳定性更好,不再被个别刷单大额用户带偏。

金融信用评分卡中的对数与分箱

阶段:特征工程与建模

解决的问题:收入、负债等特征长尾严重,直接喂给逻辑回归,系数会被极端值扭曲;而监管要求模型可解释。通过对数变换压平偏态,再对收入做等频分箱(如分 5 箱),每个箱子赋予一个 WOE 编码,模型既稳定又可解释,还天然规避了离群点的影响。

具体案例:某消费金融公司在构建 A 卡(申请评分卡)时,对“月收入、授信额度使用率、近 6 个月查询次数”分别做 Box-Cox 变换与分箱处理,逻辑回归模型的 KS 值从 0.31 提升到 0.39,且分箱后的特征让风控审核人员能直接解读“月收入在 3 万以上箱体违约率最低”。

广告点击率预估中的类别特征独热编码

阶段:特征工程与训练数据准备

解决的问题:“操作系统”(iOS/Android/Windows)、“广告位类型”(开屏/信息流/插屏)等类别特征无大小顺序,直接编码成整数会引入虚假的次序关系。独热编码将每个类别展开为独立维度,配合逻辑回归或浅层神经网络,让模型学到“开屏广告 + iOS 用户”这类组合信号。

具体案例:某广告平台对“设备型号、网络类型、广告位”三个低基数类别特征做独热编码后,训练逻辑回归 CTR 模型,AUC 从 0.62 提升到 0.68。同时通过哈希技巧把高基数的“用户城市”特征压缩到 2^18 维,兼顾了精度与内存开销。

Python 演示

python58 行
"""特征变换实战演示:纯 Python 实现常用变换方法"""import mathimport random  def minmax(vals):    lo, hi = min(vals), max(vals)    return [(v - lo) / (hi - lo) for v in vals]  def zscore(vals):    mean = sum(vals) / len(vals)    sd = math.sqrt(sum((v - mean) ** 2 for v in vals) / len(vals))    return [(v - mean) / sd for v in vals]  def log_transform(vals):    return [math.log(v) for v in vals]  def onehot(col):    uniq = list(dict.fromkeys(col))    return [[1 if v == u else 0 for u in uniq] for v in col]  def binning(vals, k=4, mode="width"):    lo, hi = min(vals), max(vals)    n = len(vals)    if mode == "width":        edges = [lo + (hi - lo) * i / k for i in range(k + 1)]    else:        sorted_vals = sorted(vals)        edges = [sorted_vals[min(n - 1, n * i // k)] for i in range(k + 1)]    bins = []    for v in vals:        b = 0        while b < k - 1 and v >= edges[b + 1]:            b += 1        bins.append(b)    return bins, edges  def main():    random.seed(42)    raw = [math.exp(1.8 * (random.random() + random.random() - 1)) for _ in range(20)]    print("原始值:", [round(v, 2) for v in raw])    print("Min-Max:", [round(v, 3) for v in minmax(raw)])    print("Z-Score:", [round(v, 3) for v in zscore(raw)])    print("对数变换:", [round(v, 3) for v in log_transform(raw)])    colors = ["red", "blue", "green", "red", "blue"]    for row in onehot(colors):        print("独热编码:", row)    bins, edges = binning(raw, k=4, mode="width")    print("等宽分箱:", [round(e, 2) for e in edges], "->", bins)  if __name__ == "__main__":    main()
目的:用纯 Python 复现正文中的五大特征变换方法,跑一遍就能直观看到同一组偏态数据在每种变换下的数值变化。
  1. lo, hi = min(vals), max(vals)取最小值和最大值作为压缩的上下界,这是 Min-Max 的核心原料。
  2. (v - lo) / (hi - lo)分子把数值平移到 0 起点,分母把跨度压缩成 1,一举两得。
  3. mean = sum(vals) / len(vals)先求均值,为 Z-Score 准备“基准秤砣”。
  4. sd = math.sqrt(sum((v - mean) ** 2 for v in vals) / len(vals))标准差衡量整体偏离程度,作为新刻度单位。
  5. return [math.log(v) for v in vals]对每个正数取自然对数,摊平长尾偏态。
  6. uniq = list(dict.fromkeys(col))按出现顺序去重,得到类别清单,保证独热编码列顺序稳定。
  7. [1 if v == u else 0 for u in uniq]每个类别一列,命中写 1、其余写 0,生成 0-1 向量。
  8. edges = [lo + (hi - lo) * i / k for i in range(k + 1)]等宽分箱的边界:把值域均匀切成 k 段。
  9. sorted_vals[min(n - 1, n * i // k)]等频分箱直接取分位数处的值作为边界,保证每箱样本数相近。
  10. while b < k - 1 and v >= edges[b + 1]: b += 1从左往右扫描边界,找到当前值落入的箱号。

常见误区

误区“Min-Max 和 Z-Score 都是把数据缩一缩,效果差不多,随便用一个就行。”

正解两者公式完全不同,性质也不同。Min-Max 依赖最大值和最小值,受离群点影响大,变换后区间固定为 [0,1];Z-Score 依赖均值和标准差,对离群点稳健,变换后均值为 0 标准差为 1。好比“切丁”关注绝对大小,而“称重校准”关注相对平均值偏离几个标准差。数据分布均匀、边界明确时用 Min-Max;分布未知、有离群点时用 Z-Score。

为何常见:两者看起来都是“把一个数换成另一个数”,初学者容易只记“缩放”这个动作,而忽略了它们对离群点的敏感度差异。

误区“标准化之后,数据就是正态分布了,可以直接做要求正态的统计检验。”

正解Min-Max 和 Z-Score 都是线性变换,只改变刻度和位置,完全不改变分布形态——偏态数据标准化后依然是偏态。只有对数、Box-Cox、平方根这类非线性变换才能改变形状,把长尾压向对称。就像把一根歪脖子黄瓜切成片,切片不会让它变直;只有“拍蒜”式的非线性处理才能改变形态。

为何常见:Z-Score 的公式里出现“均值、标准差”,让人误以为它和正态分布强相关,其实它只是借用了这两个统计量做刻度换算。

误区“不管用什么模型,先标准化总没错,特征工程必须有这一步。”

正解树模型(决策树、随机森林、梯度提升树)在分裂时只看特征值的相对顺序,对单调变换完全不敏感,做不做缩放结果一样。距离类模型(KNN、SVM、线性、神经网络)才必须做。好比炖牛肉时切大块还是小块都有讲究,但如果你做的是“整只烤鸡”,根本不涉及切丁的问题。

为何常见:网上教程大多以线性模型和神经网络举例,导致“标准化是万能前处理”的印象被过度泛化到所有模型。

误区“特征里有负数也没关系,取个对数就完事了。”

正解$\ln(X)$ 在 $X \le 0$ 时无定义或趋向负无穷,直接对含负数的数据取对数会报错或产生无穷值。正确做法是先平移:给所有值加上一个足够大的常数使最小值大于 0,再取对数;或者用 Box-Cox 的变体(如 Yeo-Johnson 变换)直接处理正负混合数据。就好比食材冻住了不能直接拍,得先化冻再下刀。

为何常见:很多人只记住了“对数能治长尾”,却忽略了数学上对数函数的定义域限制。

误区“独热编码把每个类别都展开,信息保留最完整,所以类别再多也值得做。”

正解当类别基数很高(如用户 ID、IP 地址有上万个取值)时,独热编码会产生极其稀疏的高维矩阵,维度灾难会导致内存爆炸、训练极慢,还可能因“一列只有一个 1”而毫无统计意义。工程上通常先做频率筛选(只保留出现次数多的类别)、哈希压缩,或改用目标编码、嵌入(Embedding)等紧凑表示。就像 1000 种食材各备一个碗,厨房早堆不下了,得按“常用调料、稀有食材”分类管理。

为何常见:教科书多用三五个类别的简单例子,让人误以为独热编码的维度成本可以忽略不计,忽略了真实业务里类别基数的爆炸性。

面试题

Q1. Min-Max 归一化把数据映射到什么区间?

单选题 · easy

  • A.[-1, 1] 区间内
  • B.[0, 1] 区间内← 正确答案
  • C.均值为 0 方差为 1
  • D.[0, 100] 区间内

答案:B。Min-Max 的公式为 $(X - X_{\min}) / (X_{\max} - X_{\min})$,分子把最小值平移到 0,分母把跨度压缩成 1,因此所有值都落在 [0, 1]。“均值为 0 方差为 1”是 Z-Score 的特点,属于混淆项。

Q2. Z-Score 标准化后数据的均值和标准差分别是?

单选题 · easy

  • A.均值为 0 且标准差为 1← 正确答案
  • B.均值为 1 且标准差为 0
  • C.保持原均值且标准差为 1
  • D.均值为 0 且保持原标准差

答案:A。Z-Score 先减去均值($\mu$)实现中心化,使新均值变为 0;再除以标准差($\sigma$)使新标准差变为 1。这就像“称重校准”:把整堆食材的中心移到 0,波动幅度归一为 1。

Q3. 以下哪种变换最适合处理长尾偏态且全为正数的数据?

单选题 · mid

  • A.Min-Max 归一化压缩尺度
  • B.Z-Score 标准化去中心化
  • C.对数或 Box-Cox 变换← 正确答案
  • D.独热编码生成零一向量

答案:C。Min-Max 和 Z-Score 是线性变换,只改变刻度不改变分布形状,长尾依然存在。对数或 Box-Cox 是非线性变换,能压缩右尾、使数据接近对称分布。独热编码针对的是类别特征,与偏态无关。

Q4. 关于 Min-Max 归一化的说法正确的有?

多选题 · mid

  • A.受离群点影响比较大← 正确答案
  • B.把数据压缩到 0 到 1← 正确答案
  • C.能改变数据的分布形态
  • D.对负数数据也可以直接使用← 正确答案

答案:ABD。Min-Max 依赖最大值和最小值,离群点会把正常数据挤压到 0 附近,故 A 正确;公式决定了输出区间为 [0,1],B 正确;它只做平移和缩放,是线性变换,不改变分布形态,C 错误;减最小值、除以跨度对负数同样成立,D 正确。

Q5. Box-Cox 变换相比直接对数变换的优势是什么?

单选题 · mid

  • A.自动搜索最优的变换参数 λ← 正确答案
  • B.输入数据不需要全部为正数
  • C.变换计算速度会更快一些
  • D.只能用于类别型特征数据

答案:A。Box-Cox 通过极大似然估计自动寻找最佳 λ,λ=0 时退化为对数变换,因此对数只是它的特例。Box-Cox 同样要求数据为正数,B 错误;它比一次对数计算更复杂,C 错误;它用于数值特征而非类别特征,D 错误。

Q6. 对“红、绿、蓝”做独热编码主要解决的问题是?

单选题 · mid

  • A.特征之间的尺度差异太大
  • B.类别被误当作有序的数字← 正确答案
  • C.数据分布出现严重偏态
  • D.特征数量实在太多

答案:B。若把类别编码成 0、1、2,模型会误以为“蓝”是“红”的两倍,引入虚假的次序关系。独热编码让每个类别独立占一列,彻底抹掉顺序假设。尺度、偏态、维度问题都不是独热编码的直接目的。

Q7. 高基数类别特征做独热编码后的主要问题是?

单选题 · hard

  • A.特征维度过高且矩阵极稀疏← 正确答案
  • B.所有类别值都会变成零一
  • C.缺失值将无法再被处理
  • D.模型一定会严重过拟合

答案:A。类别基数高意味着新列数等于类别数,比如一万个城市就新增一万列,绝大多数格子是 0,矩阵稀疏、内存暴涨、训练变慢。“会过拟合”不是必然结果,B、C 描述的是独热编码的正常行为或无关问题,A 才是真正痛点,工程上常用哈希压缩或嵌入处理。

Q8. 关于等宽分箱与等频分箱的区别,正确的有?

多选题 · mid

  • A.等宽按数值区间均匀切分← 正确答案
  • B.等频按样本数量均匀切分← 正确答案
  • C.等宽对长尾分布易出现空箱← 正确答案
  • D.两种分箱结果总是一致

答案:ABC。等宽分箱把值域均分,等频分箱按分位数保证每箱样本数相近,故 A、B 正确。长尾数据下等宽分箱会让大部分样本挤在前几箱、后面出现空箱,C 正确。两者的切分逻辑完全不同,结果通常不一致,D 错误。

Q9. 以下哪种模型通常可以跳过特征变换直接训练?

单选题 · hard

  • A.线性回归与逻辑回归
  • B.K 近邻与支撑向量机
  • C.决策树与随机森林← 正确答案
  • D.带 L2 惩罚的岭回归

答案:C。树模型在分裂时只看特征值的相对大小关系,对归一化、标准化这类单调变换不敏感,因此可以跳过缩放。线性回归、KNN、SVM 都依赖特征尺度,必须做变换。这就像炖整鸡不需要切丁,但做沙拉必须切。

Q10. 关于 Z-Score 标准化与 Min-Max 归一化的对比,正确的有?

多选题 · hard

  • A.Z-Score 用均值和标准差缩放← 正确答案
  • B.Min-Max 用最大值和最小值缩放← 正确答案
  • C.Z-Score 对离群点相对更稳健← 正确答案
  • D.两者都会改变数据的分布形态

答案:ABC。Z-Score 依赖均值 $\mu$ 和标准差 $\sigma$,Min-Max 依赖 $\min$ 和 $\max$,A、B 正确。Min-Max 的上下界会被离群点轻易拉远,而均值和标准差受单点扰动较小,C 正确。两者都是线性变换,只改变刻度和位置,不改变分布形态,D 错误。