深度学习论文: LLaMA: Open and Efficient Foundation Language Models

深度学习论文: LLaMA: Open and Efficient Foundation Language Models
LLaMA: Open and Efficient Foundation Language Models
PDF:https://arxiv.org/pdf/2302.13971.pdf
PyTorch: https://github.com/shanglianlm0525/PyTorch-Networks

1 概述

本文介绍了LLaMA,这是一系列基础而先进的语言模型,其参数规模横跨7亿至65亿不等,展现了强大的语言处理能力。研究表明,通过大规模公开数据的训练,LLaMA系列模型成功打破了对专有或受限数据集的依赖,达到了业界最前沿(SOTA)的性能水平。本研究的核心目标是通过显著增加训练中的token数量,开发出在不同推理场景下均能展现出卓越性能的语言模型。

LLaMA模型家族以其多样的参数配置,为语言模型领域带来了新的竞争力量。特别值得注意的是,即便是参数规模仅为GPT-3十分之一的LLaMA-13B版本,也在多数基准测试中超越了GPT-3,展现了其高效与强大。这一成果不仅提升了语言模型的性能边界,更旨在推动LLMs的普及,使得更多研究者能够在单个GPU的资源限制下,轻松访问并深入研究这些大型模型。
在这里插入图片描述
进一步地,在LLaMA系列中,65亿参数的顶级版本在性能上足以与Chinchilla、PaLM-540B等业界顶尖的大型语言模型相抗衡。尤为关键的是,LLaMA的训练完全基于公开数据,秉持开源精神,与许多依赖非公开或未详尽记录数据集的现有模型形成鲜明对比。尽管市场上已存在如OPT、GPT-NeoX、BLOOM和GLM等使用公开数据的模型,但它们在性能上尚未能与PaLM-62B或Chinchilla等顶尖模型相提并论。LLaMA的出现,无疑为语言模型领域注入了新的活力,也为未来的研究和应用开辟了更广阔的道路。

2 Approach

2-1 Pre-training Data

本训练数据集是精心构建的多元化数据集合,其数据来源广泛且覆盖多个领域,具体比例及处理方法如下:

英文CommonCrawl [67%]:
  • 精心预处理了2017年至2020年的五个CommonCrawl数据转储,采用CCNet管道(Wenzek等人,2020),确保数据质量。
  • 在行级别上进行去重操作,减少重复内容。
  • 利用fastText线性分类器识别并剔除非英文页面,保持语言一致性。
  • 通过n-gram语言模型过滤低质量内容,提升数据集质量。
  • 训练线性模型对页面进行分类,保留与维基百科参考相关的页面,丢弃其他低质量页面。
C4 [15%]:
  • 鉴于C4数据集在多样化预处理方面的优势,将其纳入以进一步提升模型性能。
  • 预处理包括去重和语言识别,确保数据纯净。
  • 质量过滤更多依赖于启发式规则,如标点符号、单词和句子数量等,筛选高质量内容。
Github [4.5%]:
  • 从Google BigQuery获取公开Github数据集,筛选符合Apache、BSD和MIT许可的开源项目。
  • 基于行长度和字母数字字符比例等启发式规则过滤低质量文件。
  • 使用正则表达式去除样板文字,如标题等,清理数据。
  • 在文件级别上进行精确匹配去重,确保数据唯一性。
维基百科 [4.5%]:
  • 添加2022年6月至8月期间的维基百科转储,涵盖20种使用拉丁或西里尔字母的语言。
  • 移除超链接、评论和其他格式化样板文字,使数据更纯净。
Gutenberg and Books3 [4.5%]:
  • 包含Gutenberg 项目和ThePile的Books3部分,提供公共领域书籍资源。
  • 在书籍级别上进行去重,移除内容重叠超过90%的书籍,避免数据冗余。
ArXiv [2.5%]:
  • 处理arXiv Latex文件,引入科学领域高质量数据。
  • 去除论文的引言部分和参考文献,专注于核心研究内容。
  • 去除.tex文件中的注释,并内联扩展用户编写的定义和宏,确保内容一致性和完整性。
Stack Exchange [2%]:
  • 引入Stack Exchange数据转储,包含多样化领域的高质量问题和答案。
  • 保留28个最大网站的数据,去除HTML标签,并按答案得分排序,优先使用高质量答案。
分词器:
  • 采用字节对编码(BPE)算法(Sennrich等人,2015),结合SentencePiece(Kudo和Richardson,2018)实现,对数据进行高效分词。
  • 将所有数字拆分成单个数字,并对未知UTF-8字符进行字节级分解,确保分词准确性和灵活性。

