如何在TensorFlow中编写自定义损失函数?

47

我刚开始学习 tensorflow,我想编写自己的损失函数。是否有相关的教程?例如,铰链损失或平方和损失(虽然这已经在tf中了)? 我可以直接在Python中完成吗,还是必须编写cpp代码?

5个回答

58

我们需要编写损失函数。例如,我们可以使用基本的均方误差作为预测y和目标y_的损失函数:

 loss_mse = 1/n(Sum((y-y_)^2))

张量的基本函数包括 tf.add(x,y)tf.sub(x,y)tf.square(x)tf.reduce_sum(x)以及等等

然后,我们可以在TensorFlow中定义我们的损失函数,如下:

cost = tf.reduce_mean(tf.square(tf.sub(y,y_)))

注意:y和y_都是张量。
此外,如果我们能够写出方程,我们就可以定义任何其他的损失函数。对于一些训练运算符(最小化器),损失函数应满足一些条件(平滑、可微等)。
TensorFlow将数组、常量、变量定义为张量,使用tf函数定义计算,并使用会话在图中运行。我们可以定义任何我们想要的东西,并在最后运行它。

14

除了其他答案之外,如果损失函数可以表示为现有函数的组合,则可以在Python中编写损失函数。

例如,请查看sigmoid_cross_entropy_with_logits的实现链接,该函数使用基本变换实现。


1
也许这个现有损失函数实现的链接更加合适。 - Causality

11
几乎所有的TensorFlow教程都使用自定义函数。例如,在入门教程中,他们编写了一个自定义函数:

计算当前模型与提供数据之间差值的平方和

squared_deltas = tf.square(linear_model - y)
loss = tf.reduce_sum(squared_deltas)

下一步初学者的MNIST使用交叉熵
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

您可以看到,这并不难:您只需要将函数编码为张量格式并使用它们的基本函数。

例如,以下是如何实现F-beta得分(F1得分的一般方法)。 其公式为:

enter image description here

我们唯一需要做的就是找到如何计算布尔值或0/1值的真正阳性、假阳性和假阴性。如果您有0/1值的向量,可以按照以下方式计算每个值:
TP = tf.count_nonzero(actual, predicted)
FP = tf.count_nonzero((actual - 1) * predicted)
FN = tf.count_nonzero((predicted - 1) * actual)

现在,一旦您知道这些值,就可以轻松获得您的
denom = (1 + b**2) * TP + b**2 TN + FP
Fb = (1 + b**2) * TP / denom

4
很遗憾,你的F-beta分数实现存在多个问题:
  • 第一行应该是: TP = tf.count_nonzero(actual * predicted)
  • denom = (1 + b**2) * TP + b**2 FN + FP
  • 然而,这里的主要问题是该实现不能用作自定义损失函数,因为没有办法计算梯度。例如,没有线性的方法来确定“predicted”值。
- Johnson_145
解决梯度问题的一种方法是通过使用预测概率来计算TP、FP和FN,如Scherzinger等人所述 - Johnson_145
这也是奇怪的,因为F-beta分数是一种度量指标而不是损失函数,你试图最大化它,而不是最小化它,所以我觉得损失函数的例子不足以说明问题。 - J Agustin Barrachina

6
def focal_loss(y_true, y_pred):
  pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred))
  pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred))
  custom_loss=kb.square((pt_1-pt_0)/10)
  return custom_loss    

model.compile(loss=focal_loss,
          optimizer='adam',
          metrics=['accuracy'])

5

我使用Kullbak-Leibler距离实现了自定义损失函数,其中p=常数。我将其应用于自编码器中。

rho = 0.05

class loss_with_KLD(losses.Loss):
    
    def __init__(self, rho):
        super(loss_with_KLD, self).__init__()
        self.rho = rho
        self.kl = losses.KLDivergence()
        self.mse = losses.MeanSquaredError(reduction=tf.keras.losses.Reduction.SUM)
        
    def call(self, y_true, y_pred):
        mse = self.mse(y_true, y_pred)
        kl = self.kl(self.rho, y_pred)
        return mse + kl

也许对任何人都有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接