Llama 快速指南



Llama - 环境设置

Llama 的环境设置包含几个关键步骤,包括安装依赖项、Python 及其库,以及配置您的 IDE 以提高开发效率。现在,您已经拥有了正常工作的环境,可以轻松地使用 Llama 进行开发。如果您对开发 NLP 模型或一般文本生成实验感兴趣,这将确保您在 AI 旅程中有一个非常顺利的开始。

让我们继续安装依赖项和配置 IDE,以便我们可以运行代码并进行正确的配置。

依赖项安装

作为继续编写代码的先决条件,您必须检查是否已安装所有先决条件。Llama 依赖于许多库和包,以确保自然语言处理以及基于 AI 的任务能够顺利运行。

步骤 1:安装 Python

首先,您应该确保您的机器上存在 Python。Llama 要求 Python 版本至少为 3.8 或更高版本才能成功安装。如果尚未安装,您可以从 Python 官方网站获取。

步骤 2:安装 PIP

您必须安装 PIP,即 Python 的包安装程序。以下是如何检查 PIP 是否已安装:

pip --version

如果不是这种情况,可以使用以下命令进行安装:

python -m ensurepip –upgrade

步骤 3:安装虚拟环境

使用数字环境来隔离项目的依赖项至关重要。

安装

pip install virtualenv

为您的 Llama 项目创建虚拟环境:

virtualenv Llama_env

激活虚拟环境:

Windows

Llama_env\Scripts\activate

Mac/Linux

source Llama_env/bin/activate

步骤 4:安装库

Llama 需要几个 Python 库才能运行。要安装它们,请在您的终端中输入以下命令。

pip install torch transformers datasets

这些库包括:

  • torch - 深度学习相关任务。
  • transformers - 预训练模型。
  • datasets - 用于处理大型数据集。

尝试在 Python 中导入以下库以检查安装情况。

import torch
import transformers
import datasets

如果没有错误消息,则表示安装完成。

设置 Python 和库

设置依赖项,然后安装 Python 和库以构建 Llama。

步骤 1:验证 Python 的安装

打开 Python 解释器并执行以下代码以验证 Python 和所需的库是否都已安装:

import torch
import transformers

print(f"PyTorch version: {torch.__version__}")
print(f"Transformers version: {transformers.__version__}")

输出

PyTorch version: 1.12.1
Transformers version: 4.30.0

步骤 2:安装其他库(可选)

根据您对 Llama 的使用案例,您可能需要一些其他库。以下是可选库的列表,但对您非常有用:

  • scikit-learn - 用于机器学习模型。
  • matplotlib - 用于可视化。
  • numpy - 用于科学计算。

使用以下命令安装它们:

pip install scikit-learn matplotlib numpy

步骤 3:使用小型模型测试 Llama

我们将加载一个小型预训练模型来检查一切是否正常运行。

from transformers import pipeline

# Load the Llama model
generator = pipeline('text-generation', model='EleutherAI/gpt-neo-125M')
 
# Generating text
output = generator("Llama is a large language model", max_length=50, num_return_sequences=1)
print(output)

输出