整个训练数据集分词后大约包含1.4T个token,其中大部分token在训练中仅使用一次,但计划对维基百科和图书领域数据进行大约两个周期的训练,以充分利用资源。
在这里插入图片描述

2-2 Architecture

基于近期在大语言模型领域的进展,提出的网络架构基于Transformer(Vaswani等,2017),并融入了多项优化改进,这些改进灵感来源于不同的先进模型如PaLM和GPTNeo。

预归一化 [GPT3灵感]

为提升训练稳定性,Llama采用了预归一化技术,对Transformer子层的输入进行规范化处理,以维持参数的范数,有效避免了梯度消失或爆炸的问题。与传统的输出归一化不同,这种策略是在输入端进行的。优化措施参考了GPT-3的经验,并结合了Zhang和Sennrich(2019)提出的RMSNorm归一化函数,旨在提高模型的整体性能。

RMSNorm作为LayerNorm的一种替代方案,发表在《Root Mean Square Layer Normalization》一文中。它的设计初衷是因为LayerNorm的计算成本较高,而RMSNorm在保持性能的同时,能够减少7%到64%的运算量。RMSNorm与LayerNorm的主要区别在于,RMSNorm省略了计算均值的步骤,只专注于方差的计算,通过Root Mean Square来实现归一化,从而简化了计算过程。

在这里插入图片描述

## LlaMa 模型的源代码,网址:https://github.com/facebookresearch/llama/blob/main/llama/model.py
import torch
import torch.nn as nn

class RMSNorm(torch.nn.Module):
    # 定义一个继承自 torch.nn.Module 的 RMSNorm 类
    def __init__(self, dim: int, eps: float = 1e-6):
        """
        初始化 RMSNorm 归一化层。
        参数:
            dim (int): 输入张量的维度。
            eps (float, optional): 为了数值稳定性添加到分母的小值,默认为 1e-6。
        属性:
            eps (float): 为了数值稳定性添加到分母的小值。
            weight (nn.Parameter): 可学习的缩放参数。
        """
        super().__init__()  # 调用父类的初始化方法
        self.eps = eps  # 存储数值稳定性参数
        self.weight = nn.Parameter(torch.ones(dim))  # 初始化可学习的缩放参数

    def _norm(self, x):
        """
        对输入张量应用 RMSNorm 归一化。
        参数:
            x (torch.Tensor): 输入张量。
        返回:
            torch.Tensor: 归一化后的张量。
        """
        # 计算归一化值,使用均方根(RMS)作为分母
        return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)

    def forward(self, x):
        """
        RMSNorm 层的前向传播。
        参数:
            x (torch.Tensor): 输入张量。
        返回:
            torch.Tensor: 应用 RMSNorm 后的输出张量。
        """
        # 将输入张量转换为 float 类型,应用归一化,然后恢复原始类型
        output = self._norm(x.float()).type_as(x)
        # 应用可学习的缩放参数并返回结果
        return output * self.weight
SwiGLU激活函数 [PaLM启发]

为了提升模型的非线性表达能力和整体性能,将ReLU激活函数替换为SwiGLU激活函数。SwiGLU由Shazeer(2020)提出,并在PaLM等模型中展现出优势。Llama在此基础上进行了微调,采用 2 3 4 d \frac{2}{3} 4d 324d 的维度设置,以适应我们的网络架构需求。

SwiGLU(Swish-Gated Linear Unit)是一种结合Swish激活函数与GLU(Gated Linear Unit)机制的激活函数。其公式如下:
在这里插入图片描述
SwiGLU激活函数需要进行三次矩阵乘法运算,相比于ReLU等传统激活函数计算复杂度更高。

然而,研究发现,尽管计算量增加,SwiGLU带来的性能提升显著:

更好的泛化性能:SwiGLU在处理复杂的文本数据时表现出更好的泛化能力。
稳定的梯度流:Swish激活函数平滑的曲线特性有助于稳定梯度,减少梯度消失和爆炸的可能性。

class SwiGLU(nn.Module):
    """
    Swish-Gated Linear Unit
    https://arxiv.org/pdf/2002.05202v1.pdf
    """
    def __init__(self, size):
        super().__init__()
        self.linear_gate = nn.Linear(size, size)
        self.linear = nn.Linear(size, size)
        self.beta = torch.randn(1, requires_grad=True)

        self.beta = nn.Parameter(torch.ones(1))
        self.register_parameter("beta", self.beta)

    def forward(self, x):
        swish_gate = self.linear_gate(x) * torch.sigmoid(self.beta * self.linear_gate(x))
        out = swish_gate * self.linear(x)
        return out
