【大模型】LLaMA-1 模型介绍-二、模型介绍

时间:2024-05-10 15:03:05

2.1 模型结构

主流的大语言模型都采用了Transformer架构,它是一个基于多层Self-attention的神经网络模型。

原始的Transformer由编码器(Encoder)和解码器(Decoder)两个部分构成,同时,这两个部分也可以独立使用。

在这里插入图片描述

和 GPT 系列一样,LLaMA 模型也是 Decoder-only 架构,但结合前人的工作做了一些改进,比如:

  • Pre-normalization [GPT3]。为了提高训练稳定性,LLaMA 对每个 transformer 子层的输入进行归一化,使用 RMSNorm 归一化函数,Pre-normalization 由Zhang和Sennrich(2019)引入。
  • SwiGLU 激活函数 [PaLM]。将 ReLU 非线性替换为 SwiGLU 激活函数,且使用 2 / 3 ∗ 4 d 2/3 *4d 2/34d 而不是 PaLM 论文中的 4d,SwiGLU 由 Shazeer(2020)引入以提高性能。
  • Rotary Embeddings [GPTNeo]。模型的输入不再使用 positional embeddings,而是在网络的每一层添加了 positional embeddings (RoPE),RoPE 方法由Su等人(2021)引入。

2.2 模型超参数

不同模型的超参数详细信息在下表中给出:

在这里插入图片描述

2.3 SwiGLU

Feed Forward 层全称是 Position-wise Feed-Forward Networks(FPN),FFN 接收一个向量 x(序列中特定位置的隐藏表示),并将其通过两个可学习的线性变换(由矩阵 W1 和 W2 以及偏置向量 b1 和 b2 表示)进行处理,在两个线性变换之间应用修正线性(ReLU)激活函数。计算过程用数学公式可表达为:
在这里插入图片描述

在 T5 模型的实现中,使用是没有偏置 bias 的版本,数学公式表达如下:
在这里插入图片描述
后续的研究提出了用其他非线性激活函数替换ReLU,如高斯误差线性单元 (Gaussian Error Linear Units):
在这里插入图片描述

[Dauphin et al., 2016] 提出了门控线性单元(GLU),定义为输入的两个线性变换的逐元素乘积,其中一个经过了 sigmoid 激活。另外,他们还建议省略激活函数,称之为“双线性”(bilinear)层。

在这里插入图片描述
我们还可以使用其他激活函数定义 GLU 变体,如下所示:
在这里插入图片描述
在本论文中,作者提出了 Transformer FFN 层的其他变体,这些变体使用 GLU 或其变体代替第一个线性变换和激活函数。同样也省略了偏差项。

SwiGLU 激活函数是 Gated Linear Units (GLU) 变体之一,来源于论文 GLU Variants Improve Transformer。SwiGLU 数学表达式如下:
在这里插入图片描述
其中激活函数 Swish 的定义如下:
在这里插入图片描述

原始的的 FPN 层只有两个权重矩阵,但 F P N S w i G L U FPN_{SwiGLU} FPNSwiGLU 的线性变换层有三个权重矩阵。为了保持参数数量和计算量的恒定,需要将隐藏单元的数量 d_ff(W 和 V 的第二个维度以及 W2 的第一个维度)缩小 2/3。实现代码如下所示:

# -*- coding  : utf-8 -*-

import torch
import torch.nn as nn
import torch.nn.functional as F

class FFNSwiGLU(nn.Module):
    def __init__(self, input_dim: int, hidden_dim: int):
        super().__init__()
        hidden_dim = int(2 * hidden_dim / 3)
        self.gate_proj = nn.Linear(input_dim, hidden_dim, bias=False)
        self.down_proj = nn.Linear(hidden_dim, input_dim, bias=False)
        self.up_proj = nn.Linear(input_dim, hidden_dim, bias=False) 

    def forward(self, x):
        # LLaMA 官方提供的代码和模型默认是使用 F.silu() 激活函数,transformers 可通过配置指定
        return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x))

layer = FFNSwiGLU(128, 256)
x = torch.randn(1, 128)
out = layer(x)
print(out.shape) # torch.Size([1, 128])