Keras Sequential模型适配自定义精度规则的损失函数选型问题
是否需要自定义损失函数
首先你要优先实现自定义评价指标,损失函数可以先试原生MAE能不能满足需求,达不到预期再自定义损失。你初步写的损失函数不能直接用,因为它是不可导的阶跃函数,梯度为0,无法用于梯度下降训练。
第一步:先实现自定义评价指标
你当前代码里用的accuracy是分类任务的准确率,完全不适用于你的回归场景,先把你定义的精度规则写成Keras可调用的指标函数,训练时就能实时查看你关心的精度数值:
import tensorflow as tf def custom_accuracy(y_true, y_pred): # 计算每个特征的差值绝对值 diff = tf.abs(y_true - y_pred) # 单样本所有特征差值都<=10则标记为正确,否则错误 sample_correct = tf.cast(tf.reduce_all(diff <= 10, axis=-1), tf.float32) # 返回全局平均准确率 return tf.reduce_mean(sample_correct)
修改模型编译的metrics参数即可:
self.model.compile(loss='mae', optimizer='adam', metrics=['mse', 'mae', custom_accuracy])
改完先跑一轮训练,看原生MAE损失下,你的自定义精度能不能达到要求。MAE本身就是惩罚预测值和真实值的差值,天然会推动所有特征的差值尽可能缩小,大部分场景下够用。
第二步:如需自定义损失,用可导的平滑版本
如果MAE训练后自定义精度达不到要求,再换自定义损失。核心逻辑是给差值超过10的样本加额外惩罚,同时保证损失可导:
def custom_loss(y_true, y_pred): diff = tf.abs(y_true - y_pred) # 基础损失:所有特征的MAE base_loss = tf.reduce_mean(diff, axis=-1) # 平滑惩罚项:特征差值越超过10,惩罚越高,用softplus替代阶跃保证可导 penalty = tf.reduce_mean(tf.nn.softplus(diff - 10) * 10, axis=-1) # 总损失 = 基础损失 + 惩罚项,惩罚系数10可根据效果调整 return base_loss + penalty
修改编译参数的loss字段即可:
self.model.compile(loss=custom_loss, optimizer='adam', metrics=['mse', 'mae', custom_accuracy])
后续优化建议
- 开启你注释掉的早停策略,把监控指标换成
val_custom_accuracy,模式设为max,自动保存验证集上自定义精度最高的权重:self.earlystopping = callbacks.EarlyStopping(monitor="val_custom_accuracy", mode="max", patience=10, restore_best_weights=True) - 训练时如果出现震荡,可以适当调小Adam的学习率,比如设为1e-4。
- 可以适当调整损失函数里的惩罚系数,系数越大,模型越优先保证所有特征的差值不超过10。
内容的提问来源于stack exchange,提问作者Petar
相关产品推荐
相关产品推荐

