开始使用 Llama

Llama 代表 大型语言模型 Meta AI。由 Meta AI 创立的变压器架构已得到改进,旨在处理自然语言处理中更复杂的问题。Llama 以赋予其类似人类的特征的方式生成文本,从而提高语言理解能力等等,包括文本生成、翻译、摘要等。

Llama 是一种能够在比其同行 GPT-3 所需的更小的数据集上优化性能的野兽。它旨在在较小的数据集上高效运行,从而可供更广泛的用户使用,同时具有可扩展性。

Llama 架构概述

Transformer 模型是 Llama 的骨干架构。它最初由 Vaswani 等人提出。名为"Attention is All You Need",但它本质上是一个自回归模型。这意味着它一次生成一个标记的文本,根据到目前为止出现的内容预测序列中的下一个单词。

Llama 架构的重要特征如下 −

  • 高效训练 − Llama 可以高效地对小得多的数据集进行训练。因此,它特别适合研究和应用,在这些应用中,可用的计算能力是一个限制,或者数据可用性可能很小。
  • 自回归结构 − 它逐个生成标记,使生成的文本高度连贯,因为每个下一个标记都基于它迄今为止拥有的所有标记。
  • 多头自注意力 −该模型的注意力机制设计为根据重要性为句子中的单词分配不同的权重,以便它理解输入中的局部和全局上下文,
  • 堆叠 Transformer 层 − Llama 堆叠了许多由自注意力机制和前馈神经网络组成的 Transformer 块。

为什么是 Llama?

Llama 已经实现了合理的计算效率来匹配其模型容量。它可以生成非常长的连贯文本流并执行几乎任何任务,包括问答和总结,一直到语言翻译,以及其他资源节约型活动。与其他一些大型语言模型(如 GPT-3)相比,Llama 模型更小,运行成本更低,因此更多人可以使用该模型。

Llama 变体

Llama 有多种版本,所有版本都使用不同数量的参数进行训练 −

  • Llama-7B = 70 亿个参数
  • Llama-13B = 130 亿个参数
  • Llama-30B = 300 亿个参数
  • Llama-65B = 650 亿个参数

在此过程中,用户可以根据自己的硬件以及特定任务的要求选择正确的模型变体。

了解模型的组件

Llama 的功能仅建立在几个非常重要的参数上组件。让我们讨论每个组件,并考虑它们如何相互通信以提高模型的整体性能。

嵌入层

Llama 的嵌入层是将输入标记映射到高维向量。因此,它可以捕获单词之间的语义关系。这种映射背后的直觉是,在连续的向量空间中,语义相似的标记彼此最接近。

嵌入层还通过将标记的形状更改为转换层期望的维度来为转​​换层准备输入。

import torch
import torch.nn as nn
# 嵌入层
embedding = nn.Embedding(num_embeddings=10000, embedding_dim=256)
# 标记化输入(例如:"未来是光明的")
input_tokens = torch.LongTensor([2, 45, 103, 567])
# 输出嵌入
embedding_output = embedding(input_tokens)
print(embedding_output)

输出

tensor([[-0.4185, -0.5514, -0.8762,  ...,  0.7456,  0.2396,  2.4756],
        [ 0.7882,  0.8366,  0.1050,  ...,  0.2018, -0.2126,  0.7039],
        [ 0.3088, -0.3697,  0.1556,  ..., -0.9751, -0.0777, -1.3352],
        [ 0.7220, -0.7661,  0.2614,  ...,  1.2152,  1.6356,  0.6806]],
       grad_fn=<EmbeddingBackward0>)

这种词嵌入表示还允许模型理解标记如何以复杂的方式相互关联。

自注意力机制

Transformer 模型的自注意力是一项创新,其中 Llama 将注意力机制放在句子的各个部分,并理解每个单词与其他单词之间的关系。在这种情况下,Llama 使用多头注意力机制,将注意力机制拆分为多个头,以便模型可以自由探索输入序列的各个部分。

这样就创建了查询、键和值矩阵,模型据此选择相对于其他单词赋予每个单词多少权重(或注意力)。

import torch
import torch.nn. functional as F

# 示例查询、键、值张量
queries = torch.rand(1, 4, 16) # (batch_size, seq_length, embedding_dim)
keys = torch.rand(1, 4, 16)
values = torch.rand(1, 4, 16)

# 计算缩放点积注意力
scores = torch.bmm(queries, keys.transpose(1, 2)) / (16 ** 0.5)
attention_weights = F.softmax(scores, dim=-1)

# 将注意力权重应用于值
output = torch.bmm(attention_weights, values)
print(output)

