Keras自定义损失函数报错InvalidArgumentError:输入需为标量但形状为[64]
问题原因
你遇到的报错核心是tf.cond仅支持标量布尔值作为判断条件,而你传入的判断条件是对应整批样本的布尔张量(shape为[64],和你的batch size一致),不符合输入要求。前两次调用成功是eager模式下的测试调用,进入图模式执行训练时就会触发校验报错。
修复方案
将损失函数中逐样本判断的逻辑从tf.cond替换为支持逐元素判断的tf.where,同时调整MSE损失的降维策略,适配逐样本加权的需求。
修改后的自定义损失函数
def custom_loss(y_true, y_pred): # 设置MSE不做全局降维,保留逐样本的损失值 mse = tf.keras.losses.MeanSquaredError(reduction=tf.keras.losses.Reduction.NONE) penalty = 10 # 逐样本判断真实值与预测值符号是否相反 sign_opposite = tf.logical_or( tf.logical_and(tf.greater(y_true, 0.0), tf.less(y_pred, 0.0)), tf.logical_and(tf.less(y_true, 0.0), tf.greater(y_pred, 0.0)) ) # 符号相反样本应用高惩罚,其余应用低惩罚 base_loss = mse(y_true, y_pred) loss = tf.where(sign_opposite, base_loss * penalty, base_loss * penalty / 4) # 逐样本判断预测值是否超出真实值幅值 exceed_amplitude = tf.logical_or( tf.logical_and(tf.greater(y_true, 0.0), tf.greater(y_pred, y_true)), tf.logical_and(tf.less(y_true, 0.0), tf.less(y_pred, y_true)) ) # 超出幅值样本额外加惩罚 loss = tf.where(exceed_amplitude, loss * penalty / 5, loss * penalty / 10) # 对整批损失求平均返回标量,适配模型训练要求 return tf.reduce_mean(loss)
其他需要修正的代码问题
- 原代码中
MODEL_NAME的f字符串缺少右括号,修正为:MODEL_NAME = f"MODEL 01-{str(int(time.time()))}" - ModelCheckpoint的
mode参数设置错误,你监控的是均方误差(值越小模型效果越好),需要将mode='max'修改为mode='min',否则会错误保存误差更大的模型。
内容的提问来源于stack exchange,提问作者iKey
相关产品推荐
相关产品推荐

