注意
单击此处下载完整的示例代码
SST-2 使用 XLM-RoBERTa 模型的二进制文本分类¶
作者: Parmeet Bhatia
概述¶
本教程演示如何使用预先训练的 XLM-RoBERTa (XLM-R) 模型在 SST-2 二进制数据集上训练文本分类器。 我们将展示如何使用 torchtext 库来:
为 XLM-R 模型构建文本预处理管道
读取 SST-2 数据集并使用文本和标签转换对其进行转换
使用预先训练的 XLM-R 编码器实例化分类模型
常见导入¶
import torch
import torch.nn as nn
DEVICE = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
数据转换¶
XLM-R 等模型不能直接处理原始文本。培训的第一步 这些模型是将输入文本转换为 Tensor (numerical) 形式,使其 然后,模型可以对其进行处理以进行预测。处理文本的标准方法是:
标记文本
将令牌转换为(整数)ID
添加任何特殊令牌 ID
XLM-R 使用句子模型进行文本分词。下面,我们使用预训练的句词
model 以及相应的词汇表,以使用 TorchText 的转换构建文本预处理管道。
转换是使用 Pipeline 实现的,这与 torchscriptable 类似,但可使用 torchscriptable。请注意,转换同时支持批处理和非批处理文本输入,即一个
可以传递单个句子或句子列表。
torch.nn.Sequential()
import torchtext.transforms as T
from torch.hub import load_state_dict_from_url
padding_idx = 1
bos_idx = 0
eos_idx = 2
max_seq_len = 256
xlmr_vocab_path = r"https://download.pytorch.org/models/text/xlmr.vocab.pt"
xlmr_spm_model_path = r"https://download.pytorch.org/models/text/xlmr.sentencepiece.bpe.model"
text_transform = T.Sequential(
T.SentencePieceTokenizer(xlmr_spm_model_path),
T.VocabTransform(load_state_dict_from_url(xlmr_vocab_path)),
T.Truncate(max_seq_len - 2),
T.AddToken(token=bos_idx, begin=True),
T.AddToken(token=eos_idx, begin=False),
)
from torch.utils.data import DataLoader
或者,我们也可以使用预训练模型附带的 transform,该模型可以开箱即用地执行上述所有操作
text_transform = XLMR_BASE_ENCODER.transform()
数据¶
torchtext 提供了几个标准的 NLP 数据集。有关完整列表,请参阅文档 在 https://pytorch.org/text/stable/datasets.html。这些数据集是使用可组合的 torchdata 构建的 datapipes 的 v.s,因此支持使用用户定义的函数的标准流控制和映射/转换 和 transforms。下面,我们将演示如何使用文本和标签处理转换来预处理 SST-2 数据集。
注意
目前,使用 datapipes 仍需注意一些事项。如果您愿意 扩展此示例以包括 shuffling、multi-processing 或 分布式学习,请参阅此说明以获取更多说明。
from torchtext.datasets import SST2
batch_size = 16
train_datapipe = SST2(split="train")
dev_datapipe = SST2(split="dev")
# Transform the raw dataset using non-batched API (i.e apply transformation line by line)
def apply_transform(x):
return text_transform(x[0]), x[1]
train_datapipe = train_datapipe.map(apply_transform)
train_datapipe = train_datapipe.batch(batch_size)
train_datapipe = train_datapipe.rows2columnar(["token_ids", "target"])
train_dataloader = DataLoader(train_datapipe, batch_size=None)
dev_datapipe = dev_datapipe.map(apply_transform)
dev_datapipe = dev_datapipe.batch(batch_size)
dev_datapipe = dev_datapipe.rows2columnar(["token_ids", "target"])
dev_dataloader = DataLoader(dev_datapipe, batch_size=None)
或者,我们也可以使用批处理 API(即对整个批处理应用转换)
def batch_transform(x):
return {"token_ids": text_transform(x["text"]), "target": x["label"]}
train_datapipe = train_datapipe.batch(batch_size).rows2columnar(["text", "label"])
train_datapipe = train_datapipe.map(lambda x: batch_transform)
dev_datapipe = dev_datapipe.batch(batch_size).rows2columnar(["text", "label"])
dev_datapipe = dev_datapipe.map(lambda x: batch_transform)
模型准备¶
torchtext 提供了 SOTA 预训练模型,可用于微调下游 NLP 任务。 下面我们使用具有标准基本架构的预训练 XLM-R 编码器,并附加一个分类器头对其进行微调 在 SST-2 二元分类任务中。我们将使用库中的标准分类器 head,但用户可以定义 他们自己合适的任务头,并将其连接到预先训练的编码器上。有关可用预训练模型的更多详细信息, 请参阅 https://pytorch.org/text/main/models.html 中的文档
num_classes = 2
input_dim = 768
from torchtext.models import RobertaClassificationHead, XLMR_BASE_ENCODER
classifier_head = RobertaClassificationHead(num_classes=num_classes, input_dim=input_dim)
model = XLMR_BASE_ENCODER.get_model(head=classifier_head)
model.to(DEVICE)
训练方法¶
现在,我们来定义标准优化器和训练标准以及一些辅助函数 用于训练和评估
import torchtext.functional as F
from torch.optim import AdamW
learning_rate = 1e-5
optim = AdamW(model.parameters(), lr=learning_rate)
criteria = nn.CrossEntropyLoss()
def train_step(input, target):
output = model(input)
loss = criteria(output, target)
optim.zero_grad()
loss.backward()
optim.step()
def eval_step(input, target):
output = model(input)
loss = criteria(output, target).item()
return float(loss), (output.argmax(1) == target).type(torch.float).sum().item()
def evaluate():
model.eval()
total_loss = 0
correct_predictions = 0
total_predictions = 0
counter = 0
with torch.no_grad():
for batch in dev_dataloader:
input = F.to_tensor(batch["token_ids"], padding_value=padding_idx).to(DEVICE)
target = torch.tensor(batch["target"]).to(DEVICE)
loss, predictions = eval_step(input, target)
total_loss += loss
correct_predictions += predictions
total_predictions += len(target)
counter += 1
return total_loss / counter, correct_predictions / total_predictions
火车¶
现在,我们拥有训练分类模型的所有要素。请注意,我们可以直接迭代 在我们的 dataset 对象上,而不使用 DataLoader。我们的预处理数据集应该已经产生了批量数据, 感谢我们应用的 Batching Datapipe。对于分布式训练,我们需要使用 DataLoader 来 处理数据分片。
num_epochs = 1
for e in range(num_epochs):
for batch in train_dataloader:
input = F.to_tensor(batch["token_ids"], padding_value=padding_idx).to(DEVICE)
target = torch.tensor(batch["target"]).to(DEVICE)
train_step(input, target)
loss, accuracy = evaluate()
print("Epoch = [{}], loss = [{}], accuracy = [{}]".format(e, loss, accuracy))
输出¶
100%|██████████|5.07M/5.07M [00:00<00:00, 40.8MB/s]
Downloading: "https://download.pytorch.org/models/text/xlmr.vocab.pt" to /root/.cache/torch/hub/checkpoints/xlmr.vocab.pt
100%|██████████|4.85M/4.85M [00:00<00:00, 16.8MB/s]
Downloading: "https://download.pytorch.org/models/text/xlmr.base.encoder.pt" to /root/.cache/torch/hub/checkpoints/xlmr.base.encoder.pt
100%|██████████|1.03G/1.03G [00:26<00:00, 47.1MB/s]
Epoch = [0], loss = [0.2629831412637776], accuracy = [0.9105504587155964]
脚本总运行时间:(0 分 0.000 秒)