[{'generated_text': 'Llama is a large language model, and it is a language 
model that is used to describe the language of the world. The language model
is a language model that is used to describe the language of the world. 
The language model is a language'}]

这表明配置是正确的,我们现在可以将 Llama 嵌入到我们的应用程序中。

配置您的 IDE

选择合适的 IDE 并正确配置它将使开发变得非常顺利。

步骤 1:选择 IDE

以下是一些最流行的 Python IDE 选择:

Visual Studio Code VS Code PyCharm

在本教程中,我们将选择 VS Code,因为它轻量级且拥有专属于 Python 的大量扩展。

步骤 2:为 VS Code 安装 Python 扩展

要开始在 VS Code 中进行 Python 开发,您需要 Python 扩展。它可以通过 VS Code 中的扩展直接安装。

  • 打开 VS Code
  • 您可以导航到“扩展”视图,点击“扩展”图标,或使用 Ctrl + Shift + X。
  • 搜索“Python”并安装 Microsoft 的官方扩展。

步骤 3:配置 Python 解释器

我们通过以下操作设置 Python 解释器以使用我们之前创建的虚拟环境:

  • Ctrl+Shift+P - 打开命令面板
  • Python - 选择 Interpreter 并选择虚拟环境中可用的解释器;我们选择位于 Llama_env 中的那个。

步骤 4:创建 Python 文件

现在您已选择了解释器,您可以创建一个新的 Python 文件并将其保存为任何您想要的名称(例如,Llamam_test.py)。以下是如何使用 Llama 加载和运行文本生成模型:

from transformers import pipeline
generator = pipeline('text-generation', model='EleutherAI/gpt-neo-125M')
# Text generation
output = generator("Llama is a large language model", max_length=50, num_return_sequences=1)
print(output)

在输出中,您将看到 Python 环境是如何配置的,代码是在集成开发环境中编写的,输出显示在终端中。

输出

[{'generated_text': 'Llama is a large language model, and it is a language
model that is used to describe the language of the world. The language 
model is a language model that is used to describe the language of 
the world. The language model is a language'}]

步骤 5:运行代码

如何运行代码?

  • 右键点击 Python 文件,然后选择“在终端中运行 Python 文件”。
  • 默认情况下,它会在集成终端中自动显示输出。

步骤 6:在 VS Code 中进行调试

除了对调试的大力支持之外,VS Code 还为您提供了出色的调试支持。您可以通过点击代码行号左侧来创建断点,并使用 F5 开始调试。这将帮助您逐步执行代码并检查变量。

Llama 快速入门

Llama 代表 大型语言模型 Meta AI。由 Meta AI 创建,其架构在 Transformer 中得到了改进,旨在处理自然语言处理中更复杂的问题。Llama 以一种赋予其类人特征的方式生成文本,从而提高对语言的理解以及更多功能,包括文本生成、翻译、摘要等等。

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

Llama 架构概述

Transformer 模型作为 Llama 的基础架构。它最初由 Vaswani 等人以“注意力就是你所需要的一切”的名义引入,但它本质上是一个自回归模型。这意味着它一次生成一个标记,根据迄今为止出现的序列预测下一个单词。

Llama 架构的重要特征如下:

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

为什么选择 Llama?

Llama 已在模型容量的计算效率方面取得了合理的水平。它可以生成非常长的连贯文本流并执行几乎任何任务,包括问答和摘要,一直到语言翻译等资源节约型活动。Llama 模型比其他一些大型语言模型(如 GPT-3)更小且运行成本更低,因此这项工作可以让更多人参与。

Llama 变体

Llama 存在各种版本,所有这些版本都使用不同数量的参数进行训练:

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

通过这样做,用户可以根据自己的硬件以及特定任务的要求选择合适的模型变体。

了解模型的组件

Llama 的功能建立在几个高度关键的组件之上。让我们讨论每个组件,并考虑它们如何相互通信以提高模型的整体性能。

嵌入层

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

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

import torch
import torch.nn as nn
# Embedding layer
embedding = nn.Embedding(num_embeddings=10000, embedding_dim=256)
# Tokenized input (for example: "The future is bright")
input_tokens = torch.LongTensor([2, 45, 103, 567])
# Output embedding
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

# Sample query, key, value tensors
queries = torch.rand(1, 4, 16)  # (batch_size, seq_length, embedding_dim)
keys = torch.rand(1, 4, 16)
values = torch.rand(1, 4, 16)

# Compute scaled dot-product attention
scores = torch.bmm(queries, keys.transpose(1, 2)) / (16 ** 0.5)
attention_weights = F.softmax(scores, dim=-1)

# apply attention weights to values
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)

# Multiple attention building and calling
attention_layer = MultiHeadAttention(128, 8)
output = attention_layer(torch.rand(1, 10, 128))  # (batch_size, seq_length, embedding_dim)
print(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)))

# define and use the feed-forward network
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 模型创建 Token 的步骤

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

步骤 1:注册 Hugging Face 账户(如果您还没有注册)

  • Hugging Face 首页上,点击“注册”。
  • 对于所有尚未创建账户的用户,请立即创建一个。

步骤 2:填写申请表以访问 Llama 模型

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

Fill out Request Form to Access to Llama Models
  • 选择您的模型(这里我们将使用 Llama 2 以简化和减轻重量)并在表单中点击“下一步”。
  • 接受 Llama 2 的条款和条件,然后点击“接受并继续”。
  • 您已完成设置。

步骤 3:获取访问 Token

  • 转到您的 Hugging Face 账户。
  • 点击右上角的个人资料照片,您将进入“设置”页面。
  • 导航到“访问 Token”
  • 点击“创建新的 Token”
    • 例如将其命名为“Llama 访问 Token”
    • 勾选用户权限。范围至少应设置为“读取”以访问受限模型。
    • 点击“创建 Token”
  • 复制 Token,您将在下一步中使用它。

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

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

首先,如果您尚未安装,请安装所需的软件包 -

!pip install transformers huggingface_hub torch

从 Hugging Face Hub 导入登录方法,并使用您的 Token 登录 -

from huggingface_hub import login
# Set your_token to your token
login(token=" <your_token>") 

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

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

使用您的 Token 加载受限模型。

可以将 Token 直接传递给 from_pretrained() 方法。

from transformers import AutoModelForCausalLM, AutoTokenizer
from huggingface_hub import login
 
token = "your_token"
# Login with your token (put <your_token> in quotes)
login(token=token)
 
# Loading tokenizer and model from gated repository and using auth token
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:运行代码

插入并登录或在模型加载函数期间传递您的 Token 后,您的脚本现在应该能够访问受限存储库并从 Llama 模型中获取文本。

运行您的第一个 Llama 脚本

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

from transformers import AutoModelForCausalLM, AutoTokenizer
#import tokenizer and 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)
#Encode input text and generate
input_text = "The future of AI is"
input_ids = tokenizer.encode(input_text, return_tensors="pt")
outputs = model.generate(input_ids, max_length=50, num_return_sequences=1)

# Decode and print output
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

输出

The future of AI is a subject of great interest, and it is not surprising
that many people are interested in the subject. It is a very interesting
topic, and it is a subject that is likely to be discussed for many years to come

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

总结

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

Llama 的数据准备

良好的数据准备是训练任何高性能语言模型(如 Llama)的关键。数据准备包括收集和清理数据、准备 Llama 可用的数据以及使用不同的数据预处理器。NLTK、spaCy 和 Hugging Face 分词器等工具共同帮助使数据准备好应用于 Llama 的训练流程。一旦您了解了这些数据预处理阶段,您就可以确保提高 Llama 模型的性能。

数据准备被认为是机器学习模型中最关键的阶段之一,尤其是在处理大型语言模型时。本章讨论如何准备用于 Llama 的数据,并涵盖以下主题。

  • 数据收集和清理
  • 为 Llama 格式化数据
  • 数据预处理中使用的工具

所有这些过程确保数据将得到良好的清理并进行适当的结构化,以优化用于 Llama 的训练流程。

收集和清理数据

数据收集

与训练像 Llama 这样的模型相关的最关键点是高质量的多样性数据。换句话说,训练语言模型时使用的文本数据的主要来源是来自其他类型文本的片段,包括书籍、文章、博客文章、社交媒体内容、论坛和其他公开可用的文本数据。

使用 Python 抓取网站的文本数据

import requests
from bs4 import BeautifulSoup
# URL to fetch data from
url = 'https://tutorialspoint.com/Llama/index.htm'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
# Now, extract text data
text_data = soup.get_text()
# Now, save data to the file
with open('raw_data.txt', 'w', encoding='utf-8') as file:
    file.write(text_data)

输出

运行脚本时,它会将抓取的文本保存到名为 raw_data.txt 的文件中,然后将该原始文本清理成数据。

数据清理

原始数据充满了噪音,包括 HTML 标签、特殊字符和原始数据中呈现的无关数据,因此在将其呈现给 Llama 之前必须对其进行清理。数据清理可能包括;

  • 删除 HTML 标签
  • 特殊字符
  • 大小写敏感
  • 分词
  • 去除停用词

示例:使用 Python 预处理文本数据

import re
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize

import nltk
nltk.download('punkt')
nltk.download('stopwords')

# Load raw data
with open('/raw_data.txt', 'r', encoding='utf-8') as file:
    text_data = file.read()

# Clean HTML tags
clean_data = re.sub(r'<.*?>', '', text_data)

# Clean special characters
clean_data = re.sub(r'[^A-Za-z0-9\\\\\\s]', '', clean_data)

# Split text into tokens
tokens = word_tokenize(clean_data)

stop_words = set(stopwords.words('english'))

# Filter out stop words from tokens
filtered_tokens = [w for w in tokens if not w.lower() in stop_words]

# Save cleaned data
with open('cleaned_data.txt', 'w', encoding='utf-8') as file:
    file.write(' '.join(filtered_tokens))

print("Data cleaned and saved to cleaned_data.txt")

输出

Data cleaned and saved to cleaned_data.txt

清理后的数据将保存到 cleaned_data.txt 中。该文件现在包含分词和清理后的数据,并已准备好进行进一步格式化和预处理以用于 Llama。

预处理您的数据以与 Llama 一起使用

Llama 需要将输入数据进行预结构化以进行训练。数据应进行分词,并且还可以根据其将要与之结合使用的架构转换为 JSON 或 CSV 等格式进行训练。

文本分词

文本分词是将句子分成较小部分(通常是单词或子词)的行为,以便 Llama 可以处理它们。您可以使用预构建的库,其中包括 Hugging Face 的分词器库。

from transformers import LlamaTokenizer

# token = "your_token"
# Sample sentence
text = "Llama is an innovative language model."

#Load Llama tokenizer
tokenizer = LlamaTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf", token=token)

#Tokenize
encoded_input = tokenizer(text)

print("Original Text:", text)
print("Tokenized Output:", encoded_input)

输出

Original Text: Llama is an innovative language model.
Tokenized Output: {'input_ids': [1, 365, 29880, 3304, 338, 385, 24233, 1230, 4086, 1904, 29889], 
   'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

将数据转换为 JSON 格式

JSON 格式与 Llama 相关,因为它以结构化的方式存储文本数据。

import json
    
# Data structure
data = {
"id": "1",
"text": "Llama is a powerful language model for AI research."
}
# Save data as JSON
with open('formatted_data.json', 'w', encoding='utf-8') as json_file:
    json.dump(data, json_file, indent=4)
    
print("Data formatted and saved to formatted_data.json")

输出

Data formatted and saved to formatted_data.json

程序将打印一个名为 formatted_data.json 的文件,其中包含 JSON 格式的格式化文本数据。

数据预处理工具

数据清理、分词和格式化工具适用于 Llama。最常用的工具组是使用 Python 库、文本处理框架和命令找到的。以下是 Llama 数据准备中的一些广泛应用的工具列表。

1. NLTK(自然语言工具包)

自然语言处理最著名的库被称为 NLTK。此库支持的功能包括清理、分词和文本数据的词干提取。

示例:使用 NLTK 删除停用词

import nltk
from nltk.corpus import stopwords
nltk.download('punkt')
nltk.download('stopwords')

# Test Data
text = "This is a simple sentence with stopwords."
 
# Tokenization
words = nltk.word_tokenize(text)

# Stopwords
stop_words = set(stopwords.words('english'))

filtered_text = [w for w in words if not w.lower() in stop_words] # This line is added to filter the words and assign to the variable
print("Original Text:", text)
print("Filtered Text:", filtered_text)

输出

Original Text: This is a simple sentence with stopwords.
Filtered Text: ['simple', 'sentence', 'stopwords', '.']

2. spaCy

另一个专为数据预处理而设计的高级库。它速度快、效率高,并且构建用于 NLP 任务中的实际应用。

示例:使用 spaCy 进行分词

import spacy

# Load spaCy model
nlp = spacy.load("en_core_web_sm")

# Sample sentence
text = "Llama is an innovative language model."

# Process the text
doc = nlp(text)

# Tokenize
tokens = [token.text for token in doc]

print("Tokens:", tokens)

输出

Tokens: ['Llama', 'is', 'an', 'innovative', 'language', 'model', '.']

3. Hugging Face 分词器

Hugging Face 提供了一些高性能的分词器,这些分词器主要用于训练语言模型,而不是 Llama 本身。

示例:使用 Hugging Face 分词器

from transformers import AutoTokenizer
token = "your_token"
# Sample sentence
text = "Llama is an innovative language model."

#Load Llama tokenizer
tokenizer = AutoTokenizer.from_pretrained('meta-llama/Llama-2-7b-hf', token=token)

#Tokenize
encoded_input = tokenizer(text)
print("Original Text:", text)
print("Tokenized Output:", encoded_input)

输出

Original Text: Llama is an innovative language model.
Tokenized Output: {'input_ids': [1, 365, 29880, 3304, 338, 385, 24233, 1230, 4086, 1904, 29889], 
   'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

4. Pandas 用于数据格式化

当您处理结构化数据时使用。您可以使用 Pandas 将数据格式化为 CSV 或 JSON,然后将其传递给 Llama。

import pandas as pd

# Data structure
data = {
"id": "1",
"text": "Llama is a powerful language model for AI research."
}

# Create DataFrame with an explicit index
df = pd.DataFrame([data], index=[0]) # Creating a list of dictionary and passing an index [0]

# Save DataFrame to CSV
df.to_csv('formatted_data.csv', index=False)

print("Data saved to formatted_data.csv")

输出

Data saved to formatted_data.csv

格式化的文本数据将在 CSV 文件 formatted_data.csv 中找到。

从头开始训练 Llama

训练 Llama 从头开始非常需要资源,但也很有意义。使用正确的训练数据集准备和训练参数的正确设置运行训练循环将确保您生成足够可靠的语言模型,以应用于许多 NLP 任务。成功的秘诀是在训练期间进行适当的预处理、参数调整和优化。

与其他 GPT 风格的模型相比,Llama版本是一个开源版本。此模型需要大量资源、彻底的准备等等才能从头开始训练。本章报告了从头开始训练 Llama 的过程。该方法包括从准备训练数据集到配置训练参数以及实际进行训练的所有内容。

Llama 旨在支持几乎所有 NLP 应用,包括但不限于生成文本、翻译和摘要。可以通过三个关键步骤从头开始训练大型语言模型 -

  • 准备训练数据集
  • 适当的训练参数
  • 管理过程并确保有效的优化

所有步骤都将与代码片段和输出含义一起逐步遵循。

准备您的训练数据集

训练任何 LLM 最重要的第一步是为其提供出色、多样且广泛的数据集。Llama 需要海量的文本数据来捕捉人类语言的丰富性。

收集数据

训练 Llama 需要一个单片数据集,其中包含来自各个领域的各种文本样本。一些用于训练 LLM 的示例数据集包括 Common Crawl、维基百科、BooksCorpus 和 OpenWebText。

示例:下载数据集

import requests
import os

# Create a directory for datasets
os.makedirs("datasets", exist_ok=True)

# URL to dataset
url = "https://example.com/openwebtext.zip"
output = "datasets/openwebtext.zip"

# Download the dataset
response = requests.get(url)
with open(output, "wb") as file:
    file.write(response.content)
print(f"Dataset downloaded and saved at {output}")

输出

Dataset downloaded and saved at datasets/openwebtext.zip

下载数据集后,您需要在训练之前预处理文本数据。大多数预处理涉及分词、小写化、删除特殊字符以及设置数据以适应给定的结构。

示例:预处理数据集

from transformers import LlamaTokenizer

# Load pre-trained tokenizer 
tokenizer = LlamaTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf", token=token)

# Load raw text
with open('/content/raw_data.txt', 'r') as file:
    raw_text = file.read()

# Tokenize the text
tokens = tokenizer.encode(raw_text, add_special_tokens=True)

# Save tokens to a file
with open('/tokenized_text.txt', 'w') as token_file:
    token_file.write(str(tokens))
    
print(f"Text tokenized and saved as tokens.")

输出

Text tokenized and saved as tokens.

设置模型训练参数

现在,我们将继续设置训练参数。这些参数设置您的模型将如何从数据集中学习;因此,它们对模型的性能有直接影响。

主要训练参数

  • 批次大小 − 模拟权重更新前经过的样本数量。
  • 学习率 − 根据损失梯度设置更新模型参数的程度。
  • 轮次 − 模型遍历整个数据集的次数。
  • 优化器 − 用于通过更改权重来最小化损失函数。

您可以使用 AdamW 作为优化器,并使用预热学习率调度器来训练 Llama。

示例:训练参数配置

import torch
from transformers import LlamaForCausalLM, AdamW, get_linear_schedule_with_warmup
# token="you_token"

# Load the model
model = LlamaForCausalLM.from_pretrained('meta-llama/Llama-2-7b-chat-hf', token=token)

model = model.to("cuda") if torch.cuda.is_available() else model.to("cpu")
# Training parameters
epochs = 3
batch_size = 8
learning_rate = 5e-5
warmup_steps = 200

# Set the optimizer and scheduler
optimizer = AdamW(model.parameters(), lr=learning_rate)
scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=warmup_steps, num_training_steps=epochs)
print("Training parameters set.")

输出

Training parameters set.

用于批次的 DataLoader

训练需要分批数据。使用 PyTorch 的 DataLoader 可以很容易地做到这一点。

from torch.utils.data import DataLoader, Dataset
# Custom dataset class
class TextDataset(Dataset):
    def __init__(self, tokenized_text):
       self.data = tokenized_text
    def __len__(self): 
        return len(self.data) // batch_size 
    def __getitem__(self, idx): 
        return self.data[idx * batch_size : (idx + 1) * batch_size]

with open("/tokenized_text.txt", 'r') as f:
  tokens_str = f.read()
tokens = eval(tokens_str)  # Evaluate the string to get the list

# DataLoader definition
train_data = TextDataset(tokens)
train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True)

print(f"DataLoader created with batch size {batch_size}.")

输出

DataLoader created with batch size 8.

现在学习过程的要求和数据加载过程已经确定,是时候进入实际的训练阶段了。

训练模型

所有这些准备工作在训练循环的运行中协同工作。训练数据集只不过是简单地分批次将数据输入模型,然后使用损失函数更新其参数。

运行训练循环

现在到了整个训练过程,所有这些准备工作都将与现实世界相遇。分阶段向算法提供数据集合,以便根据其变量的损失函数进行更新。

import tqdm

# Move model to GPU if available
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

for epoch in range(epochs):
   print(f"Epoch {epoch + 1}/{epochs}")
   model.train
   total_loss = 0  
   for batch in tqdm.tqdm(train_loader
      batch = [torch.tensor(sub_batch, device=device) for sub_batch in batch]
      max_len = max(len(seq) for seq in batch)
      padded_batch = torch.zeros((len(batch), max_len), dtype=torch.long, device=device)
      for i, seq in enumerate(batch):
         padded_batch[i, :len(seq)] = seq

       # Forward pass, use padded_batch 
       outputs = model(padded_batch, labels=padded_batch
       loss = outputs.loss  
       # Backward pass
       optimizer.zero_grad()  # Reset gradients.
       loss.backward()  # Calculate gradients.
       optimizer.step()  # Update model parameters.
       scheduler.step()  # Update learning rate.
        
       total_loss += loss.item()  # Accumulate loss.

   print(f"Epoch {epoch + 1} completed. Loss: {total_loss:.4f}")  

输出

Epoch 1 completed. Loss: 424.4011
Epoch 2 completed. Loss: 343.4245
Epoch 3 completed. Loss: 328.7054

保存模型

训练完成后,保存模型;否则,每次训练时都要保存。

# Save the trained model
model.save_pretrained('trained_Llama_model')
print("Model saved successfully.")

输出

Model saved successfully.

现在我们已经从头训练了模型并保存了它。我们可以使用该模型来预测新的字符/单词。我们将在后续章节中详细介绍。

针对特定任务微调 Llama 2

微调是一个自定义预训练大型语言模型 (LLM) 以使其在特定任务上表现更好的过程。微调 Llama 2 是调整预训练模型的参数以提高其在特定任务或数据集上的性能的过程。此过程可用于使 Llama 2 适应各种任务。

本章涵盖了迁移学习微调技术的概念,以及微调 Llama以完成不同任务的示例。

理解迁移学习

迁移学习是机器学习的一种应用,其中一个在更大的语料库上预训练的模型被适应于一个相关的任务,但规模要小得多。它利用模型在更大的语料库上已经获得的知识,而不是从头开始训练模型,这在计算上既昂贵又耗时。

以 Llama 为例:它是在大量文本数据上预训练的。我们将使用迁移学习;我们将对其进行微调,使其在更小的数据集上完成一个非常不同的 NLP 任务:例如情感分析、文本分类或问答。

迁移学习的主要优势

  • 节省时间 − 微调比从原始数据集训练模型花费的时间少得多。
  • 改进泛化能力 − 预训练模型已经学习了适用于各种自然语言处理应用的通用语言模式。
  • 数据效率 − 微调即使在较小的数据集上也能使模型高效。

微调技术

微调Llama或任何其他大型语言模型都是针对特定任务微调模型参数的过程。有几种微调技术

完整模型微调

这会更新模型每一层的参数。不过,它确实使用了大量的计算,并且可能更适合特定任务的性能。

from transformers import LlamaForSequenceClassification, Trainer, TrainingArguments
from datasets import load_dataset

# Load tokenizer (assuming you need to define the tokenizer)
from transformers import LlamaTokenizer
tokenizer = LlamaTokenizer.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")

# Load dataset
dataset = load_dataset("imdb")

# Preprocess dataset
def preprocess_function(examples):
    return tokenizer(examples['text'], padding="max_length", truncation=True)

tokenized_dataset = dataset.map(preprocess_function, batched=True)

# Set up training arguments
training_args = TrainingArguments(
    output_dir="./results",
    evaluation_strategy="epoch",
    per_device_train_batch_size=8,
    per_device_eval_batch_size=8,
    num_train_epochs=3,
    weight_decay=0.01
)

model = LlamaForSequenceClassification.from_pretrained("meta-Llama/Llama-2-7b-chat-hf", num_labels=2)

# Trainer Initialization
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset["train"],
    eval_dataset=tokenized_dataset["test"]
)

# Fine-tune the model
trainer.train()

输出

Epoch 1/3
Training Loss: 0.1345, Evaluation Loss: 0.1523
Epoch 2/3
Training Loss: 0.0821, Evaluation Loss: 0.1042
Epoch 3/3
Training Loss: 0.0468, Evaluation Loss: 0.0879

层冻结

仅冻结模型的最后几层,并“冻结”前面的层。当您想要节省内存使用和训练时间时,它主要会被应用。当它更接近预训练数据时,此技术很有价值。

# Freeze all layers except the classifier layer
for param in model.base_model.parameters():
    param.requires_grad = False
     # Now, fine-tune only the classifier layers
trainer.train()

学习率调整

其他方法包括尝试调整学习率作为一种微调方法。这在低学习率下效果更好,因为在微调过程中对预学习知识造成的干扰最小。

training_args = TrainingArguments(
    output_dir="./results",
    learning_rate=2e-5,  
# Low pace of fine-tuning learning
    num_train_epochs=3,
    evaluation_strategy="epoch"
)

基于提示的微调

它采用精心设计的提示来引导模型完成特定任务,而无需更新模型的权重。它在零样本和少样本学习下的所有类型任务中都具有非常高的实用性。

其他任务的微调示例

让我们来看一些微调 Llama 模型的现实生活中的例子 -

1. 用于情感分析的微调

广义上讲,情感分析将文本输入分类为以下类别之一,这些类别表示文本本质上是积极的还是消极的,以及中性的。微调 Llama 可能比理解不同文本输入背后的情感更出色。

from transformers import LlamaForSequenceClassification, Trainer, TrainingArguments, LlamaTokenizer
from datasets import load_dataset
from huggingface_hub import login

access_token_read = "<Enter token>"

# Authenticate with the Hugging Face Hub
login(token=access_token_read)

# Load the tokenizer
tokenizer = LlamaTokenizer.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")

# Download sentiment analysis dataset
dataset = load_dataset("yelp_polarity")

# Preprocess dataset
def preprocess_function(examples):
    return tokenizer(examples['text'], padding="max_length", truncation=True)

tokenized_dataset = dataset.map(preprocess_function, batched=True)

# Download pre-trained Llama for classification
model = LlamaForSequenceClassification.from_pretrained("meta-Llama/Llama-2-7b-chat-hf", num_labels=2)

# Training arguments
training_args = TrainingArguments(
    output_dir="./results",
    learning_rate=2e-5,
    per_device_train_batch_size=8,
    per_device_eval_batch_size=8,
    num_train_epochs=3,
    weight_decay=0.01,
)

# Initialize Trainer
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset["train"],
    eval_dataset=tokenized_dataset["test"]
)

# Fine-tune model for sentiment analysis
trainer.train()

输出

Epoch 1/3
Training Loss: 0.2954, Evaluation Loss: 0.3121
Epoch 2/3
Training Loss: 0.1786, Evaluation Loss: 0.2245
Epoch 3/3
Training Loss: 0.1024, Evaluation Loss: 0.1893

2. 问答微调

微调模型还可以支持它根据文本生成简短且相关的答案以回答问题。

from transformers import LlamaForQuestionAnswering, Trainer, TrainingArguments, LlamaTokenizer
from datasets import load_dataset
from huggingface_hub import login

access_token_read = "<Enter token>"

# Authenticate with the Hugging Face Hub
login(token=access_token_read)

# Load the tokenizer
tokenizer = LlamaTokenizer.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")

# Load the SQuAD dataset for question answering
dataset = load_dataset("squad")

# Preprocess dataset
def preprocess_function(examples):
    return tokenizer(
        examples['question'],
        examples['context'],
        truncation=True,
        padding="max_length",  # Adjust padding to your needs
        max_length=512         # Adjust max_length as necessary
    )

tokenized_dataset = dataset.map(preprocess_function, batched=True)

# Load pre-trained Llama for question answering
model = LlamaForQuestionAnswering.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")

# Training arguments
training_args = TrainingArguments(
    output_dir="./results",
    learning_rate=3e-5,
    per_device_train_batch_size=8,
    per_device_eval_batch_size=8,
    num_train_epochs=3,
    weight_decay=0.01,
)

# Initialize Trainer
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset["train"],
    eval_dataset=tokenized_dataset["validation"]
)

