返回首页

Roadmap
更新于 2026年10月21日 全文 2373 字未阅读

数值型数据:分箱#

在机器学习中,把连续的数值切成几段「桶(bucket)」再交给模型,往往比直接喂原始数值更利于建模。这一做法就叫作 分箱(binning),也常被叫作 分桶(bucketing)——它是特征工程里很常用的一招。

MLWM: 例如在机器学习第8.3.5节 特征划分中介绍决策树是如何处理连续型特怎变量时,我们就用到了类似的分箱策略。

直观地讲,分箱是把特征的不同数值子区间映射到一个个桶(bin)里,因此,在很多场景下分箱直接就把数值数据变成了类别型数据。

我们来看下面这个例子:

假设有一个名为 X 的特征,最小值是 15,最大值是 425。可以用分箱把 X 切成下面 5 个桶:

  • 桶 1:15 到 34

  • 桶 2:35 到 117

  • 桶 3:118 到 279

  • 桶 4:280 到 392

  • 桶 5:393 到 425

桶 1 覆盖 15 到 34 这段,所以 X 在区间内的所有取值——17、29 这些——都会落进同一个桶。一个在这些桶上训练的模型,对 17 与 29 完全一视同仁,不会因为它们的具体数值有差异就给出不同的反应。

那这 5 个桶是如何进入特征向量的呢?这里就要用到一个标准的「独热(one-hot)」表示:

桶编号范围特征向量
115-34[1.0, 0.0, 0.0, 0.0, 0.0]
235-117[0.0, 1.0, 0.0, 0.0, 0.0]
3118-279[0.0, 0.0, 1.0, 0.0, 0.0]
4280-392[0.0, 0.0, 0.0, 1.0, 0.0]
5393-425[0.0, 0.0, 0.0, 0.0, 1.0]

你会发现:哪怕 X 在数据集中只占一列,在经过分箱之后,模型实际看到的却是 5 个独立特征——每个桶有自己的权重。这种「一列变多列」的切分,是分箱最关键的一点。


什么时候该用分箱#

并不是所有的特征都适合分箱,因此它是一把双刃剑。如果分箱用对了,它能显著提升模型效果;如果用错了,反而会把细节「磨平」,让模型学不到有用的模式。

当满足以下任一条件时,分箱是比缩放或裁剪更合适的替代方案:

  • 特征与标签之间没有明显线性关系——整体呈非线性、甚至看不出相关性。

  • 特征值在某些子区间内扎堆(即呈现「簇」状),并不均匀地铺满整个取值范围。

这听起来似乎有点反直觉,在上面这个例子中,37 和 115 明明差了好几倍,却被模型当成「同一类」。其实关键就在另一面——当特征呈现「簇状」而非「线性」时,用分箱表达数据远比直接喂原值更贴切。

下面我们通过示例来进行说明。


分箱示例:购物人数 vs 当日温度#

我们用一个具体例子把分箱的工作机制讲透。假设你在做一个模型,根据当日的室外温度预测来店的购物人数,下面这张散点图展示了温度与购物人数的关系:

图 9. 一张 45 点的散点图。这 45 个点天然分成了三组。
图 9. 购物人数 vs 温度的散点图

从图9可以直观看出,温度最舒服的那段,购物人数最多。

那能不能直接把温度当成原值塞进模型?比如数据集里某条样本的温度是 35.0,那就用 35.0 进入特征向量——这样是不是最稳妥的做法?我们来算一笔账。

在线性回归的训练中,模型只能给每个特征学到一个全局权重。如果温度被当成单一特征,那么在预测时:35.0 对结果的影响将是 7.0 的 5 倍(或者反过来,是 1/5)。可惜从图上看,温度与标签之间没有任何明显的线性关系——硬塞线性权重反而会成为累赘。

MLWM: 上面的意思是说,温度为35°时是温度为7°时的5倍,但是35°时对应的购物任务并不是7°时的5倍,这就与 $y=wx+b$ 这个模型矛盾了。

如果改成 3 个簇,效果会好很多:

  • 桶 1:温度区间 4 到 11。

  • 桶 2:温度区间 12 到 26。

  • 桶 3:温度区间 27 到 36。

图 10. 与图 9 同样的 45 点散点图,但用三条竖直的虚线把图分成了 3 桶,使分桶更直观。
图 10. 把散点图切成 3 个桶