输出

tensor([[[0.4782, 0.5340, 0.4079, 0.4829, 0.4172, 0.5398, 0.3584, 0.6369,
          0.5429, 0.7614, 0.5928, 0.5989, 0.6796, 0.7634, 0.6868, 0.5903],
         [0.4651, 0.5553, 0.4406, 0.4909, 0.3724, 0.5828, 0.3781, 0.6293,
          0.5463, 0.7658, 0.5828, 0.5964, 0.6699, 0.7652, 0.6770, 0.5583],
         [0.4675, 0.5414, 0.4212, 0.4895, 0.3983, 0.5619, 0.3676, 0.6234,
          0.5400, 0.7646, 0.5865, 0.5936, 0.6742, 0.7704, 0.6792, 0.5767],
         [0.4722, 0.5550, 0.4352, 0.4829, 0.3769, 0.5802, 0.3673, 0.6354,
          0.5525, 0.7641, 0.5722, 0.6045, 0.6644, 0.7693, 0.6745, 0.5674]]])

这种注意力机制使模型能够"关注"序列的不同部分,从而使其能够学习句子中单词之间的长距离依赖关系。

多头注意力

多头注意力是自注意力的扩展,其中并行应用多个注意力头。在此过程中,每个注意力头都会选择输入的不同部分,确保实现数据中依赖关系的所有可能性。

然后进入前馈网络,分别处理每个注意力结果。

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

class MultiHeadAttention(nn.Module):
   def __init__(self, dim_model, num_heads):
      super(MultiHeadAttention, self).__init__()
      self.num_heads = num_heads
      self.dim_head = dim_model // num_heads

        self.query = nn.Linear(dim_model, dim_model)
        self.key = nn.Linear(dim_model, dim_model)
        self.value = nn.Linear(dim_model, dim_model)
        self.out = nn.Linear(dim_model, dim_model)
        
   def forward(self, x):
      B, N, C = x.shape
      queries = self.query(x).reshape(B, N, self.num_heads, self.dim_head).transpose(1, 2)
      keys = self.key(x).reshape(B, N, self.num_heads, self.dim_head).transpose(1, 2)
      values = self.value(x).reshape(B, N, self.num_heads, self.dim_head).transpose(1, 2)
      intention = torch.matmul(queries, keys.transpose(-2, -1)) / (self.dim_head ** 0.5)
      attention_weights = F.softmax(intention, dim=-1)
      out = torch.matmul(attention_weights, values).transpose(1, 2).reshape(B, N, C)
      return self.out(out)

# 多重注意力构建和调用
attention_layer = MultiHeadAttention(128, 8)
output = attention_layer(torch.rand(1, 10, 128))  # (batch_size, seq_length, embedding_dim)
print(output)

Output

tensor([[[-0.1015, -0.1076,  0.2237,  ...,  0.1794, -0.3297,  0.1177],
         [-0.1028, -0.1068,  0.2219,  ...,  0.1798, -0.3307,  0.1175],
         [-0.1018, -0.1070,  0.2228,  ...,  0.1793, -0.3294,  0.1183],
         ...,
         [-0.1021, -0.1075,  0.2245,  ...,  0.1803, -0.3312,  0.1171],
         [-0.1041, -0.1070,  0.2232,  ...,  0.1817, -0.3308,  0.1184],
         [-0.1027, -0.1087,  0.2223,  ...,  0.1801, -0.3295,  0.1179]]],
       grad_fn=<ViewBackward0>)

前馈网络

前馈网络可能是 Transformer 模块中最不重要但又至关重要的构建模块。顾名思义,它将某种形式的非线性变换应用于输入序列;因此,模型可以学习更复杂的模式。

Llama 注意力的每一层都使用前馈网络进行这种变换。

class FeedForward(nn.Module):
   def __init__(self, dim_model, dim_ff):
      super(FeedForward, self).__init__() #This line was incorrectly indented
      self.fc1 = nn.Linear(dim_model, dim_ff)
      self.fc2 = nn.Linear(dim_ff, dim_model)
      self.relu = nn.ReLU()
   def forward(self, x):
      return self.fc2(self.relu(self.fc1(x)))

# 定义并使用前馈网络
ffn = FeedForward(128, 512)
ffn_output = ffn(torch.rand(1, 10, 128)) # (batch_size, seq_length, embedding_dim)
print(ffn_output)

输出

