趋近智
为对抗过拟合 (overfitting)并提升神经网络 (neural network)模型在未见数据上的表现,需要应用正则化 (regularization)技术。这包括修改网络训练过程的核心组成部分,具体是损失计算和前向/后向传播,以引入L2正则化和Dropout。
我们将假设你已经设置了一个基本的神经网络结构和训练循环,可能类似于前一章中构建的那个。我们这里的侧重点是添加正则化所需的修改。
L2正则化在损失函数 (loss function)中增加一个基于权重 (weight)平方大小的惩罚项。目标是保持权重较小,防止模型过度依赖任何单个输入特征。
1. 修改损失函数
原始损失函数(例如,交叉熵或均方误差)衡量预测误差。对于L2正则化,我们增加一个惩罚项。新的L2正则化损失 为:
这里:
在你的代码中,计算批次总损失时,你会计算原始损失,然后添加此惩罚项。你需要访问网络中的所有权重矩阵。
# 示例:计算L2正则化成本
# 假设 'parameters' 是一个包含权重矩阵 W1, W2, ... 的字典
# 且 'lambd' 是正则化超参数
# 且 'm' 是批次大小
l2_cost = 0
num_layers = len(parameters) // 2 # 假设参数是 W1, b1, W2, b2, ...
for l in range(1, num_layers + 1):
W = parameters['W' + str(l)]
l2_cost += np.sum(np.square(W))
l2_cost = (lambd / (2 * m)) * l2_cost
total_cost = original_cost + l2_cost
2. 修改梯度计算(反向传播 (backpropagation))
由于损失函数发生了变化,相对于权重的梯度也随之变化。L2惩罚项相对于权重矩阵 的导数是 。在反向传播期间,此项需要添加到每个权重矩阵的原始梯度计算中。
权重的更新规则变为:
因此,在你的反向传播实现中,计算原始梯度 (即 )之后,你只需添加正则化项:
# 示例:反向传播期间修改 W[l] 的梯度计算
# 假设 dW_original 是未正则化时计算的梯度
dW_regularized = dW_original + (lambd / m) * parameters['W' + str(l)]
# 在参数更新步骤中使用 dW_regularized
# parameters['W' + str(l)] = parameters['W' + str(l)] - learning_rate * dW_regularized
请记住,偏置梯度 通常不被正则化,因此它们的计算保持不变。
Dropout的工作方式不同。它不直接改变损失函数 (loss function),而是在训练期间修改网络结构本身。在训练期间的每次前向传播中,Dropout会随机“丢弃”(设为零)一层中一部分神经元的输出。
1. 修改前向传播
在特定层的前向传播期间(通常应用于隐藏层),计算激活(例如,应用ReLU或Tanh之后)之后,你执行以下步骤:
A 形状相同的矩阵 D。此矩阵的每个元素会随机为0(概率为 keep_prob)或1(概率为 1 - keep_prob)。keep_prob 是保持神经元激活的概率。A 与掩码 D 进行元素级乘法。这有效地将一些激活设为零 (A_dropped = A * D)。keep_prob (A_scaled = A_dropped / keep_prob)。这种缩放确保了层在训练期间的期望输出与测试期间(当dropout关闭时)的期望输出保持一致。这种被称为反向Dropout的技术是标准做法。# 示例:在层 l 的前向传播期间应用 dropout
# A_prev 是前一层的激活
# W, b 是当前层的参数
# activation_func 是激活函数(例如,relu)
# keep_prob 是保持神经元激活的概率
Z = np.dot(W, A_prev) + b
A = activation_func(Z) # 激活输出
# 应用 Dropout
D = np.random.rand(A.shape[0], A.shape[1]) < keep_prob # 创建掩码
A = A * D # 应用掩码
A = A / keep_prob # 缩放(反向Dropout)
# 将掩码 D 与 Z 和 A 一起存储在缓存中,用于反向传播
# cache = (..., D, ...)
2. 修改反向传播 (backpropagation)
在反向传播期间,应用Dropout的层的梯度计算需要考虑掩码 D。需要对被丢弃的神经元关闭反向传播的梯度。你只需将相同掩码 D(你在前向传播期间存储在缓存中的)重新应用于激活 dA 在计算梯度 dW、db 和 dA_prev 之前。记住也要用 keep_prob 进行缩放。
# 示例:在层 l 的反向传播期间应用 dropout 掩码
# dA 是损失相对于当前层激活 A 的梯度
# 缓存包含在该层前向传播中使用的掩码 D
# keep_prob 是前向传播中使用的相同概率
# 从缓存中检索掩码
# D = cache[某个索引] # 获取该层使用的掩码
dA = dA * D # 应用前向传播期间使用的掩码
dA = dA / keep_prob # 应用缩放
# 使用修改后的 dA 继续其余的反向传播步骤
# dZ = dA * activation_gradient(Z)
# dW = ...
# db = ...
# dA_prev = ...
重要提示: Dropout应仅在训练期间处于活跃状态。在评估模型或对新数据进行预测时,你必须关闭Dropout。这表示在评估/预测模式的前向传播中,你不应用掩码或缩放。使用反向Dropout使这变得简单,因为你无需在训练后修改权重 (weight)。
你如何判断正则化 (regularization)是否有效?随训练周期监控你的训练和验证损失(以及准确率)。如果没有正则化,你可能会看到训练损失持续降低,而验证损失在某个点后开始增加或停滞。这种差距表明过拟合 (overfitting)。
理想情况下,应用L2正则化或Dropout应:
训练和验证损失在有无正则化情况下的比较。正则化通常会略微增加训练损失,但会降低验证损失,从而减小差距,并显示出更好的泛化能力。
这种实践涉及修改你的网络实现中的特定部分。首先尝试通过调整成本和梯度计算来添加L2正则化。然后,在前向传播期间尝试添加Dropout层,并确保你在反向传播 (backpropagation)期间正确处理它,并在评估期间将其关闭。观察它对你的训练和验证指标的影响,并尝试不同的正则化强度 或 Dropout keep_prob 值。
这部分内容有帮助吗?
© 2026 ApX Machine LearningAI伦理与透明度•