将经过Dropout训练的模型应用于对新数据进行预测(推断或测试时),涉及一些特定的考量。在训练期间,Dropout通过以概率 $p$ 将神经元激活值设为零来引入随机性。这意味着,平均而言,层中只有 $(1-p)$ 比例的神经元对传递到下一层的输出有贡献。因此,与不使用Dropout运行网络相比,前向传播的激活值整体大小或比例会减小。然而,在测试时,我们希望模型是确定性的。相同的输入通过网络应始终产生相同的输出。在推断期间随机丢弃神经元会违背这一点。因此,在测试时,我们使用整个网络——所有神经元都处于激活状态。但现在存在不匹配的情况:网络是使用由于Dropout而平均规模较小的激活值进行训练的。如果我们在测试期间突然以全强度使用所有神经元,传递给后续层的激活值将明显变大,超过网络在训练期间所遇到的情况。这种规模差异可能导致性能不佳,因为网络未针对这些较大的值进行校准。调整方案为了解决这一差异,我们需要确保神经元在测试时的预期输出与训练时的预期输出一致。设 $a$ 为神经元的输出激活值。在训练期间,该神经元以 $(1-p)$ 的概率处于激活状态。因此,它对下一层的预期贡献是 $(1-p) \times a$。在测试时,神经元始终处于激活状态,产生输出 $a$。为了使测试时的输出规模与预期的训练时规模一致,我们只需将测试时的激活值按相同因子 $(1-p)$ 进行调整:$$ a_{\text{测试}} = a_{\text{训练}} \times (1-p) $$通过在推断期间将Dropout层中所有神经元的激活值乘以保留概率 $(1-p)$,我们确保下一层的输入规模与训练期间平均观察到的情况保持一致。示例:调整的视觉表示设想一个具有四个神经元的小层,丢弃概率为 $p=0.5$ (即保留概率为 $1-p=0.5$)。digraph G { rankdir=LR; node [shape=circle, style=filled, fillcolor="#a5d8ff"]; splines=false; edge [color="#495057"]; subgraph cluster_train { label="训练阶段 (p=0.5)"; color="#adb5bd"; style=dashed; fontcolor="#495057"; a1 [label="x1"]; a2 [label="x2", fillcolor="#dee2e6", fontcolor="#868e96"]; a3 [label="x3"]; a4 [label="x4", fillcolor="#dee2e6", fontcolor="#868e96"]; {rank=same; a1 a2 a3 a4} } subgraph cluster_test { label="测试阶段 (调整)"; color="#adb5bd"; style=dashed; fontcolor="#495057"; b1 [label="0.5*x1"]; b2 [label="0.5*x2"]; b3 [label="0.5*x3"]; b4 [label="0.5*x4"]; {rank=same; b1 b2 b3 b4} } y_train [label="下一\n层", shape=box, style=filled, fillcolor="#ced4da"]; y_test [label="下一\n层", shape=box, style=filled, fillcolor="#ced4da"]; a1 -> y_train [label=" 激活"]; a3 -> y_train [label=" 激活"]; {b1, b2, b3, b4} -> y_test [label=" 已调整"]; }在训练期间 (左侧),随机一部分神经元被停用 (显示为灰色)。预期输出值减小。在测试时 (右侧),所有神经元都处于激活状态,但其输出会按保留概率 $(1-p)$ 进行调整,以使其规模与训练期间所见的预期规模一致,然后再传递给下一层。这一调整步骤对于Dropout的正确运行非常重要。没有它,网络的行为在训练和测试阶段之间会明显不同。实现上的说明在测试阶段执行此调整操作是正确实现Dropout的一种方式。然而,这意味着推断代码需要了解训练期间使用的丢弃概率,并执行这个额外的乘法步骤。一种常见的替代方法,称为“倒置Dropout”,则是在训练阶段进行调整。这使得测试阶段更简单,因为届时不需要调整。我们将在下一节讨论倒置Dropout,因为它是大多数深度学习框架中的标准实现方式。然而,了解测试时调整的要求,提供了为什么调整(无论是在训练还是测试时)是必要的根本原因。