旋转位置嵌入 [GPTNeo创新]

为了更有效地处理序列中的位置信息,摒弃了传统的绝对位置嵌入,转而采用Su等人(2021)提出的旋转位置嵌入(RoPE)。

RoPE的核心思想是通过一系列旋转矩阵来编码序列中不同位置的相对关系,从而使得模型能够捕捉到序列中的位置信息。RoPE 通过将每个位置的嵌入表示为旋转矩阵,实现对位置信息的编码。这种方法使得模型能够通过旋转操作来感知序列中元素的相对位置。同时旋转矩阵保留了位置之间的相对关系,使得模型在处理长距离依赖时更加有效。

在这里插入图片描述
RoPE的关键优势:

  • 相对位置感知:RoPE能够保持位置信息的相对关系,使得相邻位置的编码具有相似性,而远离位置的编码则具有差异性。这种特性使得模型能够更好地感知和利用位置信息,从而提高对序列数据的理解。

  • 外推能力:RoPE可以通过旋转矩阵生成超过预训练长度的位置编码,这意味着模型可以处理比训练时更长的序列,增强了模型的泛化能力和鲁棒性。

  • 与线性注意力机制的兼容性:RoPE不需要额外的计算或参数来实现相对位置编码,这与线性注意力机制(如Transformer中的自注意力机制)兼容,从而降低了模型的计算复杂度和内存消耗。

  • 无需额外参数:与其他需要额外参数或计算的混合位置编码方法(如Transformer-XL、XLNet)相比,RoPE不需要引入额外的参数或计算步骤,这简化了模型的架构并可能提高效率。

RoPE的这些特性使其在处理长序列数据时特别有用,因为它可以有效地捕捉到长距离的依赖关系,同时保持计算效率。然而,RoPE作为一种相对较新的技术,可能还需要进一步的研究和实验来验证其在不同任务和数据集上的表现和稳定性。

# 生成旋转矩阵
def precompute_freqs_cis(dim: int, seq_len: int, theta: float = 10000.0):
    # 计算词向量元素两两分组之后,每组元素对应的旋转角度\theta_i
    freqs = 1.0 / (theta ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim))
    # 生成 token 序列索引 t = [0, 1,..., seq_len-1]
    t = torch.arange(seq_len, device=freqs.device)
    # freqs.shape = [seq_len, dim // 2] 
    freqs = torch.outer(t, freqs).float()  # 计算m * \theta

    # 计算结果是个复数向量
    # 假设 freqs = [x, y]
    # 则 freqs_cis = [cos(x) + sin(x)i, cos(y) + sin(y)i]
    freqs_cis = torch.polar(torch.ones_like(freqs), freqs) 
    return freqs_cis

# 旋转位置编码计算
def apply_rotary_emb(
    xq: torch.Tensor,
    xk: torch.Tensor,
    freqs_cis: torch.Tensor,
) -> Tuple[torch.Tensor, torch.Tensor]:
    # xq.shape = [batch_size, seq_len, dim]
    # xq_.shape = [batch_size, seq_len, dim // 2, 2]
    xq_ = xq.float().reshape(*xq.shape[:-1], -1, 2)
    xk_ = xk.float().reshape(*xk.shape[:-1], -1, 2)
    
    # 转为复数域
    xq_ = torch.view_as_complex(xq_)
    xk_ = torch.view_as_complex(xk_)
    
    # 应用旋转操作,然后将结果转回实数域
    # xq_out.shape = [batch_size, seq_len, dim]
    xq_out = torch.view_as_real(xq_ * freqs_cis).flatten(2)
    xk_out = torch.view_as_real(xk_ * freqs_cis).flatten(2)
    return xq_out.type_as(xq), xk_out.type_as(xk)