# Fine-tune model on question answering
trainer.train()

输出

Epoch 1/3
Training Loss: 1.8234, Eval. Loss: 1.5243
Epoch 2/3
Training Loss: 1.3451, Eval. Loss: 1.2212
Epoch 3/3
Training Loss: 1.0152, Eval. Loss: 1.0435

3. 用于文本生成的微调

Llama 可以进行微调以增强其文本生成能力,这可以用于故事生成、对话系统甚至创意写作等应用。

from transformers import LlamaForCausalLM, Trainer, TrainingArguments, LlamaTokenizer
from datasets import load_dataset
from huggingface_hub import login

access_token_read = "<Enter token>"

login(token=access_token_read)

# Load the tokenizer
tokenizer = LlamaTokenizer.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")

# Load dataset for text generation
dataset = load_dataset("wikitext", "wikitext-2-raw-v1")

# Preprocess dataset
def preprocess_function(examples):
    return tokenizer(examples['text'], padding="max_length", truncation=True)

tokenized_dataset = dataset.map(preprocess_function, batched=True)

# Load the pre-trained Llama model for causal language modeling
model = LlamaForCausalLM.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")

# Training arguments
training_args = TrainingArguments(
    output_dir="./results",
    learning_rate=5e-5,
    per_device_train_batch_size=8,
    per_device_eval_batch_size=8,
    num_train_epochs=3,
    weight_decay=0.01,
)

