【论文解读】Parameter-Efficient Transfer Learning for NLP

news2024/11/15 9:22:02

一. 介绍

1.1 为什么要引入Adapter

在存在许多下游任务的情况下,微调的参数效率很低:每个任务都需要一个全新的模型。作为替代方案,我们建议使用适配器模块进行传输。

1.2 论文目标

目标是建立一个在所有这些方面都表现良好的系统,但不需要为每个新任务训练一个全新的模型

1.3 论文贡献

设计一个有效的适配器模块及其与基础模型的集成。我们提出了一个简单而有效的瓶颈架构。

二.  NLP的适配器调优

2.1 瓶颈设计

上图显示了我们的适配器体系结构,以及它在Transformer的应用。Transformer的每一层都包含两个主要子层:注意层和前馈层。左图:将适配器模块两次添加到每个Transformer层,在多头注意之后的投影和两个前馈层之后。右图:适配器由瓶颈组成,瓶颈包含与原始模型中的注意力和前馈层相关的几个参数。适配器还包含一个跳过连接。在适配器调优期间,绿色层在下游数据上进行训练,这包括适配器、层归一化参数和最终分类层。

为了限制参数的数量,提出了一个瓶颈架构。适配器首先将原始的d维特征投影到较小的维度m中,使用非线性,然后投影回d维。每层添加的参数总数(包括偏差)为2md + d + m。通过设置m 远小于 d,我们限制了每个任务添加的参数数量

2.2 实验结论

  1. 虽然每个适配器对整体网络的影响很小,但整体效果很大。
  2. 较低层上的适配器比较高层上的适配器影响较小。
  3. 在两个数据集上,适配器的性能对于低于10−2的标准差是鲁棒的。但是,当初始化太大时,性能会下降,对CoLA的影响更大。
  4. 跨适配器大小的模型质量是稳定的,并且在所有任务中使用固定的适配器大小可以对性能造成很小的损害。
  5. 以下扩展未能显著提升性能(i)向适配器添加批处理/层规范化,(ii)增加每个适配器的层数,(iii)不同的激活函数,例如tanh, (iv)仅在注意层内插入适配器,(v)与主层并行添加适配器,并可能使用乘法交互。

三.实验

代码参考:adapter-hub/adapter-transformers: Huggingface Transformers + Adapters = ❤️ (github.com)

以构建Bert模型为例,模型基本继承,包含关系如下图所示

3.1  增加adapter

通过add_adapter调用模型父类ModelAdaptersMixin的add_adapter方法实现增加adapter

model.add_adapter(adapter_name, config=adapter_config)

    def add_adapter(self, adapter_name: str, config=None, overwrite_ok: bool = False, set_active: bool = False):
        config = AdapterConfigBase.load(config)  # ensure config is ok and up-to-date
        # In case adapter already exists and we allow overwriting, explicitly delete the existing one first
        if overwrite_ok and adapter_name in self.config.adapters:
            self.delete_adapter(adapter_name)
#-----------------------------------------------------
        #将配置文件添加到config文件中
        self.config.adapters.add(adapter_name, config=config)
        try:
        #初始化模型模块同时初始化权重
            self._add_adapter_weights(adapter_name)
#-----------------------------------------------------
        except ValueError as ex:
            self.delete_adapter(adapter_name)
            raise ex
        if set_active:
            self.set_active_adapters(adapter_name)

3.1.1 _add_adapter_weights函数

    def _add_adapter_weights(self, adapter_name: str):
        #对模型中的每一层添加adapter层
        self.apply_to_adapter_layers(lambda i, layer: layer.add_adapter(adapter_name, i))
        
        # PHM Layer
        adapter_config = self.config.adapters.match(adapter_name, AdapterConfig, location_key="phm_layer")
        if adapter_config:
            adapter_module = list(self.get_adapter(adapter_name)[0].values())[0]
            # if multiple adapters with same location key exist they are returned as a modulelist
            if isinstance(adapter_module, nn.ModuleList):
                adapter_module = adapter_module[0]
            if adapter_config["shared_phm_rule"] or adapter_config["shared_W_phm"]:
                if self.config.model_type in SUBMODEL_NAMES:
                    hidden_sizes = [
                        getattr(self.config, key).hidden_size for key in SUBMODEL_NAMES[self.config.model_type]
                    ]
                    if all(hidden_sizes[0] == h for h in hidden_sizes):
                        self.base_model.shared_parameters[adapter_name] = init_shared_parameters(
                            adapter_config, hidden_sizes[0], self.device
                        )
                    else:
                        raise ValueError(
                            "The model has different hidden sizes {}. Sharing comapcter weights is only possible if"
                            " the hidden_sizes match.".format(hidden_sizes)
                        )
                else:
                    self.base_model.shared_parameters[adapter_name] = init_shared_parameters(
                        adapter_config, self.config.hidden_size, self.device
                    )
        # Prefix Tuning
        for module in self.modules():
            if isinstance(module, PrefixTuningPool):
                module.confirm_prefix(adapter_name)
        if isinstance(self, InvertibleAdaptersMixin) or isinstance(self, InvertibleAdaptersWrapperMixin):
            self.add_invertible_adapter(adapter_name)

