TensorFlow自定义指标函数始终输出0问题求助
问题分析与解决方案
核心问题
你的LSTM模型最后一层是Dense(1, activation='sigmoid'),输出的y_pred形状为(batch_size, 1)。但自定义指标up_profit_metric中使用了tf.argmax(y_pred, axis=-1)——对长度为1的维度取argmax,结果永远是0,导致y_pred_class全为0,后续所有“预测类别为1”的判断条件都无法触发,最终利润总和始终为0。
另外你构造的测试示例中y_pred_example是(3,2)的形状,和模型实际输出形状不匹配,这也是测试正常但训练异常的关键原因。
修复后的指标函数
针对二分类场景(损失用binary crossentropy),应该基于sigmoid输出的阈值判断类别,而非argmax。修改后的代码如下:
def up_profit_metric(y_true, y_pred): # 基于阈值(如0.5)将sigmoid输出转为类别1/0 y_pred_class = tf.cast(y_pred > 0.5, tf.int32) # 挤压维度,从(batch_size,1)转为(batch_size,) y_pred_class = tf.squeeze(y_pred_class, axis=-1) answer = tf.cast(y_true[:, 0], tf.int32) go_high = y_true[:, 1] price_now = y_true[:, 2] perc_inH = y_true[:, 3] q_to_buy = tf.cast(tf.round(1000 / price_now), tf.float32) deal_amt = q_to_buy * price_now # 正样本预测正确的利润计算 condition1 = tf.logical_and(tf.equal(answer, y_pred_class), tf.equal(y_pred_class, 1)) profit1 = deal_amt * go_high / 100 # 正样本预测错误的利润计算 condition2 = tf.logical_and(tf.not_equal(answer, y_pred_class), tf.equal(y_pred_class, 1)) profit2 = deal_amt * perc_inH / 100 # 根据条件选择对应利润值 profit = tf.where(condition1, profit1, tf.where(condition2, profit2, tf.cast(0, dtype=tf.float32))) total_profit = tf.reduce_sum(profit) return total_profit
额外修正点
- 模型编译时的
EarlyStopping监控的val_precision未在metrics中声明,会导致报错,建议改为监控val_up_profit_metric或添加precision指标 fit函数中重复传入了y_tr_h,应修正为:
lstm_up2.fit( X_train_reshaped, y_tr_h, validation_data=(X_val_reshaped, y_val_h), epochs=70, batch_size=24, shuffle=False )
内容的提问来源于stack exchange,提问作者Anton Lyubimov
相关产品推荐
相关产品推荐

