TensorFlow2.1.3下用Functional API构建LSTM出现predictions>=0报错
问题排查与解决方案
问题现象
代码运行到第5个Epoch前完全正常,先出现val_prc指标缺失的警告,随后出现输出层预测值为NaN的报错。
警告信息
WARNING:tensorflow:Early stopping conditioned on metric `val_prc` which is not available. Available metrics are: loss,tp,fp,tn,fn,accuracy,precision,recall,auc,prc WARNING:tensorflow:Can save best model only with val_prc available, skipping.
报错信息
InvalidArgumentError: assertion failed: [predictions must be >= 0] [Condition x >= y did not hold element-wise:] [x (model/output_layer/Sigmoid:0) = ] [[-nan][-nan][-nan]...] [y (metrics/tp/Cast_2/x:0) = ] [0] [[{{node metrics/tp/assert_greater_equal/Assert/AssertGuard/else/_270/Assert}}]] [Op:__inference_distributed_function_19774] Function call stack: distributed_function
根因定位
- val_prc指标缺失:你在fit方法中硬编码了
validation_steps=190,如果验证集总样本数/批次大小的结果小于190,验证步骤没有完整执行,就不会生成val_前缀的验证集指标。 - 输出层NaN报错:Sigmoid激活的输出出现NaN本质是梯度爆炸,你在
time_layer2的LSTM层使用了relu作为激活函数,LSTM循环结构搭配relu非常容易出现梯度爆炸,反向传播过程中权重更新过大,最终导致前向传播输出NaN。 - 其他潜在诱因:类别权重设置过大、初始偏置计算异常、学习率偏高都可能加重梯度爆炸问题。
修复方案
- 移除fit方法中的
validation_steps=190参数,让TensorFlow自动遍历全量验证集计算指标,也可以手动计算正确的验证步数:validation_steps = np.ceil( len(x_valid)/32 )后传入。 - 将
time_layer2层的LSTM激活函数从relu改为tanh,和其他LSTM层保持一致,避免梯度爆炸:layer22 = LSTM(64,activation="tanh", return_sequences=False, name="time_layer2")(layer21_dropout) - 检查
class_weights的数值,避免类别权重比值超过1000,如果样本极不均衡,可以适当下调权重比值,同时给LSTM层增加L2正则化:layer22 = LSTM(64,activation="tanh", return_sequences=False, name="time_layer2", kernel_regularizer=tf.keras.regularizers.l2(1e-5), recurrent_regularizer=tf.keras.regularizers.l2(1e-5))(layer21_dropout) - 确认初始偏置计算正常:
pos和neg都不能为0,避免initial_bias出现无穷大的异常值。 - 可以将学习率从1e-4下调到5e-5,进一步降低梯度爆炸的风险。
内容的提问来源于stack exchange,提问作者Spandyie
相关产品推荐
相关产品推荐