class Attention(nn.Module):
    def __init__(self, args: ModelArgs):
        super().__init__()

        self.wq = Linear(...)
        self.wk = Linear(...)
        self.wv = Linear(...)
        
        self.freqs_cis = precompute_freqs_cis(dim, max_seq_len * 2)

    def forward(self, x: torch.Tensor):
        bsz, seqlen, _ = x.shape
        xq, xk, xv = self.wq(x), self.wk(x), self.wv(x)

        xq = xq.view(batch_size, seq_len, dim)
        xk = xk.view(batch_size, seq_len, dim)
        xv = xv.view(batch_size, seq_len, dim)

        # attention 操作之前,应用旋转位置编码
        xq, xk = apply_rotary_emb(xq, xk, freqs_cis=freqs_cis)
        
        # scores.shape = (bs, seqlen, seqlen)
        scores = torch.matmul(xq, xk.transpose(1, 2)) / math.sqrt(dim)
        scores = F.softmax(scores.float(), dim=-1)
        output = torch.matmul(scores, xv)  # (batch_size, seq_len, dim)
  # ......

参考资料:
1 十分钟读懂旋转编码(RoPE)
2 一文看懂 LLaMA 中的旋转式位置编码(Rotary Position Embedding)

通过上述优化,提出的网络架构在保持Transformer强大能力的同时,进一步提升了训练稳定性、非线性表达能力和对位置信息的处理能力,从而有望在大语言模型任务中取得更优的表现。

提出的Llama架构如下:
在这里插入图片描述

2-3 Optimizer

  • 模型采用AdamW优化器训练,设置β1为0.9,β2为0.95
  • 使用余弦退火学习率计划,最终学习率是初始最大值的10%
  • 使用权重衰减和梯度裁剪
  • 使用2000步预热
  • 根据模型大小调整学习率和批量大小。

2-4 Efficient implementation

  • xformers: 不保存注意力的权重,不计算被掩码的 K/Q 的得分
  • 使用检查点技术,减少在反向传播过程中重新计算的激活量
  • 实现了模型和序列并行性,以及尽可能重叠激活计算和GPU间的通信。

3 Main results

Common Sense Reasoning

在这里插入图片描述

Closed-book Question Answering

在这里插入图片描述
在这里插入图片描述

Reading Comprehension

在这里插入图片描述

Mathematical reasoning

在这里插入图片描述

Code generation

在这里插入图片描述

Massive Multitask Language Understanding

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一二三应用开发平台应用开发示例(7)——文档功能实现示例

概述 在完成文件夹配置工作后,接下来配置文档管理系统最核心的管理对象“文档”。 依旧是使用平台低代码配置工作来配置,配置流程跟文件夹的配置是相同的,以下简要说明,重点是新涉及到的功能或注意点。 创建实体 配置模型属性 …

【Dison夏令营 Day 15】 Python 鸡蛋捕手

在本次课程中,我们使用 Python 创建了经典的 "抓蛋 "游戏。在这个游戏中,每抓到一个鸡蛋就能赢得 10 分,而每掉落一个鸡蛋就会损失一条命。 小时候,我们都玩过 "抓鸡蛋 "游戏。我们使用海龟软件包在 Python …

【linux】阿里云centos配置邮件服务

目录 1.安装mailx服务 2./etc/mail.rc 配置增加 3.QQ邮箱开启smtp服务,获取授权码 4.端口设置:Linux 防火墙开放端口-CSDN博客 5.测试 1.安装mailx服务 yum -y install mailx 2./etc/mail.rc 配置增加 #邮件发送人 set from924066173qq.com #阿里…

windows USB 设备驱动开发-USB电源管理(一)

符合通用串行总线 (USB) 规范的 USB 设备的电源管理功能具有一组丰富而复杂的电源管理功能。 请务必了解这些功能如何与 Windows 驱动程序模型 (WDM) 交互,特别是 Microsoft Windows 如何调整标准 USB 功能以支持系统唤醒体系结构。 基于内核模式驱动程序框架的 US…

android13 rom 开发总纲说明

1. 这里是文章总纲,可以在这里快速找到需要的文章。 2. 文章一般是基于标准的android13,有一些文章可能会涉及到具体平台,例如全志,瑞芯微等一些平台。 3.系统应用 3.1系统应用Launcher3桌面相关: 3.2系统应用设置S…

NLP入门——词袋语言模型的搭建、训练与预测

卷积语言模型实际上是取了句子最后ctx_len个词作为上下文输入模型来预测之后的分词。但更好的选择是我们做一个词袋,将所有分词装在词袋中作为上下文,这样预测的分词不只根据最后ctx_len个分词,而是整个词袋中的所有分词。 例如我们的序列是&…

绝对值不等式运用(C++)

货仓选址 用数学公式表达题意,假设有位置a1~an,假设选址在x位置处,则有: 如何让这个最小,我们把两个式子整合一下,利用绝对值不等式: 我们知道: 如下图所示:到A,B两点&…

