深度多任务学习 - 3课程学习

发布者

在过去的一年里,我的团队和我一直在研究个性化的用户体验Taboola Feed..我们使用多任务学习(MTL)预测同一组输入特征上的多个关键性能指标(KPI),并在TensorFlow中实现了深度学习(DL)模型。回到我们开始时,MTL似乎比现在更复杂,所以我想分享一些经验教训。

在DL模型中实现MTL有很多帖子(123.)。
在这篇文章中,我将分享一些在神经网络(NN)中实现MTL时需要考虑的具体要点。我还将提出简单的TensorFlow解决方案来克服讨论的问题。

分享是关怀

我们想从基本的方法开始硬参数共享.硬共享意味着我们有一个共享子网,然后是特定于任务的子网。

在Tensorflow中开始使用这种模型的简单方法是使用估算器多个头.因为它看起来与其他的NN架构没有什么不同,你可能会问自己什么会出错?

第1课 - 结合损失

我们在MTL模型中遇到的第一个挑战是为多个任务定义一个单一的损失函数。虽然单个任务具有定义良好的损失函数,但多个任务会产生多个损失。

我们尝试的第一件事只是为了总结不同的损失。很快我们就可以看到,虽然一项任务会聚到良好的结果,但其他任务看起来很糟糕。仔细看看,我们可以很容易地看待原因。损失的尺度如此不同,那么一个任务占主导地位的整体损失,而其他任务的遗失没有机会影响共享层的学习过程。

快速修复正在替换加权总和的损失总和,使所有损失带到大致相同的范围内。但是,此解决方案涉及可能需要在一段时间内调谐的另一个超级计。

幸运的是,我们找到了伟大的论文提出用不确定性来衡量MTL中的损失。它的方法是,通过学习另一个噪声参数在每个任务的损失函数中。这允许有多个任务,可能是回归和分类,并将所有损失以相同的规模。现在我们可以回到简单地计算我们的损失。

我们不仅比加权总和获得了更好的结果,我们可以忘记额外的重量超公数。这里是本文作者提供的凯拉斯实现。

第2课 - 调整学习率

通常,学习率是最重要的超参数之一优化神经网络.所以我们尝试了调整,并找到了一个学习率,看起来非常适合任务A,另一个对任务B的另一个非常适合。选择较高的速率Relu死亡的在其中一个任务中,使用较低的任务时带来了对另一个任务的缓慢收敛。那么我们能做什么呢?我们可以为每个“头”(任务特定的子网)单独调优一个学习率,并为共享子网调优另一个学习率。

虽然听起来很复杂,但实际上很简单。通常当训练一个神经网络在TensorFlow中,你使用类似的东西:

Optimizer = TF.Train.AdamOptimizer(Learning_rate).minimize(丢失)

AdamOptimizer定义如何应用渐变,以及最小化计算并应用它们。我们可以替换最小化在我们自己的实现中,当应用梯度时,将在我们的计算图中为每个变量使用适当的学习速率:

all_variables = shared_vars + a_vars + b_vars all_gradients = tf.gradentes(丢失,all_variables)shared_subnet_gradients = all_gradents [:len(shared_vars)] a_gradients = all_gradentes [len(shared_vars):len(shared_vars + a_vars)] b_gradients = all_gradients [len(shared_vars+ a_vars):] shared_subnet_optimizer = tf.train.adamoptimizer(shared_learning_rate)a_optimizer = tf.train.adamoptimizer(a_learning_rate)b_optimizer = tf.train.adamoptimizer(b_learning_rate)train_opared_op = shared_subnet_optimizer.apply_gradeness(zip(shared_subnet_gradients,shared_vars))train_a_op =a_optimizer.apply_gradents(zip(a_gradients,a_vars))train_b_op = b_optimizer.apply_gradents(zip(b_gradients,b_vars))train_op = tf.group(train_shared_op,train_a_op,train_b_op)

顺便说一下,这个技巧实际上对单任务网络也很有用。

第3课 - 使用估计作为特征

一旦我们通过创建一个预测多个任务的NN的第一个阶段,我们可能希望将我们的估计用作另一个任务作为特征。在正向通行证中真的很容易。估计是一个张量,所以我们可以像任何其他层的输出一样。但是在背面发生了什么?

假设任务A的估计作为任务B传递给特征。我们可能不希望将梯度从任务B返回到任务A,因为我们已经拥有A的标签。
别担心,Tensorflow的API有tf.stop_gradient.只是因为这个原因。计算渐变时,它允许您传递您希望作为常量治疗的张特兰人列表,这正是我们所需要的。

ALL_GRADENTERS = TF.GRADENTERS(丢失,all_variables,stop_gradients = stop_tensors)

同样,这在MTL网络中是有用的,但不仅仅是。只要要使用TensorFlow计算值,可以使用此技术,并且需要假装该值是常量。例如,在训练生成对抗网络(GANs)时,您不希望通过对抗示例的生成过程。

下一个是什么?

我们的模型已启动,运行,Taboola Feed正在个性化。然而,仍有很多改进的空间,以及许多有趣的架构探索。在我们的用例中,预测多个任务还意味着我们根据多个KPI做出决定。这比使用单个KPI可能有点棘手......但这已经是一个全新的主题。

感谢阅读,我希望这篇文章对你有用!

立即启动您的Taboola职业生涯!