在AdapterLayer类中的add_adapter函数,往每一层中添加了Adapter或者是ParallelAdapter

以Adapter类为例,在初始化函数中我们可以看到Adapter实际上就是一个线性层下采样到映射维度,在投影到原先模型的维度,即下图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1114105.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

作业收集神器

作业收集系统,这是一个让老师们又爱又恨的存在。爱它,因为可以轻松整理学生作业,掌握他们的学习进度;恨它,因为那一份份纸质作业,总是带来无尽的麻烦和挑战。现在,我要告诉你们一个秘密——如何…

基础算法学习|高精度

高精度 模板 高精度加法 // C A B, A > 0, B > 0 vector<int> add(vector<int> &A, vector<int> &B) {//大的数小的数if (A.size() < B.size()) return add(B, A);vector<int> C;int t 0;for (int i 0; i < A.size(); i )…

网安顶刊IEEE Transactions on Dependable and Secure Computing

安全顶刊论文列表 写在最前面IEEE Transactions on Dependable and Secure ComputingTable of Contents&#xff08;March-April 2023&#xff09;Volume 20, Issue 2Table of Contents&#xff08;Sept.-Oct. 2023&#xff09;Volume 20, Issue 5 写在最前面 为了给自己找论文…

如何解决msvcp120.dll丢失?dll丢失有效的5个解决方法分享

在我日常的计算机使用过程中&#xff0c;我遇到了一个令人困扰的问题——MSVCP120丢失。这个问题不仅影响了我的工作效率&#xff0c;也让我对计算机的安全性产生了疑虑。经过一段时间的研究和解决&#xff0c;我对此问题有了深入的理解&#xff0c;并从中获得了宝贵的经验。 …

【嵌入式C语言】1--内存

1.程序运行为什么需要内存 1.计算机程序运行的目的 计算机为什么需要编程&#xff1f; 程序的目的是为了去运行&#xff0c;程序运行是为了得到一定的结果。计算机就是用来计算的&#xff0c;所有计算机程序其实都是在做计算。计算就是在计算数据&#xff0c;所以计算机程序中…

美摄美颜SDK,提供一站式美颜技术解决方案

数字化时代&#xff0c;图像处理技术已经成为企业提升用户体验&#xff0c;增强产品竞争力的重要工具。其中&#xff0c;美颜技术作为图像处理的重要组成部分&#xff0c;已经广泛应用于各类应用中&#xff0c;如社交软件、直播平台、电商平台等。为了满足企业对于美颜技术的需…

测试用例大全

一、文本框为字符型 必填项非空校验&#xff1a; 必填项未输入&#xff0d;&#xff0d;程序应提示错误&#xff1b; 必填项只输入若干个空格&#xff0c;未输入其它字符&#xff0d;&#xff0d;程序应提示错误&#xff1b; 字段唯一性校验&#xff1a;&#xff08;不是所…

秋叶Lora训练器遇到NaN detected

根据我在网络上的搜索&#xff0c;排除了图片尺寸不到位&#xff08;需要1024*1024&#xff09;、arb没开等等情况。最后发现&#xff0c;是需要在保存格式上&#xff0c;不要选fp16&#xff0c;而是选择bf16. 然后就可以运行了&#xff01;

人类科技之巅,光刻机巨头【阿斯麦股票】在第三季度财报后值得买入吗?

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 总结&#xff1a; &#xff08;1&#xff09;阿斯麦&#xff08;ASML&#xff09;公布了强劲的第三季度财务业绩&#xff0c;销售额为67亿欧元&#xff0c;每股收益为4.81欧元&#xff0c;同比增长了12%。 &#xff08;2&a…

