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

2024-04-26 20:58:59 发布

您现在位置:Python中文网/ 问答频道 /正文

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

方法1:创建多个丢失函数(每个输出一个),合并它们(使用tf.reduce_meantf.reduce_sum),然后像这样将其传递给训练操作:

final_loss = tf.reduce_mean(loss1 + loss2)
train_op = tf.train.AdamOptimizer().minimize(final_loss)

方法2:创建多个培训操作,然后按如下方式分组:

train_op1 = tf.train.AdamOptimizer().minimize(loss1)
train_op2 = tf.train.AdamOptimizer().minimize(loss2)
final_train_op = tf.group(train_op1 train_op2)

我的问题是一种方法是否比另一种方法有利?有没有第三种方法我不知道?

谢谢


Tags: 方法reducetftensorflowtrainmeanfinalop
3条回答

这两种方法的区别在tensorflow的多任务学习中得到了很好的证明。

简而言之:

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

方法2: 这将创建两个独立的优化器,称为备用训练。当您为每个输出使用输入特性的子集时,将使用此选项。因此,当输入train_op1的特征子集时,train_op2的子图是未触及的。可以使用不同的输入特性以交替顺序调用每个优化器。

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

我想说一个我认为在以前的回答中没有提到的微妙的观点。

如果您使用类似gradientdescentomoptimizer的操作,这些操作将非常相似。这是因为取梯度是一个线性运算,和的梯度和梯度之和是一样的。

但是,亚当做了一件特别的事:不管你的损失有多大,它都会按你的学习速度来调整梯度。如果你把你的损失乘以1000,它不会影响亚当,因为变化会被标准化。

所以,如果你的两次损失大致相同,那就没什么区别了。如果其中一个比另一个大得多,那么请记住,在最小化之前求和基本上会忽略小的一个,而两个操作将花费相同的努力来最小化两者。

我个人喜欢把它们分开,这样你就可以更好地控制在一个或另一个损失上。例如,如果是多任务学习,并且一个任务比另一个任务更重要,那么两个学习率不同的操作大致可以完成这一任务。

方法1正确的方法,因为只定义一次梯度图(用于计算反向传播)。这样,您就可以使用一个带有单个图形的单个loss函数来对同一个参数进行单个更新(更新会同时考虑这两个损失项)。

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

运算将计算两个不同的损失和两组不同的更新变量。

当更新变量的时刻到来时,您会遇到一个问题: 哪个更新操作首先执行,由第一个图定义的那个还是另一个? 无论如何,你要放弃一个计算,因为一个将覆盖另一个。更新中没有同步,计算的损失也没有关系。

相关问题 更多 >