开始前,会这些就够了
- 知道平均值和最大值的区别
- 知道动作价值是未来收益的估计
- 先读 MDP、Bellman 与策略梯度:先认识动作价值与 Bellman 更新,再理解最大估值为什么会被用于下一步学习。
两个动作的真实收益都为零。估计器对每个动作有时多报一分、有时少报一分,平均下来恰好正确。现在每次只挑报得最高的那个,最后的平均估值还是零吗?
答案是零点五。不是每个动作的估计器本身偷偷加了分,而是“挑最高”更容易挑中向上偏的误差。本篇用全部情况枚举,展示把选择和评价拆开后,哪些偏差消失,哪些问题仍在。
把例子带到自己的电脑上
下载完整练习包
需要 Python 3.10 或更新版本,无第三方依赖;实测 Windows / Python 3.14.0,Python 3.10 仅做语法兼容检查。使用标准库,不需要安装第三方包。下载 ZIP 后选择“全部提取”,进入能看到 README.md 的文件夹。
下载 ZIP · 5 个文件包里有什么
- demo.py:完整可运行源码
- README.md:运行步骤与练习
- observed.stdout.txt:本次实际输出
- verification.json:源码和运行验证记录
- SHA256SUMS.txt:文件摘要
在这个文件夹打开 PowerShell,逐行运行
python --version
python -B demo.py解压后,在含 demo.py 的目录打开终端。命令分别回车执行。独立有限噪声下的单次价值估计枚举;未实现或训练完整 Q-learning、Double Q-learning 或 Double DQN。
找不到命令或文件时,先按 README 检查环境和所在目录。文中标出的阅读时间只估算文章篇幅,安装环境和动手练习可按自己的节奏进行。
同一张表挑最大值,再用另一张表估价
正在准备实验控件…
两项真值是 (0,v)。每项误差等概率取 ±1,枚举所有离散组合;并列固定选第 0 项。独立 B 与 A 拷贝是两种教学假设,真实 Double Q 训练并不自动保证两张估计表完全独立。
把误差模型写清楚
先固定一个状态和两个动作,真实价值为 [0,0]。估值表 A 对每个动作分别加 −1 或 +1,四种组合等可能,动作之间的误差独立。
四张表依次是 [−1,−1]、[−1,+1]、[+1,−1]、[+1,+1]。对任意一个固定动作取平均,估值都是零,因此这里称每个动作估计无偏。
“无偏”说的是把这种实验重复许多次时的期望,不是每次都准确。本篇会直接枚举全部组合,不使用随机种子或有限次抽样来近似。
先取最大值,再平均,顺序不能交换
四张表各自的最大值是 −1、+1、+1、+1,平均为 0.5;真实价值先取最大则为零。E[max A] 与 max E[A] 不是一个运算。
直觉上,一次向下估错可能被另一个动作盖过去;只要有动作向上估错,它就更容易被选中。我们对“最高分”附带了一次偏爱正误差的筛选。
在 Q-learning 中,更新目标通常包含 r+gamma×max_a Q(s_next,a)。如果把带误差的估值直接放进这个最大值,偏差就可能进入后续学习。这里仅隔离其中的估计步骤,不运行完整的学习循环。
A 负责选,B 负责给选中动作打分
再造一张 B 表。B 的每个误差也独立取 −1 或 +1,并且整张 B 与 A 独立。先令 a*=argmax A,再读取 B[a*];不要在 B 里重新挑最大值。并列时固定选索引较小的动作。
四张 A 与四张 B 两两组合,一共十六种等可能情况。选中动作虽然受 A 的误差影响,但 B 没参与这次选择;在本例条件下,B 对选中动作仍平均给零。因此交叉评价的平均为零。
这个结论依赖 B 在给定选择结果后仍能无偏评价该动作。独立的无偏 B 是一个充分条件;把 A 复制成 B 不满足它。代码也验证复制后平均仍是 0.5。
真值不同,仍可能选错动作并低估
把真实价值改为 [0,1],保留同样独立的 ±1 误差。A 的四张表变成 [−1,0]、[−1,2]、[1,0]、[1,2]。第三张会误选真实价值为零的动作。
最大值法平均报 1.25,高于真正最大值 1;交叉评价平均报 0.75,低于 1。B 无偏地评价了“被选中的动作”,并不表示 A 一定选中了真正最好的动作。
一般说,在这些独立无偏假设下,交叉评价的期望是被选动作真实价值的加权平均。只有选到的动作都具有最大真实价值时,它才等于最大值;否则可以低估。
偏差变小,不保证每次误差更小
回到真值 [0,0]。最大值法有 0.5 的偏差,交叉评价偏差为零,但两者本例的均方误差都是 1。均方误差就是每次误差平方后再平均。
这说明“减少偏差”和“保证更小总误差”是两个不同命题。交叉评价可以改变方差,不能只展示均值更准,就宣称所有误差指标都变好。
Double DQN 把这一思路用于神经网络:在线网络选择动作,目标网络评价该动作。目标网络会周期性从在线网络复制参数,因此两者并不满足本篇完全独立的人工设定;不能把本例的零偏差原样套过去。
用精确分数枚举,不靠碰运气
保存为 demo.py,运行 python demo.py。只需要 Python 3.14 标准库。Fraction 让均值与断言使用精确分数,最后打印时才转成六位小数。
十个条件覆盖单个估计器无偏、并列选择、最大值高估、独立评价、复制反例、低估与均方误差。实验没有经验回放、环境交互、神经网络或训练收敛测试。
展开收起代码 · 小实验
长行可在代码区域内左右滚动,按 Tab 可把焦点移入代码区。
"""Enumerate finite estimator noise; this is not a Q-learning training loop."""
from fractions import Fraction
from itertools import product
def estimates(truth):
return [tuple(value + error for value, error in zip(truth, errors))
for errors in product((-1, 1), repeat=len(truth))]
def first_argmax(values):
return max(range(len(values)), key=values.__getitem__)
def average(values):
return sum(values, Fraction(0)) / len(values)
def evaluate(truth):
tables = estimates(truth)
target = max(truth)
single = [max(a) for a in tables]
# Every A table is paired with every independently generated B table.
double = [b[first_argmax(a)] for a in tables for b in tables]
copied = [a[first_argmax(a)] for a in tables]
return {
"truth": target,
"single": average(single),
"double": average(double),
"copied": average(copied),
"single_mse": average([(x - target) ** 2 for x in single]),
"double_mse": average([(x - target) ** 2 for x in double]),
}
def main():
equal = evaluate((0, 0))
unequal = evaluate((0, 1))
tables = estimates((0, 0))
checks = {
"four_equiprobable_A_tables": len(tables) == 4,
"each_estimator_unbiased": all(average([a[i] for a in tables]) == 0 for i in range(2)),
"tie_breaks_toward_first": first_argmax((1, 1)) == 0,
"max_has_positive_bias": equal["single"] == Fraction(1, 2),
"independent_equal_value_evaluation_unbiased": equal["double"] == 0,
"copied_table_keeps_bias": equal["copied"] == equal["single"],
"single_mse_one": equal["single_mse"] == 1,
"double_mse_not_lower_here": equal["double_mse"] == equal["single_mse"],
"unequal_single_overestimates": unequal["single"] == Fraction(5, 4),
"unequal_double_underestimates": unequal["double"] == Fraction(3, 4),
}
assert all(checks.values()), checks
print("noise=independent +/-1; tie=first action; exact enumeration")
print("A tables=4; independent A/B pairs=16")
for truth, result in (((0, 0), equal), ((0, 1), unequal)):
print(f"true_values={truth} true_max={result['truth']}")
print(f" single_mean={float(result['single']):.6f} double_mean={float(result['double']):.6f} copied_B_mean={float(result['copied']):.6f}")
print(f" single_bias={float(result['single'] - result['truth']):.6f} double_bias={float(result['double'] - result['truth']):.6f}")
print(f"equal_values_MSE: single={float(equal['single_mse']):.6f} double={float(equal['double_mse']):.6f}")
print(f"PASS {len(checks)} checks; estimator experiment only, no RL training")
if __name__ == "__main__":
main()
怎样运行:在独立练习文件夹中,依次执行下载区的命令。2026-10-23 使用 Python 3.10 或更新版本,无第三方依赖;实测 Windows / Python 3.14.0,Python 3.10 仅做语法兼容检查 复跑这份源码并核对完整输出。独立有限噪声下的单次价值估计枚举;未实现或训练完整 Q-learning、Double Q-learning 或 Double DQN。
运行后对照结果
noise=independent +/-1; tie=first action; exact enumeration
A tables=4; independent A/B pairs=16
true_values=(0, 0) true_max=0
single_mean=0.500000 double_mean=0.000000 copied_B_mean=0.500000
single_bias=0.500000 double_bias=0.000000
true_values=(0, 1) true_max=1
single_mean=1.250000 double_mean=0.750000 copied_B_mean=1.250000
single_bias=0.250000 double_bias=-0.250000
equal_values_MSE: single=1.000000 double=1.000000
PASS 10 checks; estimator experiment only, no RL training
真正该核对的是谁选、谁评、误差怎样相关
读实现时先把动作索引 a* 和被读取的估值分开。max B、B[argmax A]、(A+B)/2 都是不同运算,不能因为出现了两张表就都叫同一算法。
本例刻意给出独立、等概率、零均值误差,便于证明。真实训练中的两个网络可能共享数据、参数来源和系统性误差,Double Q 也不保证永远无偏、永远不低估,或每次选对动作。
要验证实际算法,应另外报告估值误差、实际回报及训练稳定性。本篇只证明这个有限模型里选择与评价复用误差会发生什么,为理解真实算法提供一个可核验的局部环节。
记住这三点
- 每个动作的估计无偏,不代表最大估计值无偏。
- B[argmax A] 将选择和评价分开;复制 A 并不会产生独立评价。
- 交叉评价仍可能因选错动作而低估,减少偏差也不保证降低均方误差。
别把例子用过头
- 把 E[max A] 写成 max E[A]。
- 在 B 中再做一次 argmax,误以为实现了交叉评价。
- 把目标网络当成与在线网络完全独立的估计器。
- 只看平均估值更接近真值,就承诺所有训练任务都获益。
自己试一小步
把真实价值改为 [0,3],仍使用 ±1 误差,交叉评价的均值和偏差会怎样?
- 先写出四张 A 表,标出每次选到的动作。
- 列出十六组独立 A
/B组合,分别计算最大值法与交叉评价。 - 再把 B 改成 A 的副本,比较这个新例子是否仍能显示相关误差的危害。
做到这些,就算完成
- 固定并记录并列规则。
- 分别计算偏差与均方误差。
- 解释结果依赖真实动作差距和误差幅度,而非仅依赖是否有两张表。
查原始资料
想确认一个细节,先看这份资料对应的部分,不必从头读完所有文档。
- Double Q-learning:单估计器与双估计器 (新标签页)↗
第 2.1、2.2 节说明最大值偏差、独立评价和可能的低估;第 3 节连接 Q-learning。
- Deep Reinforcement Learning with Double Q-learning (新标签页)↗
Double DQN 使用在线网络选择动作、目标网络评价动作,且两者并非完全独立。
- On the Estimation Bias in Double Q-Learning (新标签页)↗
摘要、第 2、3 节讨论近似误差下 Double Q 仍可能低估,不能视作彻底无偏保证。