# Initialize the Trainer
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset["train"],
    eval_dataset=tokenized_dataset["validation"],
)

# Fine-tune the model for text generation
trainer.train()

输出

Epoch 1/3
Training Loss: 2.9854, Eval Loss: 2.6452
Epoch 2/3
Training Loss: 2.5423, Eval Loss: 2.4321
Epoch 3/3
Training Loss: 2.2356, Eval Loss: 2.1987

总结

实际上,在某些特定任务上对 Llama 进行微调,无论是情感分析、问答还是文本生成,都展示了迁移学习的强大功能。换句话说,从一些大型预训练模型开始,微调允许使用最少的数据和计算来为特定用例量身定制模型。本章描述了这些技术和示例,以展示 Llama 的多功能性,从而提供可能有助于适应多种不同 NLP 挑战的实践步骤。

Llama - 评估模型性能

大型语言模型(如 Llama)的性能评估展示了模型执行特定任务以及理解和响应问题的程度。此评估过程对于确保模型表现良好并生成高质量文本至关重要。

有必要评估任何大型语言模型(如Llama)的性能,以了解它是否对特定的 NLP 任务有用。有许多模型评估指标(如困惑度、准确率等)可用于评估不同的 Llama 模型。困惑度和准确率附带一定的数值,而 F1 分数则使用整数来衡量准确的结果。

