Keras中自定义“差异度量”损失函数的定义问题排查
排查你的自定义损失函数问题
首先,我们先明确Malhotra论文里损失函数的计算逻辑:对于每个包含L个时间步的样本X,损失是每个时间步的真实向量x(i)与重构向量x'(i)的L2范数平方之和,之后在整个训练集上做平均(Keras默认会对batch内的损失取平均,所以我们只需要正确计算单个样本的损失即可)。
接下来看你写的mirror_loss函数,这里确实存在几个关键问题:
1. 范数计算的维度错误
你用了tf.norm(..., axis=1),这里的axis=1指定的是时间步维度,这会把每个样本的所有时间步的特征向量拼接起来计算整体范数,完全不符合论文中“对每个时间步的特征向量单独计算范数”的要求。正确的做法应该是对特征维度计算范数,也就是axis=-1(假设你的输入shape是(batch_size, timesteps, feature_dim),-1指向最后一个维度即特征维度)。
2. 没必要混用TensorFlow和Keras后端
Keras后端其实完全可以实现这个计算,混用两者虽然不一定报错,但可能带来兼容性问题,也没必要。而且我们可以直接计算平方差的和,这和“计算L2范数再平方”是等价的,还能减少计算步骤。
修正后的损失函数
这里给你两种版本的修正代码,推荐使用纯Keras后端的版本:
纯Keras后端实现
import keras.backend as K def mirror_loss(y_true, y_pred): # 计算每个时间步下,真实与重构向量的平方差之和(等价于L2范数的平方) per_timestep_loss = K.sum(K.square(y_true - y_pred), axis=-1) # 对单个样本的所有时间步损失求和,得到单个样本的损失 return K.sum(per_timestep_loss, axis=1)
如果你偏好使用TensorFlow实现(修正维度后)
import tensorflow as tf import keras.backend as K def mirror_loss(y_true, y_pred): # 修正axis为-1,针对特征维度计算范数 diff = tf.square(tf.norm(tf.subtract(y_true, y_pred), axis=-1)) # 对时间步维度求和,得到单个样本的损失 return K.sum(diff, axis=1)
额外注意点
请确认你的y_true和y_pred的维度完全匹配,比如都是(batch_size, timesteps, feature_dim)。如果维度不对应,损失计算也会出现异常。
内容的提问来源于stack exchange,提问作者Irribarra Cristián
相关产品推荐
相关产品推荐

