分区模型没有新算法:先按一个变量分组,每组拟合一条自己的回归线。 技术部斜率 0.0898、销售部 0.0554,两条线各自的段内误差是 0.94 和 0.67,合起来 0.87。 但切太细会翻车:把技术部切成六段,六个斜率从 0.031 跳到 0.253,差 8 倍——那是噪声在装结构。
上一篇已经把两段分开算了。这一篇把这件事叫做一个模型,并说清它的边界。 书里最后还是回到「客户满意」这个落点:交付物变了,客户的问法也就变了。
一、分区模型就是几条线
分区模型没有新算法,就是把上面的做法固定下来:先分组,每组一条回归线。 分组变量可以是类别(部门、职级、地区),也可以是把连续量切成段(分数段、工龄段)。 这里用的是类别:技术部一条,销售部一条。两条线的参数完全不同,这是允许的。
关键在于分组要有业务含义。纯粹为了降误差而分组,等于把噪声也当成结构。
二、两条线长什么样
| 部门 | 人数 | 斜率 | 截距 | 段内 RMSE |
|---|---|---|---|---|
| 技术部 | 60 | 0.0898 | 0.70 | 0.94 |
| 销售部 | 24 | 0.0554 | 0.66 | 0.67 |
两条线的斜率差了 0.0344:技术部每多 10 点涨 0.90 个点,销售部只涨 0.55 个点。 截距几乎一样(0.70 和 0.66),说明两条线差不多交汇在低分那一段——但越往高分越分开。 这个差本身就是结论:两个部门的加薪机制不是同一个。
三、切得太细会怎样
既然切两段好,切六段是不是更好?拿技术部 60 条按分数切成六段试一下。 六个斜率分别是 0.253、0.150、0.221、0.195、0.031、0.243。最大是最小的 8.3 倍。 可这六段全是技术部的同一套制度,斜率不该这么乱。这些差别是噪声装出来的,不是制度变了。
段内 RMSE 确实降到了总 0.86,但那是拿样本换的:每段只剩 6 到 11 个人。 段越细,样本越少,拟合出的斜率越像噪声。这叫过拟合,代价是解释力和可靠性。
四、怎么定切几段
第一条:段内的人得真的像同一类人。理由是业务上的,不是统计上的。 第二条:每段要有足够样本,否则斜率不可信。经验上少于二十条就要小心。 第三条:段与段之间要有实质差别。两条线斜率差不多,就没必要分开。
三条都是判断,不是计算。没有一条能靠跑代码得出。 所以分区模型是最依赖业务理解的一种模型:算法只占很小一部分。
五、客户回头了
人事拿走了两段模型:技术部一条、销售部一条,各自带着自己的 RMSE。 他们不再问「这个人该加多少」,改成问「这个人在哪一段、那一段的误差多大」。 问题变了,因为交出去的东西变了:从一个数,变成了一个数加一个适用范围。
108 分那位也有了去处:他不在任何一段的范围内,走特批。 这就是第 11 章的全部内容:模型给的不是答案,是带边界的答案。
六、动手 Demo:分区模型:每条线各管一段
两个部门各自一条线,把参数和段内误差摆出来。 再把技术部按分数切成六段,看斜率乱成什么样。
def mk(seed, n, lo, hi, a, b0, noise):
S = [seed]
def rnd():
S[0] = (S[0] * 1103515245 + 12345) % 2147483648
return S[0] / 2147483648.0
out = []
for i in range(n):
x = lo + int(round(i * (hi - lo) / float(n - 1)))
y = a + b0 * x + (rnd() - 0.5) * noise
out.append((x, round(y, 1)))
return out
TECH = mk(20261102, 60, 40, 95, 1.2, 0.085, 3.2)
SALE = mk(88117, 24, 42, 92, 1.0, 0.055, 2.6)
def fit(d):
xs = [p[0] for p in d]
ys = [p[1] for p in d]
n = len(xs)
mx = sum(xs) / float(n)
my = sum(ys) / float(n)
k = sum((x - mx) * (y - my) for x, y in zip(xs, ys)) / sum((x - mx) ** 2 for x in xs)
return k, my - k * mx
def rmse(d, k, b):
return (sum((y - (b + k * x)) ** 2 for x, y in d) / float(len(d))) ** 0.5
for nm, d in (("TECH", TECH), ("SALE", SALE)):
k, b = fit(d)
print("%s n=%2d m=%.4f b=%.2f RMSE=%.2f" % (nm, len(d), k, b, rmse(d, k, b)))
print()
print("技术部切成六段:")
for lo, hi in ((40, 50), (50, 60), (60, 70), (70, 80), (80, 90), (90, 96)):
sub = [p for p in TECH if lo <= p[0] < hi]
k6, b6 = fit(sub)
print(" %2d~%2d n=%2d 斜率 %+.3f 段内 RMSE %.2f" % (lo, hi, len(sub), k6, rmse(sub, k6, b6)))
实跑输出:
--------------------------------------------------------------------
分区模型:每条线各管一段
--------------------------------------------------------------------
① 分区模型就是几条线
--------------------------------------------------------------------
分区模型没有新算法,就是把上面的做法固定下来:先分组,每组一条回归线。
分组变量要么是类别(部门、职级),要么是把连续量切成段。
这里用的是类别:技术部一条,销售部一条。两条线的参数完全不同,这是允许的。
② 两条线长什么样
--------------------------------------------------------------------
| 部门 | 人数 | 斜率 | 截距 | 段内 RMSE |
|---|---:|---:|---:|---:|
| 技术部 | 60 | 0.0898 | 0.70 | 0.94 |
| 销售部 | 24 | 0.0554 | 0.66 | 0.67 |
两条线的斜率差了 0.0344——技术部每多 10 点涨 0.90 个点,销售部只涨 0.55 个点。
这个差本身就是结论:两个部门的加薪机制不是同一个。
③ 切得太细会怎样
--------------------------------------------------------------------
既然切两段好,切六段是不是更好?拿技术部 60 条试一下,按分数切成六段。
| 分数段 | 人数 | 斜率 | 段内 RMSE |
|:---:|---:|---:|---:|
| 40~50 | 11 | +0.253 | 0.93 |
| 50~60 | 10 | +0.150 | 0.74 |
| 60~70 | 11 | +0.221 | 0.81 |
| 70~80 | 11 | +0.195 | 0.84 |
| 80~90 | 11 | +0.031 | 0.87 |
| 90~96 | 6 | +0.243 | 0.97 |
六个斜率从 0.031 到 0.253,最大是最小的 8.3 倍。
六个段都是技术部的同一套制度,斜率不该这么乱——这些差别是噪声装出来的,不是制度变了。
段内 RMSE 确实更小了(总 RMSE 0.86),但那是拿样本换来的:每段只剩十几个人。
! 段越细,样本越少,拟合出来的斜率越像噪声。这叫过拟合,代价是解释力和可靠性。
④ 怎么定切几段
--------------------------------------------------------------------
第一条:切开之后,段内的人得真的像同一类人。理由是业务上的,不是统计上的。
第二条:每段要有足够的样本,否则斜率不可信。经验上少于二十条就要小心。
第三条:段与段之间要有实质差别。两条线斜率差不多,就没必要分开。
这三条没有一条是算法给的,全靠对业务的理解。
⑤ 客户回头了
--------------------------------------------------------------------
人事拿走了两段模型:技术部一条、销售部一条,各自带 RMSE。
他们不再问「这个人该加多少」,改成问「这个人在哪一段、那一段的平均误差多大」。
问题变了,因为交出去的东西变了:从一个数,变成了一个数加一个适用范围。
这就是第 11 章的全部内容:模型给的不是答案,是带边界的答案。
两段模型的斜率差 0.0344,是制度差异;六段模型的斜率差 0.222,是噪声。 同样是「差」,来源完全不同。 判断方法只有一个:问这个差在业务上解不解释得通。解释得通就是结构,解释不通就是过拟合。
30 秒实验
- 如果把销售部按「有无大客户」再分两段,会降误差还是会过拟合?判断依据是什么?
- 两条线的截距几乎一样(0.70 与 0.66),这说明了什么?
- 想一想:为什么分区模型比单一模型更容易说服客户,也更容易被客户质疑?
常见误区
- 切到误差最小为止:一直切下去误差总会降,但那是在拟合噪声。
- 分组没有业务含义:按「姓名字母」分组也能切,切出来的斜率毫无意义。
- 每段样本太少还硬拟合:六条数据拟合一条线,斜率可以是任何值。
- 只报段内 RMSE:单段误差小是必然的,要比就得拿全样本合起来比。
自测三问(点开对答案)
1. 分区模型和普通回归的本质区别是什么? —— 没有区别。算法完全一样,只是先把数据按一个变量分组,每组各跑一次回归。 2. 为什么切成六段反而不好? —— 因为每段样本太少,拟合出来的斜率主要由噪声决定。段内误差看着降了,但那是在拟合噪声。 3. 判断一个分组值不值得,看哪三件事? —— 段内是不是同一类人、样本够不够、段与段之间有没有实质差别。三条都要靠业务判断。第 11 章到此收口。第 12 章换赛道:数据从一个表变成多张表,讲关系数据库。
- ☐ (本篇完,下一篇 12.1 数据邦新闻要分析销量)