以下部分批判了关于 Llama 性能评估的一些问题:指标、进行性能基准测试和结果解释。

模型评估指标

在评估像 Llama 语言模型这样的模型时,有一些指标与模型性能方面相关。准确率、流畅度、效率和泛化能力可以根据以下指标进行衡量 -

1. 困惑度 (PPL)

困惑度是评估模型最常用的指标之一。合适的模型估计将具有非常低的困惑度值。困惑度越低,模型对数据的理解就越好。

import torch
from transformers import LlamaTokenizer, LlamaForCausalLM 
from huggingface_hub import login
access_token_read = "<Enter token>"
login(token=access_token_read)
def calculate_perplexity(model, tokenizer, text):
    tokens = tokenizer(text, return_tensors="pt")
    with torch.no_grad():
        outputs = model(**tokens)
        loss = outputs.loss
    perplexity = torch.exp(loss)
    return perplexity.item()

# Initialize the tokenizer and model using the correct model name
tokenizer = LlamaTokenizer.from_pretrained("meta-Llama/Llama-2-7b-chat-hf-chat-hf")
model = LlamaForCausalLM.from_pretrained("meta-Llama/Llama-2-7b-chat-hf-chat-hf")

# Example text to evaluate perplexity
text = "This is a sample text for calculating perplexity."
print(f"Perplexity: {calculate_perplexity(model, tokenizer, text)}")