【深度学习入门篇 ②】Pytorch完成线性回归!

🍊嗨,大家好,我是小森( ﹡ˆoˆ﹡ )! 易编橙终身成长社群创始团队嘉宾,橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官、CSDN人工智能领域优质创作者 。 易编橙:一个帮助编程小…

简单状压dp(以力扣464为例)

目录 1.状态压缩dp是啥? 2.题目分析 3.解题思路 4.算法分析 5.代码分析 6.代码一览 7.结语 1.状态压缩dp是啥? 顾名思义,状态压缩dp就是将原本会超出内存限制的存储改用更加有效的存储方式。简而言之,就是压缩dp的空间。 …

昇思MindSpore学习笔记6-05计算机视觉--SSD目标检测

摘要: 记录MindSpore AI框架使用SSD目标检测算法对图像内容识别的过程、步骤和方法。包括环境准备、下载数据集、数据采样、数据集加载和预处理、构建模型、损失函数、模型训练、模型评估等。 一、概念 1.模型简介 SSD目标检测算法 Single Shot MultiBox Detecto…

WebRTC群发消息API接口选型指南!怎么用?

WebRTC群发消息API接口安全性如何?API接口怎么优化? WebRTC技术在现代实时通信中占据了重要地位。对于需要实现群发消息功能的应用程序来说,选择合适的WebRTC群发消息API接口是至关重要的。AokSend将详细介绍WebRTC群发消息API接口的选型指南…

大数据开发者如何快速熟悉新公司业务

作为一名大数据开发工程师,进入一家新公司后快速熟悉业务是至关重要的。 目录 1. 了解产品形态故事1:电商平台的数据分析故事2:金融科技的风控系统故事3:社交媒体的推荐算法 2. 了解业务流程故事1:物流配送系统的优化故事2:医疗保险的理赔流程故事3:银行的贷款审批流程 3. 走…

openfoam生成的非均匀固体Solid数据分析、VTK数据格式分析、以及paraview官方用户指导文档和使用方法

一、openfoam生成的非均匀固体Solid数据分析 对于Solid/dealii-output文件,固体的数据文件, # vtk DataFile Version 3.0 #This file was generated by the deal.II library on 2024/7/10 at 9:46:15 ASCII DATASET UNSTRUCTURED_GRIDPOINTS 108000 do…

【算法】【二分法】二分法详解

先给y总打一个广告。(我这种废物收不到钱) 本科时候就在打蓝桥杯玩玩算法,当时听朋友的一个刷题且涵盖教程的网站,ACWING。 www.acwing.com 里面好处是大部分基础算法都有,Y总的视频! y总我的神&#xff01…

IDEA之Debug的使用

自定义功能图表 功能说明 光标回到Debug行 执行到光标所在行 Force Step into Trace Current Stream Chain Reset Frame 重置方法入栈

C++基础学习笔记

1.命名空间(namespace) 1.什么是命名空间&命名空间的作用 1.在C/C中,变量、函数、类都是大量存在的,这些变量等的名称将都存在于全局作用域中,就会导致很多的命名冲突等。使用命名空间的目的就是对标识符的名称进行本地化,以…

Nginx七层(应用层)反向代理:UWSGI代理uwsgi_pass篇

Nginx七层(应用层)反向代理 UWSGI代理uwsgi_pass篇 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this a…

JavaSE学习笔记第二弹——对象和多态(下)

今天我们继续复习与JavaSE相关的知识,使用的编译器仍然是IDEA2022,大家伙使用eclipse或其他编译环境是一样的,都可以。 目录 数组 定义 一维数组 ​编辑 二维数组 多维数组 数组的遍历 for循环遍历 ​编辑 foreach遍历 封装、继承和…

网络编程的学习之udp

Udp编程过程 Sento不会阻塞 实现聊天室效果 上线 聊天 下线 服务端需要一个地址,去保留名字和ip地址 交互的时候发结构体 下面这个宏只能在c语言里使用 ser.sin_port htons(50000); 上面是端口号50000以上,两边要一样 这里是不要让udp发的太快&am…

Git命令常规操作

目录 常用操作示意图 文件的状态变化周期 1. 创建文件 2. 修改原有文件 3. 删除原有文件 没有添加到暂存区的数据直接 rm 删除即可: 对于添加到暂存区的数据 文件或目录: 4. 重命名暂存区数据 5. 查看历史记录 6. 还原历史数据 恢复过程的原…