C语言指针精简版(一)

目录 理解内存、地址与指针之间的挂关系 编址与寻址&#xff08;简单理解&#xff09; 取地址操作符& 解引用操作符* 指针变量的大小 指针变量类型的意义 const修饰指针变量 const修饰变量 const修饰指针变量 指针运算 指针-整数 指针-指针 指针的运算关系 野…

高频行情数据应用解决方案

高频行情数据的因子研发和相关策略&#xff0c;是在当前金融量化投资领域普遍关注的内容。由于高频行情数据量庞大&#xff08;Level1的Tick每日10G&#xff0c;Level2的Tick每日40G&#xff09;、以及高频数据时序化处理复杂、数据访问性能等问题&#xff0c;为研发工作的开展…

C++ 的强制类型转换

C 的强制类型转换 目录(转换方式): 1 、static_cast 2 、dynamic_cast 3、reinterpret_cast 4、const_cast 5、类型转换使用建议 一、 static_cast&#xff1a; 用于基本类型之间的转换 static_cast<>() 可以说是神通广大。 使用方法 &#xff1a; type y stat…

Linux系统编程:进程part_1

进程 进程以概念为主&#xff0c;知道是怎么回事就行&#xff0c;工作一般都操作线程。 进程的基本概念 因为这些概念在OS教课书中讲的太多&#xff0c;故而这一块不会详述。 什么是进程&#xff1f; 通俗的说进程就是正在运行的程序。进程是动态的程序是静态的。 使用cat…

Pytest测试框架搭建的关键6个知识点(建议收藏)

在现代软件开发中&#xff0c;测试是确保代码质量和功能稳定性的关键步骤。而Pytest作为一个功能强大且易于使用的Python测试框架&#xff0c;为我们提供了一个优雅的方式来编写和管理测试。本文将为你介绍如何构建高效可靠的测试环境&#xff0c;着重探讨Pytest测试框架搭建时…

基于SSM的二手商品交易系统

基于SSM的二手商品交易系统 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 首页 商品详情 登录界面 管理员界面 商品管理 摘要 基于Spring&#xff08;Spring MVC&…

mysql第一篇---索引

文章目录 mysql第一篇---索引索引的数据结构为什么使用索引&#xff1f;索引的及其优缺点InnoDB中索引的推演常见的索引概念InnoDB的B树索引的注意事项MyISAM中索引方案索引的代价MySQL数据结构选择的合理性 mysql第一篇—索引 索引的数据结构 为什么使用索引&#xff1f; 索…

Git快速安装【附安装包资源】

软件安装包 项目版本管理软件 Git windows版本安装包 安装步骤 双击按照包之后&#xff0c;直接next 安装位置尽量不要选择C盘&#xff0c;如果只有C盘&#xff0c;可以尝试分盘&#xff0c;如果C盘已经很小了&#xff0c;那就没办法了 选择完安装位置之后&#xff0c;直…

班主任好物 班级查询系统来啦

哈喽各位&#xff0c;作为一名教育博主&#xff0c;今天我要给大家分享一个班主任的好物——班级查询系统&#xff01;这个系统可真是太方便了呢&#xff0c;那么&#xff0c;这个神秘的班级查询系统到底是什么呢&#xff1f;别急&#xff0c;听我慢慢道来。 班级查询系统&…

数据分析:小红书节点投放指南,引爆双十一!

导语 双11大促将临&#xff0c;对于多数品牌方而言&#xff0c;其中蕴藏着巨大的流量增长机遇。面对竞争激烈的小红书种草平台&#xff0c;品牌方们又该如何提前做好准备&#xff0c;掌握营销节奏&#xff0c;真正抓住流量密码呢&#xff1f;接下来由小编一一道来。 双十一剁…

前端 js 之 面向对象(原型、原型链及继承) 06

今天又是一个美好的一天耶 &#xff01; ✌ 文章目录 一、面向对象编程之前二、原型 与 原型链 &#x1f381;三、new 的原理 &#x1f91e;四、面向对象的优势五、继承 (构造函数之间的)ps&#xff1a; 一、面向对象编程之前 在面向对象编程之前&#xff0c;我们是 面向二进制…