Dropout模型迭代1500次后训练Cost变为NaN问题求助
Dropout模型训练迭代中Cost变为NaN问题排查
问题背景
- 参照Andrew-NG深度学习课程1第4周的代码格式实现dropout模型,实验使用课程2第1周的数据集
- 代码运行至1500次迭代时,cost值变为NaN
- 项目包含两个辅助函数文件:
deep_nn.py、dropout_and_regularization.py,主文件为dropout_project.ipynb - 已完成全量代码bug排查,未定位到异常原因
- 实现存疑:dropout逻辑中的d变量是每次迭代动态变化,还是所有迭代固定为常量?当前实现为每次迭代起始处调用
np.random.seed(1)固定d1、d2的取值
核心实现代码
def dropout_model(x, y,keep_probs = 0.86, learning_rate = 0.3, numm_iterations = 30000, print_cost = True): # 14% neurons will be dropped grads = {} costs = [] m = x.shape[1] layer_dims = [x.shape[0], 20, 3,1] parameters = nn.initialize_paraeters_deep(layer_dims) for i in range(numm_iterations): np.random.seed(1) aL, caches, d_list = dr.dropout_L_model_forward(x, parameters ,keep_probs) cost = nn.cross_entropy_cost(aL, y) grads = dr.dropout_L_model_backward(aL, y , caches, d_list, keep_probs) parameters = nn.update_parameters(parameters, grads, learning_rate) if i % 1000 == 0: costs.append(cost) if print_cost: print(f'Cost after iteration {i} is {cost}') plt.plot(costs) plt.ylabel("Cost") plt.xlabel("iteration (x1000)") plt.title(f"Learning rate : {learning_rate}") plt.show() return parameters, costs dropout_parameters, dropout_cost = dropout_model(x_train, y_train) _ = nn.predict(x_train, y_train, dropout_parameters) _ = nn.predict(x_test, y_test, dropout_parameters, "Test")
异常表现
训练迭代过程中cost出现NaN错误,异常曲线如下:
根因分析与修复方案
核心错误点
循环内每轮迭代调用np.random.seed(1)是导致问题的直接原因:
- 固定随机种子后,每轮前向传播生成的dropout掩码完全一致,相当于永久固定同一批神经元被丢弃,完全失去dropout随机正则化的作用
- 固定掩码搭配0.3的较高学习率,会让未被掩码覆盖的神经元参数更新步长过大,快速出现参数爆炸,反向传播时梯度溢出,最终计算交叉熵损失时触发
log(0)运算,直接输出NaN
修复方法
直接删除for循环内部的np.random.seed(1)代码即可。如果需要实验结果可复现,将随机种子设置到训练函数最外层、循环开始前的位置即可,禁止每轮迭代重置随机种子。
Dropout掩码d变量的正确逻辑
dropout的掩码d是每轮迭代前向传播时动态随机生成的,不能在所有迭代中固定为常量:
- 训练阶段:每轮前向传播时随机生成当前轮的掩码,将对应神经元输出置0后除以
keep_prob做数值缩放;反向传播时直接复用同一轮前向生成的掩码计算梯度即可 - 推理阶段:不启用dropout,所有神经元全部参与计算,不需要生成掩码
额外排查项
如果删除循环内固定种子的代码后仍出现NaN,可按以下顺序检查:
- 交叉熵损失计算环节增加数值裁剪,将输出层激活值aL裁剪到
[1e-8, 1-1e-8]区间,避免aL等于0或1时log运算出现无穷值 - 适当降低初始学习率,0.3对于搭配dropout的3层网络属于偏高的取值,可先降到0.01验证收敛性,再逐步调优
- 检查反向传播实现:确认d列表的掩码和对应网络层正确匹配,dropout反向传播时已将失活神经元的梯度置0,且梯度值同步除以
keep_prob做缩放
内容的提问来源于stack exchange,提问作者Himanshu Rajput
相关产品推荐
相关产品推荐