切完之后,模型就能为每一桶学到独立的权重,把每段温度对购物人数的差异化影响都拾起来。

不过,桶并不是越多越好。我们来看一个反例:哪怕每个温度值单独一桶——也就是 33 个桶——通常来说都不是好主意,原因有两条:

  • 模型只有在桶内有足够样本时,才能学到桶与标签之间的关联。 在当前例子中,每个桶都至少有 10 个样本,勉强够训练;但如果分成 33 桶,没有哪个桶能凑够训练用的样本量。

  • 每个温度值都单独成桶,会一下子让温度特征从 1 个变成 33 个——而我们通常应该尽量减少模型里的特征数量。

小测验:检验你的理解#

下面这张图展示的是虚构国家「Freedonia」在每 0.2 度纬度上的房价中位数:

图 11. 一张房价 vs 纬度的图。最低房价约 327,最高约 712。纬度覆盖 41.0 到 44.8,每个 0.2 度的纬度上有一个点代表对应的房价中位数。整体模式很不规则,但能看到两簇——一簇在纬度 41.0 到 41.8 之间,另一簇在纬度 42.6 到 43.4 之间。
图 11. 每 0.2 度纬度上的房价中位数

房价与纬度之间明显是非线性的关系——把纬度直接当成浮点数送进模型,恐怕帮不上什么忙。那是否应该把纬度分桶? 如果要分,最合理的策略是哪一种?

  • A. 不分桶

  • B. 分成 4 个桶

  • C. 把每个数据点单独成一个桶


分位数分箱#

前面说的都是「等距」分桶——把整个取值范围切成宽度相等的桶。等距分桶简单好用,但对偏态分布效果不佳,因为尾部的桶往往样本寥寥无几,模型根本学不动。

分位数分箱(quantile bucketing)正是为了补这个短板而出现的,它按样本数划分桶的边界——让每个桶里的样本数大致相等。这样一来,长尾就被压扁了。

来看一个对比。下图展示的是「等距分桶」对汽车销量的划分:每桶宽度都是 1 万美元。

图 13. 一张「汽车售价 vs 销量」的散点图:销量在 6000 美元价位最高,超过 6000 美元后销量总体下降,4 万到 6 万美元之间的销量尤其稀少。图上画了 6 个等宽桶,每桶 10000 美元范围:第 1 桶覆盖 0 到 10000,第 2 桶覆盖 10001 到 20000,以此类推。第 1 桶里样本极多;之后每个桶的样本都比上一桶少。
图 13. 有的桶里车多,有的桶里车少

可以看到:0 到 10000 这一桶塞进了几十台车,而 50000 到 60000 这一桶只有 5 台——模型在前一桶有充分样本可以学、在后一桶几乎无米下锅。

而下面这张图,用分位数分箱重新分桶,那么每个桶里的样本数大致相等,但桶的宽度差异极大。

图 14. 与图 13 同样的数据,但改用分位数桶:桶的宽度不再相等。第 1 桶覆盖 0 到 4000,第 2 桶覆盖 4001 到 6000,第 6 桶覆盖 25001 到 60000。每个桶里的样本数都大致相同。
图 14. 分位数分桶让每个桶里的车数大致相同

读者可以对比一下两种切法的差异:

  • 第 1 桶只覆盖 0 到 4000(很窄),但样本很多;

  • 第 6 桶覆盖 25001 到 60000(特别宽),但样本数与第 1 桶相当。

分位数分箱的最大好处,是让每个桶都有足够样本去训练,从而对长尾分布也保持稳定的预测能力。

分箱策略怎么选?#

许多分布下,等距分箱都够用。但对偏态(skewed)数据,强烈推荐试试分位数分箱:

  • 等距分箱把长尾「摊薄」成大段空白,却把高密度主体挤进了少数几个桶——尾部信号被浪费。

  • 分位数分箱把高密度主体「摊薄」到若干个等量桶,让每个桶都有数据可学;长尾则被压进少量桶,代价是牺牲尾部细节。


关键术语:

  • 分箱(Binning)
  • 分桶(Bucketing)
  • 裁剪(Clipping)
  • 特征(Feature)
  • 特征工程(Feature engineering)
  • 特征向量(Feature vector)
  • 标签(Label)
  • 缩放(Scaling)
阅读 --