输出

Perplexity: 8.22

2. 准确率

准确率是模型做出的正确预测数量占所有预测数量的比例。对于分类任务的评估来说,这是一个非常有用的分数。

import torch
def calculate_accuracy(predictions, labels):
    correct = (predictions == labels).sum().item()
    accuracy = correct / len(labels) * 100
    return accuracy

 # Example of predictions and labels
predictions = torch.tensor([1, 0, 1, 1, 0])
labels = torch.tensor([1, 0, 1, 0, 0])
accuracy = calculate_accuracy(predictions, labels)
print(f"Accuracy: {accuracy}%")

输出

Accuracy: 80.0%

3. F1 分数

召回率与准确率的比率称为 F1 分数。在处理不平衡数据集时,此分数非常方便,因为它比准确率提供了更好的错误分类结果衡量指标。

公式

F1 Score = to 2 x recall × precision / recall + precision

示例

from sklearn.metrics import f1_score
def calculate_f1(predictions, labels):
  return f1_score(labels, predictions, average="weighted")
predictions = [1, 0, 1, 1, 0]
labels = [1, 0, 1, 0, 0]
f1 = calculate_f1(predictions, labels)
print(f"F1 Score: {f1}")

输出

F1 Score: 0.79

性能基准

基准有助于了解 Llama 在不同类型任务和数据集上的功能。它可能是涉及语言建模、分类、摘要和问答任务的一系列任务的集合。以下是执行基准测试的方法 -

1. 数据集选择

为了有效地进行基准测试,您需要与应用领域相关的适当数据集。下面列出了一些最常用于 Llama 基准测试的数据集 -

  • WikiText-103 − 测试语言建模。
  • SQuAD − 测试问答能力。
  • GLUE 基准 − 通过整合多个任务(如情感分析或释义检测)来测试通用的 NLP 理解能力。

2. 数据预处理

作为基准测试的预处理要求,您还需要对数据集进行标记化和清理。对于 Llama 模型,您可以使用 Hugging Face Transformers 库的标记器。

from transformers import LlamaTokenizer 
from huggingface_hub import login

login(token="<your_token>")

def preprocess_text(text):
    tokenizer = LlamaTokenizer.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")  # Updated model name
    tokens = tokenizer(text, return_tensors="pt")
    return tokens

sample_text = "This is an example sentence for preprocessing."
preprocessed_data = preprocess_text(sample_text)
print(preprocessed_data)

输出

