多任务学习方法

  最近一直在做多任务,但是效果好象没什么提升,因为都是凭自己的想法和感觉在做。于是上网查找了一些这方面的资料,寻求一些理论上的支撑和前人经验上的帮助。

多任务学习:

  故名思意,就是多个任务一起学习。为什么要进行多任务学习呢?因为现实中样本采样的成本较高,而训练样本不足常常会出现过拟合的现象,而将多个相关任务同时学习,通过共享某个共同的知识可以提高各任务的泛化效果

分类:

在这里插入图片描述
  基于软共享的深度多任务学习在这里插入图片描述
  基于硬共享的深度多任务学习
在这里插入图片描述

一些问题:

1、损失的整合

  为多个任务定义一个损失函数,若将每个任务的损失进行简单相加,由于不同任务的收敛速度不同,可能某一任务的收敛得到不错的效果,而其他任务表现却很差。
  简单的解决办法是将简单相加变为加权相加,但这样会不时进行调参。
  论文《Multi-Task Learning Using Uncertainty to Weigh Losses for Scene Geometry and Semantics》,提出引入不确定性来确定损失的权重:在每个任务的损失函数中学习另一个噪声参数(noise parameter)。此方法可以接受多任务(可以是回归和分类),并统一所有损失的尺度。这样就能像一开始那样,直接相加得到总损失了。该方法不仅可以得到很好的结果而且不需要考虑额外的权重超参数。

2、调节学习速率
  学习速率是最重要的超参数之一。我们发现,任务 A 和任务 B 各自合适的速率可能是不同的。这时,我们可以在各个任务的子网络(基于硬共享的深度多任务学习)分别调节各自的学习速率,而在共享网络部分,使用另一个学习速率。
  虽然听上去很复杂,但其实非常简单。通常,在利用 TensorFlow 训练神经网络时,使用的是:

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

  AdamOptimizer 定义如何应用梯度,而 minimize 则完成具体的计算和应用。我们可以将 minimize 替换为我们自己的实现方案,在应用梯度时,为计算图中的各变量使用各自适合的学习速率。

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)  

注:这个技巧其实在单任务网络中也很实用

3、将估计作为特征
  当完成第一阶段的工作,为预测多任务创建好神经网络后,我们可能希望将某一个任务得到的估计(estimate)作为另一个任务的特征。在前向传递(forward-pass)中,这非常简单。但在反向传播中呢?
  假设将任务 A 的估计作为特征输入给 B,我们可能并不希望将梯度从任务 B 传回任务 A,因为我们已经有了任务 A 的标签。对此,TensorFlow 的 API 所提供的 tf.stop_gradient 会有所帮助。在计算梯度时,它允许你传入一个希望作为常数的张量列表,这正是我们所需要的。

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

不止如此,该技术可用在任何你希望利用 TensorFlow 计算某个值并将其作为常数的场景。

我的一些想法:

关于多个任务的训练,应该也可以不统一成一个损失函数,各个任务拥有自己的损失函数即可。
这样可以分别找到适合各个任务的学习速率,和迭代次数,然后进行次数不同迭代即可。
比如:
任务A需要迭代100次才收敛:optimizer1 = tf.train.AdamOptimizer(learning_rate1).minimize(loss1)
任务B需要迭代10次收敛:optimizer2 = tf.train.AdamOptimizer(learning_rate2).minimize(loss2)

# 训练:
for epoch in range(100):
    # Task A
    sess.run([optimizer1], feed_dict1)
    # Task B
    if epoch % 10 == 0:
        sess.run([optimizer2], feed_dict2)

【当然这部分只是我的想法啦!没什么科学依据】

参考资料:

什么是多任务学习
深度神经网络中的多任务学习汇总
关于深度多任务学习的 3 点经验

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值