Tensorflow:多个损失函数与多个训练操作

Ank*_*dal 15 python tensorflow

我正在创建一个Tensorflow模型,它预测多个输出(具有不同的激活).我认为有两种方法可以做到这一点:

方法1:创建多个损失函数(每个输出一个),合并它们(使用tf.reduce_meantf.reduce_sum)并将其传递给训练操作,如下所示:

final_loss = tf.reduce_mean(loss1 + loss2)
train_op = tf.train.AdamOptimizer().minimize(final_loss)
Run Code Online (Sandbox Code Playgroud)

方法2:创建多个训练操作,然后将它们分组如下:

train_op1 = tf.train.AdamOptimizer().minimize(loss1)
train_op2 = tf.train.AdamOptimizer().minimize(loss2)
final_train_op = tf.group(train_op1 train_op2)
Run Code Online (Sandbox Code Playgroud)

我的问题是一种方法是否优于另一种方法?还有第三种方法我不知道吗?

谢谢

khu*_*834 12

这篇关于张量流中多任务学习的文章清楚地证明了两种方法之间的差异。

简而言之:

方法1:这称为联合训练,因为它直接将损失加在一起,结果是针对两个损失同时进行所有梯度和更新。通常,当使用同一组输入功能训练多个输出时,将使用此功能。

方法2:这将创建两个单独的优化器,称为替代训练。当您为每个输出使用输入功能的子集时,将使用此功能。因此,当输入train_op1的特征子集时,train_op2的子图将保持不变。可以使用不同的输入功能以交替顺序调用每个优化器。

如果您使用相同的输入数据同时运行两个优化器,则与方法1的差异可能很小。


Sam*_*bel 10

我想提出一个微妙的观点,我认为以前的答案中没有提到。

如果您使用的是GradientDescentOptimizer之类的东西,这些操作将非常相似。这是因为采取梯度是线性操作,并且总和的梯度与梯度的总和相同。

但是,ADAM可以做一些特殊的事情:无论损失的大小如何,它都会缩放梯度,以使它们始终与您的学习率保持一致。如果您将损失乘以1000,则不会影响ADAM,因为更改将被归一化。

因此,如果您的两次损失的幅度大致相同,则不会有什么不同。如果一个大于另一个,则请记住,在最小化之前进行求和实际上会忽略较小的一个,而进行两个操作会花费相同的精力来最小化两者。

我个人喜欢将它们分成几部分,这使您可以更好地控制将精力集中在一种损失或另一种损失上。例如,如果这是多任务学习,并且一项任务比另一项任务更重要,那么具有不同学习率的两名操作员就可以大致完成此任务。

  • 感谢您指出这个微妙但重要的细节。当我阅读您的描述时,我立即想到的一个问题是:有什么好方法可以纠正两个幅度明显不同的损失?我的想法是:输入标准化或记录损失项。 (4认同)

nes*_*uno 5

该方法1 正确的,因为你只限定一旦梯度曲线(用于计算后向传播)之一。这样,您可以对单个图形使用单个损失函数,以对同一参数进行单个更新(更新同时考虑了损失的两个方面)。

相反,第二种方法定义了2个不同的图来计算梯度,这是错误的。执行训练操作时,您将并行执行训练操作(因为使用了tf.group/ tf.tuple/ tf.control_dependencies)。

这些操作将计算两个不同的损失和两个不同的更新变量集。

当更新变量的时刻到来时,您会遇到一个问题:哪个更新操作首先执行,哪个由第一个图形定义,或者另一个?在任何情况下,您都将丢弃一个计算,因为一个计算将覆盖另一个计算。更新中没有同步,计算的损失中也没有关系。

  • 这是一个错误的答案。tf.group不会创建两个独立的图。它不会忽略一个梯度更新。渐变更新是通过Assign_add进行的。并行运行它们将添加它们两者。 (2认同)
  • 在方法2中,两者都是并行执行的。最后一个结束将覆盖第一个所做的更新。您不能保证执行顺序。 (2认同)