📈 第11章 误差
📄 一句话概括

机会误差 = 实际结果 − 模型预测。60 条记录里它的范围是 −1.45 到 +1.69,中位数 −0.11。 残差不是模型的错误,是模型没装进去的那些变量的痕迹。把它当噪声扔掉,就扔掉了下一步的方向。 误差的合格线由客户定:偏 0.5 个点以内不够用,偏 2 个点以内就够了。这句话决定要不要继续做。

📝 本章和前面几章的关系

上一篇把外插挡住了。这一篇开始量误差:先看它长什么样,再想它能干什么。 书里叫机会误差,这个词的重点在「机会」——它是有用的,不是要消灭的。

一、扭曲的数据长什么样

把 60 个人的预测值和实际值并排放,每一行多一列「差」。 40 分那位:预测 4.29%,实际 4.9%,差 +0.61。 44 分那位:预测 4.65%,实际 3.4%,差 −1.25。

93 分那位:预测 9.05%,实际 10.6%,差 +1.55。 把这一列排开看,最小 −1.45,最大 +1.69,中位数 −0.11。这就是误差的分布。 它不集中在 0 附近一条细线上,而是摊开有 3 个多点的宽度。

二、机会误差 = 实际 − 预测

这个减法只能有一个方向:实际减预测。反了的话,所有解读都会翻。 差为正:这个人拿到的比模型给的多。差为负:拿到的比模型给的少。 符号很重要。只看绝对值,就丢掉了「偏哪边」这条信息,而偏哪边往往才是要追的问题。

这里正的有 28 个、负的有 32 个,符号大致对半,说明模型没有系统性偏高或偏低。 如果有系统性偏差,说明模型结构就错了,不是噪声大。这是两种完全不同的病。

三、误差不是错误

如果所有残差都是 0,那说明模型把人当成了机器:分数一样的人加薪完全一样。 现实里不会这样,因为分数之外还有部门、岗位、谈判、运气。 所以残差里藏着模型没用的那些变量的线索。把这些线索当噪声扔掉,等于扔掉了下一步的方向。

具体怎么找:把残差按某个变量分组求平均。某一组平均残差明显不是 0,那个变量就该进模型。 这件事第 11.5 节会真的做一遍:按部门一分,残差立刻显出结构。

四、误差对客户有什么用

用途 怎么用
给区间 预测 ± 一个数,客户才知道能拿它干什么
排优先级 残差大的人,说明现有制度对他解释力最弱
谈例外 拿残差去谈特批,比拿预测值去谈有理

三条用途都要求同一件事:误差得先被量出来,不能停在「大概不太准」。 「大概不太准」是一句没有信息量的话,客户听完还是不知道能干什么。 量出来的误差才能变成决策依据。量不出来的,只能叫免责声明。

五、机会误差访谈

下一步不是继续算,是回去问客户一句话:你能接受偏多少? 偏 0.5 个点以内,那现在这个模型不够用,得加变量重做。 偏 2 个点以内,那 0.94 就够,可以直接交。

同一个模型,两种答案。差别不在数据,在客户的用途。 误差的合格线是客户定的,不是分析师定的。这句话决定了后面还要不要投入。

六、动手 Demo:机会误差:实际减预测那段距离

把 60 条记录的前五行和后五行摆出来,每行加一列「差」。 再统计残差的极值、中位数、正负个数,看有没有系统性偏差。

S = [20261102]

def rnd():
    S[0] = (S[0] * 1103515245 + 12345) % 2147483648
    return S[0] / 2147483648.0

DATA = []
for i in range(60):
    x = 40 + int(round(i * 55 / 59.0))
    y = 1.2 + 0.085 * x + (rnd() - 0.5) * 3.2
    DATA.append((x, round(y, 1)))

XS = [d[0] for d in DATA]
YS = [d[1] for d in DATA]
n = len(XS)
mx = sum(XS) / float(n)
my = sum(YS) / float(n)
m = sum((x - mx) * (y - my) for x, y in zip(XS, YS)) / sum((x - mx) ** 2 for x in XS)
b = my - m * mx

res = [y - (b + m * x) for x, y in DATA]
for i in list(range(5)) + list(range(55, 60)):
    x, y = DATA[i]
    print("%2d 分  预测 %5.2f%%  实际 %4.1f%%  差 %+.2f" % (x, b + m * x, y, res[i]))

pos = sum(1 for d in res if d > 0)
print()
print("残差最小 %.2f  最大 %.2f" % (min(res), max(res)))
print("为正 %d 个,为负 %d 个" % (pos, n - pos))
print("残差合计 %+.3f(接近 0 说明没有系统性偏差)" % sum(res))

