如何较好地构建多任务学习模型?这里有三点经验

目录

共享即关怀

第一点:整合损失

第二点:调节学习速率

第三点:将估计作为特征

作者的其它文章


现在已经有很多关于利用深度学习模型实现 MTL 的文章。在本文中,我准备分享一些利用神经网络实现 MTL 时需要考虑的具体问题,同时也会展示一些基于 TensorFlow 的简单解决方案。

共享即关怀

我们准备从参数硬共享(hard parameter sharing)的基础方法开始。硬共享表示我们使用一个共享的子网络,下接各个任务特定的子网络。

在 TensorFlow 中,实现这样一个模型的简单方法是使用带有 multi_head 的 Estimator。这个模型和其他神经网络架构相比没什么不同,所以你可以自己想想,有哪些可能出错的地方?

第一点:整合损失

我们的 MTL 模型所遇到的第一个挑战是为多个任务定义一个损失函数。既然每个任务都有一个定义良好的损失函数,那么多任务就会有多个损失。

我们尝试的第一个方法是将不同损失简单相加。很快我们就发现,虽然某一个任务会收敛得到不错的结果,其他的却表现很差。进一步研究后,可以很容易地明白原因:不同任务损失的尺度差异非常大,导致整体损失被某一个任务所主导,最终导致其他任务的损失无法影响网络共享层的学习过程。

一个简单的解决方案是,将损失简单相加替换为加权和,以使所有任务损失的尺度接近。但是,这引入了另一个可能需要不时进行调节的超参数。

幸运的是,我们发现了一篇非常棒的论文《Multi-Task Learning Using Uncertainty to Weigh Losses for Scene Geometry and Semantics》,提出引入不确定性来确定 MTL 中损失的权重:在每个任务的损失函数中学习另一个噪声参数(noise parameter)。此方法可以接受多任务(可以是回归和分类),并统一所有损失的尺度。这样,我们就能像一开始那样,直接相加得到总损失了。

与损失加权求和相比,该方法不仅得到了更好的结果,而且还可以不再理会额外的权重超参数。论文作者提供的 Keras 实现参见:https://github.com/yaringal/multi-task-learning-example/blob/master/multi-task-learning-example.ipynb

第二点:调节学习速率

调节神经网络有一个通用约定:学习速率是最重要的超参数之一。所以我们尝试调节学习速率。我们发现,对于某一个任务 A 而言,存在一个特别适合的学习速率,而对于另一个任务 B,则有不同的适合学习速率。如果选择较高的学习速率,可能在某个任务上出现神经元死亡(由于大的负梯度,导致 Relu 函数永久关闭,即 dying ReLU),而使用较低的学习速率,则会导致其他任务收敛缓慢。应该怎么做呢?我们可以在各个「头部」(见上图,即各任务的子网络)分别调节各自的学习速率,而在共享网络部分,使用另一个学习速率。

虽然听上去很复杂,但其实非常简单。通常,在利用 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)

相关的pytorch实现代码请参考作者的这一篇文章:

如何为模型不同层设置不同的学习率?_云隐雾匿的博客-CSDN博客

第三点:将估计作为特征

当我们完成了第一阶段的工作,为预测多任务创建好神经网络后,我们可能希望将某一个任务得到的估计(estimate)作为另一个任务的特征。在前向传递(forward-pass)中,这非常简单。估计是一个张量,可以像任意一个神经层的输出一样进行传递。但在反向传播中呢?

假设将任务 A 的估计作为特征输入给 B,我们可能并不希望将梯度从任务 B 传回任务 A,因为我们已经有了任务 A 的标签。对此不用担心,TensorFlow 的 API 所提供的 tf.stop_gradient 会有所帮助。在计算梯度时,它允许你传入一个希望作为常数的张量列表,这正是我们所需要的。

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

和上面一样,这个方法对 MTL 网络很有用,但不止如此。该技术可用在任何你希望利用 TensorFlow 计算某个值并将其作为常数的场景。例如,在训练生成对抗网络(Generative Adversarial Network,GAN)时,你不希望将对抗示例反向传播到生成过程中。

作者的其它文章

浅谈多任务学习_soft parameter sharing_云隐雾匿的博客-CSDN博客

### 大型语言模型概述 大型语言模型(Large Language Models, LLMs)代表了一类基于深度学习技术构建的强大自然语言处理工具。这些模型通过大规模语料库训练,在多种任务上展现出卓越性能,包括但不限于文本生成、问答系统以及对话代理。 #### 发展历程与特性 LLMs经历了四个发展阶段:预训练-微调范式下的早期探索;引入自监督学习机制后的架构创新;参数量级突破百亿乃至千亿规模所带来的质变效应;最终形成具备广泛适用性的通用人工智能平台[^1]。相较于传统的小型或特定领域限定的语言模型,LLMs具有显著优势——更强的泛化能力和更少的数据依赖性。 #### 关键差异对比 当比较LLMs与其他类型的预训练语言模型时,主要存在三点不同之处: - **数据需求**:前者能够利用互联网上的海量无标注文本资源进行高效训练; - **上下文理解力**:后者往往受限于固定长度的历史记录窗口大小,而前者则能更好地捕捉长期依赖关系; - **迁移灵活性**:对于下游应用场景而言,仅需少量样本即可实现良好适配效果。 #### 应用场景拓展 除了传统的文字处理外,多模态融合成为新的研究热点之一。例如Video-LLaMA框架允许同时解析视频中的视觉和听觉信息,并将其转换成连贯的语言描述,从而支持更加复杂的人机交互形式[^3]。 此外,在实际业务操作层面,诸如内容审查这样的功能也得到了极大增强。借助于强大的分类识别技能,经过专门调整优化过的LLM版本可以迅速响应政策变动并精准定位违规行为,极大地提高了工作效率和服务质量[^4]。 ```python # Python代码示例展示如何加载一个预训练好的LLM用于简单的情感分析任务 from transformers import pipeline sentiment_analysis = pipeline("sentiment-analysis") result = sentiment_analysis(["We are very happy to see you!", "This is so annoying."]) print(result) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值