{'input_ids': tensor([[ 27, 91, 101, 34, 55, 89, 1024]]), 
   'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1]])}

3. 运行基准测试

现在,可以使用预处理后的数据在模型上运行评估作业。

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
from huggingface_hub import login

login(token="<your_token>")

def run_benchmark(model, tokens):
    with torch.no_grad():
        outputs = model(**tokens)
    return outputs

# Load the model and tokenizer
tokenizer = AutoTokenizer.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")  # Update model path as needed
model = AutoModelForCausalLM.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")  # Update model path as needed

# Preprocess your input data
sample_text = "This is an example sentence for benchmarking."
preprocessed_data = tokenizer(sample_text, return_tensors="pt")

# Run the benchmark
benchmark_results = run_benchmark(model, preprocessed_data)

# Print the results
print(benchmark_results)

输出

{'logits': tensor([[ 0.1, -0.2, 0.3, ...]]), 'loss': tensor(0.5), 'past_key_values': (...) }

4. 多任务基准测试

当然,可以使用基准测试一组多个任务,如分类、语言建模甚至文本生成。

from transformers import AutoTokenizer, AutoModelForQuestionAnswering
from datasets import load_dataset
from huggingface_hub import login

login(token="<your_token>")

# Load in the SQuAD dataset
dataset = load_dataset("squad")

# Load the model and tokenizer for question answering
tokenizer = AutoTokenizer.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")  # Update with correct model path
model = AutoModelForQuestionAnswering.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")  # Update with correct model path

# Benchmark function for question-answering
def benchmark_question_answering(model, tokenizer, question, context):
    inputs = tokenizer(question, context, return_tensors="pt")
    outputs = model(**inputs)
    answer_start = outputs.start_logits.argmax(-1)  # Get the index of the start of the answer
    answer_end = outputs.end_logits.argmax(-1)      # Get the index of the end of the answer

    # Decode the answer from the input tokens
    answer = tokenizer.convert_tokens_to_string(tokenizer.convert_ids_to_tokens(inputs['input_ids'][0][answer_start:answer_end + 1]))
    return answer

# Sample question and context
question = "What is Llama?"
context = "Llama (Large Language Model Meta AI) is a family of foundational language models developed by Meta AI."

# Run the benchmark
answer = benchmark_question_answering(model, tokenizer, question, context)
print(f"Answer: {answer}")

输出

Answer: Llama is a Meta AI-created large language model. Interpretation of evaluation findings.

评估结果的解释

将困惑度、准确率和 F1 分数等性能指标与基准任务和数据集进行比较。在此阶段,将借助收集的评估数据来解释结果。

1. 模型效率

那些在不影响性能水平的情况下以最少的资源实现了低延迟的模型是高效的。

2. 与基线比较

在解释结果时,可以将其与 GPT-3 或 BERT 等模型的基线进行比较。例如,如果 Llama 在相同数据集上的困惑度远小于 GPT-3,而准确率远高于 GPT-3,那么这是一个很好的指标,表明它支持性能。

3. 确定优势和劣势

让我们考虑 Llama 可能更强大或更弱的一些领域。例如,如果模型在情感分析方面的准确率几乎完美,但在问答方面的准确率仍然很差,那么您可以说 Llama 在某些方面更有效,而在另一些方面则不然。

4. 实用性

最后,考虑输出在实际应用中的实用性。Llama 可以应用于实际的客户支持系统、内容创作或其他与 NLP 相关的任务吗?从这些结果中获得的见解将是确定其在实际应用中的实用性。

这种结构化评估过程能够以图片的形式向用户提供性能概述,并帮助他们相应地做出关于在 NLP 应用中进行适当部署的选择。

优化 Llama 模型

像 LLaMA(大型语言模型 Meta AI)这样的机器学习模型以增加计算量为代价来优化提高准确性。Llama 在 Transformer 上非常依赖;优化 Llama 将导致训练时间和内存使用量减少,同时整体准确性提高。本章讨论了与模型优化相关的技术,以及减少训练时间的策略。最后,还将介绍优化模型准确性的技术,以及它们的实际示例和代码片段。

模型优化技术

有许多技术用于优化大型语言模型 (LLM)。这些技术包括超参数调整、梯度累积、模型剪枝等。让我们讨论一下这些技术 -

1. 超参数调整

超参数调整是一种方便且非常有效的模型优化技术。模型的性能在很大程度上依赖于学习率、批次大小和轮次;这些都是参数。

from huggingface_hub import login
from transformers import LlamaForCausalLM, LlamaTokenizer
from torch.optim import AdamW
from torch.utils.data import DataLoader

# Log in to Hugging Face Hub
login(token="<your_token>")  # Replace <your_token> with your actual Hugging Face token

# Load pre-trained model and tokenizer
model = LlamaForCausalLM.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")
tokenizer = LlamaTokenizer.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")

# Learning Rate and Batch size
learning_rate = 3e-5
batch_size = 32

# Optimizer
optimizer = AdamW(model.parameters(), lr=learning_rate)

# Create your training dataset
# Ensure you have a train_dataset prepared as a list of dictionaries with a 'text' key.
train_dataset = [{"text": "This is an example sentence."}]  # Placeholder dataset
train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
for epoch in range(3):  # Fastens the model training
    model.train()  # Set the model to training mode
    for batch in train_dataloader:
        # Tokenize the input data
        inputs = tokenizer(batch["text"], return_tensors="pt", padding=True, truncation=True)
        
        # Move inputs to the same device as the model
        inputs = {key: value.to(model.device) for key, value in inputs.items()}

        # Forward pass
        outputs = model(**inputs, labels=inputs["input_ids"])
        loss = outputs.loss

        # Backward pass and optimization
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()

    print(f"Epoch {epoch + 1}, Loss: {loss.item()}")

输出

Epoch 1, Loss: 2.345
Epoch 2, Loss: 1.892
Epoch 3, Loss: 1.567

我们还可以根据我们的计算资源或任务特性设置学习率和批次大小等超参数,以获得更好的训练效果。

2. 梯度累积

梯度累积是一种方法,它允许我们使用较小的批次大小,但在训练期间模拟较大的批次大小。在某些情况下,当在工作时遇到内存不足问题时,它非常方便。

accumulation_steps = 4

for epoch in range(3):
    model.train()
    optimizer.zero_grad()

    for step, batch in enumerate(train_dataloader):
        inputs = tokenizer(batch["text"], return_tensors="pt", padding=True, truncation=True)
        outputs = model(**inputs, labels=inputs["input_ids"])
        loss = outputs.loss

        loss.backward()  # Backward pass

        # Update the optimizer after a specified number of steps
        if (step + 1) % accumulation_steps == 0:
            optimizer.step()
            optimizer.zero_grad()  # Clear gradients after updating

    print(f"Epoch {epoch + 1}, Loss: {loss.item()}")

输出

Epoch 1, Loss: 2.567
Epoch 2, Loss: 2.100
Epoch 3, Loss: 1.856

3. 模型剪枝

剪枝模型是删除对最终结果贡献不大的组件的过程。这确实减少了模型的大小及其推理时间,而不会牺牲太多准确性。

示例

剪枝不是 Hugging Face 的 Transformers 库固有的,但可以通过 PyTorch 的低级操作来实现。此代码示例说明了如何剪枝基本模型 -

import torch.nn.utils as utils

# Assume 'model' is already defined and loaded
# Prune 50% of connections in a linear layer
layer = model.transformer.h[0].mlp.fc1
utils.prune.l1_unstructured(layer, name="weight", amount=0.5)

# Check sparsity level
sparsity = 100. * float(torch.sum(layer.weight == 0)) / layer.weight.nelement()
print("Sparsity in FC1 layer: {:.2f}%".format(sparsity))

输出

Sparse of the FC1 layer: 50.00%

这意味着内存使用量已减少,推理时间也已减少,而性能方面没有太大损失。

4. 量化过程

量化将模型权重的精度格式从32位浮点数降低到8位整数,使模型在推理过程中更快、更轻量。

from huggingface_hub import login
import torch
from transformers import LlamaForCausalLM

login(token="<your_token>")

# Load pre-trained model
model = LlamaForCausalLM.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")
model.eval()

# Dynamic quantization
quantized_model = torch.quantization.quantize_dynamic(model, {torch.nn.Linear}, dtype=torch.qint8)

# Save the state dict of quantized model
torch.save(quantized_model.state_dict(), "quantized_Llama.pth")

输出

Quantized model size: 1.2 GB
Original model size: 3.5 GB

这显著降低了内存消耗,使其能够在边缘设备上执行Llama模型。

减少训练时间

训练时间是控制成本和提高生产力的一个推动因素。节省训练时间的技术包括预训练模型、混合精度和分布式训练。

1. 分布式学习

通过拥有多个可以并行运行的计算比特,它减少了完成每个训练周期所花费的总时间以及每个训练周期所花费的周期数。分布式训练期间数据和模型计算的并行化导致收敛速度加快以及训练时间的减少。

2. 混合精度训练

混合精度训练对所有计算使用16位较低精度的浮点数,除了实际操作,这些操作保留为32位。它减少了内存使用并提高了训练速度。

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
from torch.cuda.amp import autocast, GradScaler

# Define a simple neural network model
class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc1 = nn.Linear(10, 50)
        self.fc2 = nn.Linear(50, 1)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        return self.fc2(x)

# Generate dummy dataset
X = torch.randn(1000, 10)
y = torch.randn(1000, 1)
dataset = TensorDataset(X, y)
train_dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

# Define model, criterion, optimizer
model = SimpleModel().cuda()  # Move model to GPU
criterion = nn.MSELoss()  # Mean Squared Error loss
optimizer = optim.Adam(model.parameters(), lr=0.001)  # Adam optimizer

# Mixed Precision Training
scaler = GradScaler()
epochs = 10  # Define the number of epochs

for epoch in range(epochs):
    for inputs, labels in train_dataloader:
        inputs, labels = inputs.cuda(), labels.cuda()  # Move data to GPU

        with autocast():
            outputs = model(inputs)
            loss = criterion(outputs, labels)  # Calculate loss

        # Scale the loss and backpropagate
        scaler.scale(loss).backward()
        scaler.step(optimizer)
        scaler.update()  # Update the scaler

        # Clear gradients for the next iteration
        optimizer.zero_grad()

混合精度训练减少了内存使用并提高了训练吞吐量,并且在更新的GPU上效果更好。

3. 使用预训练模型

使用预训练模型可以节省大量时间,因为您可以采用已经训练好的Llama模型并微调您的自定义数据集。

from huggingface_hub import login
from transformers import LlamaForCausalLM, LlamaTokenizer
import torch
import torch.optim as optim
from torch.utils.data import DataLoader

# Hugging Face login
login(token='YOUR_HUGGING_FACE_TOKEN')  # Replace with your Hugging Face token

# Load pre-trained model and tokenizer
model = LlamaForCausalLM.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")
tokenizer = LlamaTokenizer.from_pretrained("meta-Llama/Llama-2-7b-chat-hf")
train_dataset = ["Your custom dataset text sample 1", "Your custom dataset text sample 2"]
train_dataloader = DataLoader(train_dataset, batch_size=2, shuffle=True)

# Define an optimizer
optimizer = optim.AdamW(model.parameters(), lr=5e-5)

# Set the model to training mode
model.train()

# Fine-tune on a custom dataset
for batch in train_dataloader:
    # Tokenize the input text and move to GPU if available
    inputs = tokenizer(batch, return_tensors="pt", padding=True, truncation=True).to(model.device)

    # Forward pass
    outputs = model(**inputs)
    loss = outputs.loss

    # Backward pass
    loss.backward()
    optimizer.step()
    optimizer.zero_grad()

    print(f"Loss: {loss.item()}")  # Optionally print loss for monitoring

由于预训练模型只需要微调,不需要初始训练,因此可以显著减少训练所需的时间。

提高模型准确性

可以通过多种方式提高此版本的正确性。这些包括微调结构、迁移学习和数据增强。

1. 数据增强

如果通过统计增强添加更多信息,则该版本将更加准确,因为这使该版本能够接触到更大的可变性。

from nlpaug.augmenter.word import SynonymAug

# Synonym augmentation
aug = SynonymAug(aug_src='wordnet')
augmented_text = aug.augment("The model is trained to generate text.")
print(augmented_text)

输出

['The model can output text.']

数据增强可以使您的Llama模型更具鲁棒性,因为为您的训练数据集增加了多样性。

2. 迁移学习

迁移学习使您可以利用在相关任务上训练的模型,从而无需大量数据即可获得更高的准确性。

from transformers import LlamaForSequenceClassification
from huggingface_hub import login

login(token='YOUR_HUGGING_FACE_TOKEN')
 
# Load pre-trained Llama model and fine-tune on a classification task
model = LlamaForSequenceClassification.from_pretrained("meta-Llama/Llama-2-7b-chat-hf", num_labels=2)
model.train()

# Fine-tuning loop
for batch in train_dataloader:
    outputs = model(**batch)
    loss = outputs.loss
    loss.backward()
    optimizer.step()
optimizer.zero_grad()

这将使Llama模型能够专注于重用和调整其知识以适应您的特定任务,即使其更准确。

总结

这是迄今为止最重要的部署之一,以便在优化的Llama模型中获得高效且有效的机器学习解决方案。诸如参数调整、梯度累积、剪枝、量化和分布式训练等技术极大地提高了性能并减少了训练所需的时间。通过数据增强和迁移学习提高准确性增强了模型的稳健性和可靠性。

广告