我基于余弦创建了一个自定义损失函数:
def cos_loss(y_true, y_pred): norm_pred = tf.math.l2_normalize(y_pred) dprod = tf.tensordot( a=y_true, b=norm_pred, axes=1 ) return 1 - dprod
然而,使用这个自定义损失函数训练模型时,会出现错误In[0] mismatch In[1] shape: 2 vs. 8: [8,2] [8,2] 0 0
。如果我使用内置的损失函数如分类交叉熵,模型可以无问题地训练。
尽管我的自定义损失函数和分类交叉熵返回的数值类型和形状完全相同。例如,我创建了测试用的y_true
和y_pred
,并通过两者运行:
test_true = np.asarray([1.0, 0.0])test_pred = np.asarray([0.9, 0.2])print(cos_loss(test_true, test_pred))print(tf.keras.losses.categorical_crossentropy(test_true, test_pred))
返回结果如下:
> tf.Tensor(0.023812939816047263, shape=(), dtype=float64) tf.Tensor(0.20067069546215124, shape=(), dtype=float64)
所以两者都返回了包含单个float-64值且无形状的TensorFlow张量。那么,为什么一个有形状不匹配错误而另一个没有,尽管它们的形状输出是相同的呢?谢谢。
回答:
您的损失函数应该能够接受一批预测值和真实值,并返回一批损失值。目前情况并非如此,因为tensordot
使用axis=1
时是矩阵乘法,当您引入批次维度时就会发生维度冲突。
您可以尝试使用以下代码:
def cos_loss(y_true, y_pred): norm_pred = tf.math.l2_normalize(y_pred) dprod = tf.reduce_sum(y_true*norm_pred, axis=-1) return 1 - dprod