zoukankan      html  css  js  c++  java
  • Multi-task Learning中的tips

    整合损失函数

    MTL模型中的第一个挑战: 如何为multiple tasks定义一个统一的损失函数?最简单的办法,我们可以整合不同tasks的loss function,然后简单求和。这种方法存在一些不足,比如当模型收敛时,有一些task的表现比较好,而另外一些task的表现却惨不忍睹。其背后的原因是不同的损失函数具有不同的尺度,某些损失函数的尺度较大,从而影响了尺度较小的损失函数发挥作用。这个问题的解决方案是把多任务损失函数“简单求和”替换为“加权求和”。加权可以使得每个损失函数的尺度一致,但也带来了新的问题:加权的超参难以确定。

     

    幸运的是,有一篇论文《Multi-Task Learning Using Uncertainty to Weigh Losses for Scene Geometry and Semantics》通过“不确定性(uncertainty)”来调整损失函数中的加权超参,使得每个任务中的损失函数具有相似的尺度。该算法的keras版本实现,详见github

    调整学习率 learning rate

    在神经网络的参数中,learning rate是一个非常重要的参数。在实践过程中,我们发现某一个learnig rate=0.001能够把任务A学习好,而另外一个learning rate=0.1能够把任务B学好。选择较大的learning rate会导致某个任务上出现dying relu;而较小的learning rate会使得某些任务上模型收敛速度过慢。怎么解决这个问题呢?对于不同的task,我们可以采用不同的learning rate。这听上去很复杂,其实非常简单。通常来说,训练一个神经网络的tensorflow代码如下:

    optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss)

    其中AdamOptimizer定义了梯度下降的方式,minimize则计算梯度并最小化损失函数。我们可以通过自定义一个minimize函数来对某个任务的变量设置合适的learning rate。

    all_variables = shared_vars + a_vars + b_vars
    all_gradients = tf.gradients(loss, all_variables)
    
    shared_subnet_gradients = all_gradients[:len(shared_vars)]
    a_gradients = all_gradients[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_shared_op = shared_subnet_optimizer.apply_gradients(zip(shared_subnet_gradients, shared_vars))
    train_a_op = a_optimizer.apply_gradients(zip(a_gradients, a_vars))
    train_b_op = b_optimizer.apply_gradients(zip(b_gradients, b_vars))
    
    train_op = tf.group(train_shared_op, train_a_op, train_b_op)

    这样的trick在单任务的神经网络上效果也是很好的。

    任务A的评估作为其他任务的特征

    当我们构建了一个MTL的神经网络时,该模型对于任务A的估计可以作为任务B的一个特征。在前向传播时,这个过程非常简单,因为模型对于A的估计就是一个tensor,可以简单的将这个tensor作为另一个任务的输入。但是后向传播时不太一样。因为我们不希望任务B的梯度传给任务A。Tensorflow提供了一个API tf.stop_gradient。当计算梯度时,可以将某些tensor看成是constant常数,而非变量,从而使得其值不受梯度影响。代码如下:

    all_gradients = tf.gradients(loss, all_variables, stop_gradients=stop_tensors)

    这个trick不仅仅可以在MTL的任务中使用,在很多其他任务中也都发挥着作用。比如,当训练一个GAN模型时,我们不需要将梯度后向传播到对抗样本的生成过程中。

    参考 1

  • 相关阅读:
    ffserver搭建服务器
    socketconnect函数详解
    ffmpeg 发送媒体流
    Android—Socket编程
    流媒体客户端的结构与原理浅析
    杭电分类:大数
    各种计时函数
    UVA465:Overflow
    杭电:sort
    CODING常见错误原因
  • 原文地址:https://www.cnblogs.com/shona/p/12654623.html
Copyright © 2011-2022 走看看