5D Library › 学习的85%最优错误率定律、髓鞘化动力学与刻意练习 · English
第一章 为什么太简单学不会、太难会崩溃:85% 法则
两种失败
设想一位学习者在练习一项判断:一张 X 光片上有没有阴影,一段旋律是升了还是降了,一个句子在语法上对不对。如果题目全都很容易,他几乎每题都对;可是正因为都对,他从每道题里得到的「新信息」很少。如果题目全都很难,他几乎是在猜,对错跟他的判断关系不大,同样学不到多少。直觉告诉我们,最有效的练习难度在两者之间。
这种直觉在教育学和心理学中有很长的历史,但通常停留在定性的层面。威尔逊、申哈夫、斯特拉恰与科恩在 2019 年发表于《自然·通讯》的论文,在一个明确的数学模型里把「之间」算了出来 (Wilson et al. 2019)。
模型:精度、难度与误差驱动的学习
论文考虑的是二分类任务。每一次试次,学习者从刺激中算出一个决策变量 ,再根据 的正负做出判断。 是真实决策变量 的一个带噪声的版本: 表示刺激离类别边界有多远, 越小题目越难;噪声的大小是 , 称为精度,代表学习者的技能,是学习要提高的东西。若噪声的标准化分布函数为 、密度为 ,错误率就是
学习者通过梯度下降调整内部参数 来降低错误率。按链式法则,
其中只有第一项与难度 有关。因此,在给定的技能水平下,要让每一次试次带来的期望学习增益最大,就要让
最大。对 求导并令其为零,得到 ,其中 。对高斯噪声,,所以 ,即 :最优难度恰好让「真实信号」等于一个噪声标准差。此时的错误率是
正确率约 84.13%。这就是「85% 法则」的来源。注意它与 无关:无论学习者现在水平高低,最优的错误率都一样;变的是达到这个错误率所需的难度。
注
一处需要更正的公式。 本书的最初框架把最优错误率写成 。这个式子的值约为 0.146,并不等于 0.1587。论文的结果是 ,即标准正态分布在 处的累积概率。两者只是形状相似,下面的程序同时算出了它们。
用暴力搜索数值地重现推导:对三种噪声分布,在固定精度 下搜索使 最大的难度;再看偏离最优错误率时每次试次的学习增益还剩多少。
推导
# Optimal training error rate (Wilson et al. 2019): ER = F(-beta Delta), gradient learning
# gain -dER/dbeta = Delta p(beta Delta); find the Delta that maximises it, for three noises.
import math
from statistics import NormalDist
N = NormalDist()
def best(F, p, beta=1.0):
# brute-force search over difficulty Delta for the largest expected learning gain
grid = [i / 10000 for i in range(1, 60001)]
d = max(grid, key=lambda D: D * p(beta * D))
return d, F(-beta * d), d * p(beta * d)
noises = {
"Gaussian": (N.cdf, N.pdf),
"Laplacian": (lambda x: 0.5 * math.exp(x) if x < 0 else 1 - 0.5 * math.exp(-x),
lambda x: 0.5 * math.exp(-abs(x))),
"Cauchy": (lambda x: 0.5 + math.atan(x) / math.pi, lambda x: 1 / (math.pi * (1 + x * x))),
}
print("noise | optimal beta*Delta | optimal error rate | accuracy")
for name, (F, p) in noises.items():
d, er, _ = best(F, p)
print(f"{name:10s} | {d:18.3f} | {er:18.4f} | {1 - er:.2%}")
print(f"closed form, Gaussian: 1/2 erfc(1/sqrt 2) = {0.5 * math.erfc(1 / math.sqrt(2)):.5f}")
wrong = 0.5 * (1 - 1 / math.sqrt(2))
print(f"the formula 1/2 (1 - 1/sqrt 2) = {wrong:.5f} (not the result)")
print("\nGaussian noise: learning gain per trial relative to the optimum, beta = 1")
g_star = best(N.cdf, N.pdf)[2]
for er in (0.01, 0.05, 0.10, 0.1587, 0.20, 0.30, 0.40, 0.45):
D = -N.inv_cdf(er)
g = D * N.pdf(D) / g_star
print(f" training error rate {er:6.2%} (accuracy {1 - er:6.2%}): gain {g:5.1%}")
# noise | optimal beta*Delta | optimal error rate | accuracy
# Gaussian | 1.000 | 0.1587 | 84.13%
# Laplacian | 1.000 | 0.1839 | 81.61%
# Cauchy | 1.000 | 0.2500 | 75.00%
# closed form, Gaussian: 1/2 erfc(1/sqrt 2) = 0.15866
# the formula 1/2 (1 - 1/sqrt 2) = 0.14645 (not the result)
#
# Gaussian noise: learning gain per trial relative to the optimum, beta = 1
# training error rate 1.00% (accuracy 99.00%): gain 25.6%
# training error rate 5.00% (accuracy 95.00%): gain 70.1%
# training error rate 10.00% (accuracy 90.00%): gain 92.9%
# training error rate 15.87% (accuracy 84.13%): gain 100.0%
# training error rate 20.00% (accuracy 80.00%): gain 97.4%
# training error rate 30.00% (accuracy 70.00%): gain 75.4%
# training error rate 40.00% (accuracy 60.00%): gain 40.5%
# training error rate 45.00% (accuracy 55.00%): gain 20.6%积分学习方程,比较「每一步都把难度调到最优错误率」与「难度固定在起点」两种训练。
推导
# Learning dynamics in the model of Wilson et al. (2019), Gaussian noise. Integrate
# d beta / dt = eta * Delta * p(beta * Delta)
# two ways: (a) difficulty re-set every step so that the error rate stays at
# ER* = Phi(-1) = 15.87 % (Delta = 1 / beta); (b) difficulty frozen at its starting value.
import math
from statistics import NormalDist
N = NormalDist()
eta, beta0 = 0.01, 1.0
for label, adapt in (("(a) error rate held at 15.87%", True),
("(b) difficulty fixed at start", False)):
beta, D0, t, out = beta0, 1.0 / beta0, 0, []
for T in (100, 1000, 10000, 100000):
while t < T:
D = 1.0 / beta if adapt else D0
beta += eta * D * N.pdf(beta * D)
t += 1
D = 1.0 / beta if adapt else D0
out.append(f"t={T:>6}: beta {beta:5.2f}, ER {N.cdf(-beta * D):6.2%}")
print(label + "\n " + "\n ".join(out))
print(f"theory for (a): beta = sqrt(beta0^2 + 2 eta p(1) t) = "
f"{math.sqrt(beta0 ** 2 + 2 * eta * N.pdf(1) * 100000):.2f} at t = 100000")
# (a) error rate held at 15.87%
# t= 100: beta 1.22, ER 15.87%
# t= 1000: beta 2.42, ER 15.87%
# t= 10000: beta 7.03, ER 15.87%
# t=100000: beta 22.02, ER 15.87%
# (b) difficulty fixed at start
# t= 100: beta 1.22, ER 11.21%
# t= 1000: beta 2.06, ER 1.98%
# t= 10000: beta 3.06, ER 0.11%
# t=100000: beta 3.80, ER 0.01%
# theory for (a): beta = sqrt(beta0^2 + 2 eta p(1) t) = 22.02 at t = 100000程序给出了几点。第一,三种噪声的最优点都在 ,但对应的错误率不同:高斯噪声 15.87%,拉普拉斯噪声 18.39%,柯西噪声 25%。「85%」依赖于噪声的形状,这一点论文本身也写明了 (Wilson et al. 2019)。第二,最优点附近相当平坦:训练错误率在 10% 到 20% 之间时,每次试次的学习增益都在最大值的约 93% 以上(10% 处为 92.9%);错误率 30% 时仍有约 75%;真正吃亏的是两端:错误率 1%(正确率 99%)时增益只剩约 26%,错误率 40% 时约 40.5%。第三,长期的差别更大:难度随技能同步提高时,精度按 增长,十万次试次后达到 22.02,与理论公式完全一致;难度固定不变时,学习者很快就「做得太好」,错误率在一千次试次后降到约 2%,精度在十万次后只有 3.80。
证据
论文中的模拟与作者的限定。 威尔逊等人在两类模型上检验了这一结果:一个在 100 维高斯刺激上训练的感知机,以及劳与戈尔德提出的、模拟猴子知觉学习的生物学合理的强化学习网络 (Law and Gold 2009)。两者都在约 15.87% 的训练错误率附近学得最快 (Wilson et al. 2019)。作者同时写明,结果尚需推广到多选任务和不同的学习算法;并非所有模型都存在难度的「甜区」,例如理想贝叶斯学习者,其参数后验与试次的顺序无关,也就谈不上「什么时候出什么难度的题」。
模拟一个感知机学习者
推导假设训练者每一步都知道学习者当前的精度,并据此设定难度。这在模拟里可以做到。下面的学习者在 50 维空间里学习一个未知的分类方向,每个维度上都有单位噪声;它的精度就是它的权重方向与真实方向夹角的余弦。
学习规则是感知机规则的平滑(逻辑斯蒂)版本:错得越多或越拿不准,更新越大。每种目标错误率各模拟 60 个学习者,每人训练 400 次,最后在固定难度 的测验上评估技能。
推导
# Simulated learner in 50 dimensions: x = label*Delta*e + N(0,1) noise; precision beta =
# cos(w, e). Delta is set before each trial so the CURRENT error rate equals the target.
# Rule: smoothed (logistic) perceptron update. Skill: test accuracy at Delta = 1.
import math, random
from statistics import NormalDist
N = NormalDist()
D, TRIALS, ETA, RUNS = 50, 400, 0.05, 60
def train(target_er, seed, trials=TRIALS, record=()):
rng = random.Random(seed)
w = [rng.gauss(0, 1) for _ in range(D)]
w[0] = abs(w[0]) + 0.5 # start slightly better than chance
curve = []
for t in range(trials):
norm = math.sqrt(sum(v * v for v in w))
beta = w[0] / norm
if t in record:
curve.append(N.cdf(beta)) # test accuracy at Delta = 1
delta = -N.inv_cdf(target_er) / max(beta, 1e-3)
lab = 1 if rng.random() < 0.5 else -1
x = [rng.gauss(0, 1) for _ in range(D)]
x[0] += lab * delta
h = sum(a * b for a, b in zip(w, x)) / norm
g = 1 - 1 / (1 + math.exp(-3 * lab * h)) # large when wrong or unsure
w = [a + ETA * g * lab * b for a, b in zip(w, x)]
norm = math.sqrt(sum(v * v for v in w))
return w[0] / norm, curve
if __name__ == "__main__":
targets = (0.02, 0.05, 0.10, 0.13, 0.16, 0.20, 0.25, 0.30, 0.40)
print(f"{RUNS} learners per target, {TRIALS} trials each")
print("target training error | final precision beta | test accuracy at Delta = 1")
res = {er: sum(train(er, s)[0] for s in range(RUNS)) / RUNS for er in targets}
for er, b in res.items():
print(f" {er:5.0%} | {b:5.3f} | {N.cdf(b):6.1%}")
top = max(res, key=res.get)
near = [e for e in targets if res[e] >= 0.98 * res[top]]
print(f"best target {top:.0%}; within 2 % of the best precision: "
+ ", ".join(f"{e:.0%}" for e in near))
# 60 learners per target, 400 trials each
# target training error | final precision beta | test accuracy at Delta = 1
# 2% | 0.625 | 73.4%
# 5% | 0.727 | 76.6%
# 10% | 0.789 | 78.5%
# 13% | 0.805 | 79.0%
# 16% | 0.813 | 79.2%
# 20% | 0.814 | 79.2%
# 25% | 0.804 | 78.9%
# 30% | 0.781 | 78.3%
# 40% | 0.667 | 74.8%
# best target 20%; within 2 % of the best precision: 13%, 16%, 20%, 25%模拟的结果与理论大体一致,但并不完全相同。最优目标落在 16%–20% 一带,与最优精度相差不到 2% 的区间是 13%–25%;而训练错误率 2% 时最终精度明显较低(0.625 对 0.814),40% 时也是如此(0.667)。最优点略高于 15.87%,可能是因为有限的训练次数、离散的学习步长和平滑的学习规则都偏离了推导的理想条件(16% 与 20% 的差别只有 0.001,也在模拟误差之内)。这正好说明:最优值是一个区间,而不是一个精确到小数点的数字。
前提与适用边界
这个结果的力量来自它的简洁,它的边界也来自同样的简化。至少有五个前提:第一,难度可以连续调节,而且训练者知道学习者当前的水平;现实中只能从近期的对错去估计,第八章的自适应「阶梯法」是一种近似。第二,二元决策;多选任务、连续反应或开放式产出有各自的错误结构,最优错误率是否存在、是多少,需要另行推导。第三,噪声形状:程序已显示,噪声一变,最优错误率就从 15.87% 变到 18.39% 或 25%。第四,梯度下降类的学习规则;理想贝叶斯学习者不受试次顺序影响,依靠记忆个别样例或一次顿悟的学习也未必符合这一前提。第五,它优化的是每次试次的学习速度,没有考虑动机、挫败感与疲劳,也没有考虑一周后的保持或迁移;后几章会看到,间隔与交错恰恰以当下的表现换取长期的保持。
因此,把这个结果说成「人学任何东西都应该保持 85% 的正确率」是过度推广。更稳妥的说法是:在可以把题目难度调细、对错清楚、反馈及时的练习中,让正确率落在大约 80%–90% 之间,有理论和模拟上的理由;正确率长期接近 100% 或接近随机水平,都是难度需要调整的信号。
最近发展区:类比,不是同一个定理
维果茨基把「最近发展区」定义为:儿童独立解决问题所达到的实际发展水平,与在成人指导下或与能力更强的同伴合作时所能达到的潜在发展水平之间的距离 (Vygotsky 1978)。这个概念讲的是发展与社会中介:一个孩子今天在别人帮助下能做到的事,明天可能独立做到;教学应当走在发展的前面。
85% 法则与最近发展区确实相像:两者都说最有效的学习发生在「刚好超出现有能力」的地方。威尔逊等人在讨论中也把自己的结果与梅特卡夫和科内尔的「近端学习区域」模型联系起来,后者描述学习者如何把学习时间分配给那些尚未掌握、但离掌握不远的项目,并且承认它的思想来源可以追溯到皮亚杰与维果茨基 (Metcalfe and Kornell 2005; Wilson et al. 2019)。但是两者不是同一个定理:最近发展区没有给出任何最优正确率,它关心的是在他人帮助下能做到什么;85% 法则则是一个单个学习者、单一技能、特定学习规则下的数学结果,没有「他人」的角色。把它们放在一起,是一种有启发的类比。
假说 · 尚未验证 · 人类知觉分类中的平坦最优区
尚未确立。 在一项可以连续调节难度的二元知觉分类任务中(例如判断两组点哪一组更多),把成年人随机分为三组,用自适应程序分别把训练正确率维持在约 70%、约 85% 与约 95%,训练次数相同。作者预期:85% 组在训练后的标准测验中进步最大,但与 70% 组的差别小于与 95% 组的差别(因为最优区平坦,而太容易的代价更大)。如果 95% 组的进步不小于 85% 组,或者三组没有可靠差别,这个假说就是错的。
本章小结
威尔逊等人证明:对于用梯度下降学习的二分类学习者,在高斯噪声下,让精度与难度的乘积等于 1,也就是训练错误率约 15.87%(正确率约 84.13%)时,每次试次的学习增益最大;正确的公式是 ½ erfc(1/√2),不是 ½(1 − 1/√2)。最优区相当平坦,噪声形状不同则最优值不同,模拟学习者的最优点也落在一个区间里。这个结果依赖于难度可调、二元判断、特定噪声与梯度学习等前提,不能直接推广为「一切学习的 85% 定律」。维果茨基的最近发展区是相关的思想,但不是同一个定理。下一章讨论人类专长研究中的「刻意练习」:练习的量与质,各能解释多少差别。
参考文献
Fan, Y. (2026). The 85% Rule for Optimal Learning, Myelination Kinetics and Deliberate Practice: From Stochastic Gradient Descent and the Zone of Proximal Development to Spaced Repetition, Read Beside Classical Chinese Learning Theory [学习的85%最优错误率定律、髓鞘化动力学与刻意练习] (Version 1.0.0). 5D Library. https://doi.org/10.5281/zenodo.23761339 · Licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0).