tensor([[[ 0.0222, -0.1035, -0.1494,  ...,  0.0891,  0.2920, -0.1607],
         [ 0.0313, -0.2393, -0.2456,  ...,  0.0704,  0.1300, -0.1176],
         [-0.0838, -0.0756, -0.1824,  ...,  0.2570,  0.0700, -0.1471],
         ...,
         [ 0.0146, -0.0733, -0.0649,  ...,  0.0465,  0.2674, -0.1506],
         [-0.0152, -0.0657, -0.0991,  ...,  0.2389,  0.2404, -0.1785],
         [ 0.0095, -0.1162, -0.0693,  ...,  0.0919,  0.1621, -0.1421]]],
       grad_fn=<ViewBackward0>)

创建使用 Llama 模型的令牌的步骤

在访问 Llama 模型之前,您需要在 Hugging face 上创建令牌。我们使用 Llama 2 模型,因为它很轻量。您可以选择任何模型。请按照以下步骤开始。

步骤 1:注册 Hugging Face 帐户(如果您还没有这样做)

  • Hugging Face 主页上,单击注册。
  • 对于尚未创建帐户的所有人,请立即创建一个

步骤 2:填写访问 Llama 模型的请求表

要下载和使用 Llama 模型,您需要填写请求表。为此 −

填写访问 Llama 模型的请求表
  • 选择您的模型(这里我们将使用 Llama 2 以简化和轻量级)并单击下一步表单。
  • 接受 Llama 2 条款和条件,然后单击接受并继续。
  • 您已全部设置完毕。

步骤3:获取访问令牌

  • 转到您的 Hugging Face 帐户。
  • 点击右上角的个人资料照片,在"设置"中找到您自己
  • 导航到访问令牌
  • 点击创建新令牌
    • 将其命名为"Llama 访问令牌"
    • 勾选用户权限。范围至少应设置为已读,以访问门控模型。
    • 单击创建令牌
  • 复制令牌,您将在下一步中使用它。

步骤 4:使用令牌在脚本中进行身份验证

获得 Hugging Face 令牌后,您必须在 Python 脚本中使用此令牌进行身份验证。

首先,如果您还没有这样做,请安装所需的软件包 −

!pip install tr​​ansformers huggingface_hub torch

从 Hugging Face Hub 导入登录方法并使用您的令牌登录 −

from huggingface_hub import login
#将 your_token 设置为您的令牌
login(token=" <your_token>")

或者,如果您不希望以交互方式登录,您可以在加载模型时直接在代码中传递您的令牌。

步骤 5:更新代码以使用令牌加载模型

使用您的令牌加载门控模型。

令牌可以直接传递给 from_pretrained() 方法。

from transformers import AutoModelForCausalLM, AutoTokenizer
from huggingface_hub import login
 
token = "your_token"
# 使用您的令牌登录(将 <your_token> 放在引号中)
login(token=token)

# 从门控存储库加载 tokenizer 和模型并使用身份验证令牌
tokenizer = AutoTokenizer.from_pretrained('meta-llama/Llama-2-7b-hf', token=token)
model = AutoModelForCausalLM.from_pretrained('meta-llama/Llama-2-7b-hf', token=token)

第 6 步:运行代码

在模型加载函数期间插入并记录或传递令牌后,您的脚本现在应该能够访问门控存储库并从 Llama 模型中提供文本。

运行您的第一个 Llama 脚本

我们已经创建了令牌和其他身份验证;现在是时候运行您的第一个 Llama 脚本了。您可以使用预先训练的 Llama 模型进行文本生成。我们正在使用 Llama-2-7b-hf,它是 Llama 2 模型之一。

from transformers import AutoModelForCausalLM, AutoTokenizer
#导入 tokenizer 和 model
tokenizer = AutoTokenizer.from_pretrained('meta-llama/Llama-2-7b-hf', token=token)
model = AutoModelForCausalLM.from_pretrained('meta-llama/Llama-2-7b-hf', token=token)
#对输入文本进行编码并生成
input_text = "AI 的未来是"
input_ids = tokenizer.encode(input_text, return_tensors="pt")
outputs = model.generate(input_ids, max_length=50, num_return_sequences=1)

# 解码并打印输出
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

输出

人工智能的未来是一个备受关注的话题,许多人对这个话题感兴趣也就不足为奇了。这是一个非常有趣的话题,而且很可能在未来很多年里都会被讨论。

生成文本 − 上述脚本生成一个文本序列,表示 Llama 如何解释上下文以及创建连贯的写作。

总结

令人印象深刻的是其基于转换器的架构、多头注意力和自回归生成功能。计算效率和模型性能之间的平衡使 Llama 适用于广泛的自然语言处理任务。熟悉 Llama 的最重要组件和架构将使您有机会尝试生成文本、翻译、摘要等更多功能。