实跑输出:

--------------------------------------------------------------------
机会误差:实际减预测那段距离
--------------------------------------------------------------------

  ① 扭曲的数据长什么样
  --------------------------------------------------------------------

| 点数 | 模型预测 | 实际拿到 | 差 |
|---:|---:|---:|---:|
| 40 | 4.29% | 4.9% | +0.61 |
| 41 | 4.38% | 3.5% | -0.88 |
| 42 | 4.47% | 3.4% | -1.07 |
| 43 | 4.56% | 3.4% | -1.16 |
| 44 | 4.65% | 3.4% | -1.25 |
| 91 | 8.87% | 8.2% | -0.67 |
| 92 | 8.96% | 7.7% | -1.26 |
| 93 | 9.05% | 10.6% | +1.55 |
| 94 | 9.14% | 10.4% | +1.26 |
| 95 | 9.23% | 9.1% | -0.13 |

  前五行和后五行摆在一起,能看出这个差有正有负,而且大小差不多。
  残差最小 -1.45,最大 1.69,中位数 -0.11。
  ! 残差不是「模型的错」,是模型没装进去的那些因素在起作用。

  ② 机会误差 = 实际 − 预测
  --------------------------------------------------------------------
  书里把它叫机会误差。名字的意思是:这段距离不是废料,是机会。
  差为正:这个人拿到的比模型给的多。差为负:拿到的比模型给的少。
  符号很重要。只看绝对值,就丢掉了「偏哪边」这条信息。
  这里正负大致对半——说明模型没有系统性偏高或偏低,只是单个不准。

  ③ 误差不是错误
  --------------------------------------------------------------------
  如果所有残差都是 0,那说明模型把人当成了机器:分数一样的人加薪完全一样。
  现实里不会这样,因为分数之外还有部门、岗位、谈判、运气。
  所以残差里藏着模型没用的那些变量的线索。把它当噪声扔掉,等于扔掉了下一步的方向。
  这里残差为正的有 28 个、为负的有 32 个,符号大致对半,说明模型没有系统性偏高或偏低。
  如果某一类人的残差总是同号,那就是模型漏了变量的明确信号——那类人得单独建模。

  ④ 误差对客户有什么用
  --------------------------------------------------------------------

| 用途 | 怎么用 |
|---|---|
| 给区间 | 预测 ± 一个数,客户才知道能拿它干什么 |
| 排优先级 | 残差大的人,说明现有制度对他解释力最弱 |
| 谈例外 | 拿残差去谈特批,比拿预测值去谈有理 |

  这三条都要求同一件事:误差得先被量出来,不能停在「大概不准」。

  ⑤ 机会误差访谈
  --------------------------------------------------------------------
  下一步不是继续算,是回去问客户一句话:你能接受偏多少?
  偏 0.5 个点以内,那现在这个模型不够用;偏 2 个点以内,那 0.94 就够。
  误差的合格线是客户定的,不是分析师定的。这句话决定了后面要不要继续做。

残差合计是 0.000——这是最小二乘的数学性质,不是巧合。 所以永远不能靠「残差加起来是多少」判断模型好坏。 要判断有没有系统性偏差,得先分组,再看组内的平均残差。这一步 11.5 节做。

30 秒实验

  1. 把残差按分数段分成三组,各组平均残差分别是多少?有没有哪一组明显不为 0?
  2. 如果把「实际 − 预测」改成「预测 − 实际」,后面的解读要改哪些地方?
  3. 想一想:为什么残差合计必然为 0,这件事会让「残差平均是 0」变成一个没用的结论?

常见误区

  1. 减法方向反了:写成预测减实际,所有正负解读全反。要固定成实际减预测。
  2. 只看绝对值:丢掉符号就丢掉了「偏哪边」这条最有用的问题。
  3. 把残差当垃圾:残差里的结构就是下一个该进模型的变量。
  4. 用「残差平均为 0」证明模型好:最小二乘的必然结果,不带任何信息。
自测三问(点开对答案) 1. 机会误差怎么算?方向为什么不能反? —— 实际减预测。方向反了,正负号的解读全反,后面所有结论都会跟着错。 2. 残差合计为什么必然是 0? —— 因为最小二乘选的那条线让残差平方和最小,这个条件本身就推出残差和为零。 它是数学性质,不是模型好的证据。 3. 误差的合格线由谁定? —— 客户。同一个模型,用途不同,能接受的偏差也不同。分析师只负责把误差量准。

误差看得见了,但客户要的是一个能写进制度的数。下一篇把它压成一个数:均方根误差。

相关笔记