携手创造,共同成长!这是我参与「日新方案 8 月更文挑战」的第30天,点击检查活动概况

阐明

之前的一篇博客简略的文本分类使命:运用Huggingface Trainer完成 为大家展示了怎么运用Huggingface Transformers库来快速上手完成一个现代的文本分类模型的范式,虽然trainer很好用,但因为其封装的太过完善,所以在某些修改方面显得不是那么方便,咱们有必要自己运用Pytorch手写一下整个流程。

使命简介

与前一篇博客相同,仍进行IMDB数据集上的情感剖析。不过本次实验的不同之处在于:

  1. 为了快速完成,运用练习数据为1000条,测试为100条;
  2. 运用BERT进行练习而不是distil-bert。

数据预处理

自始自终,咱们仍是运用datasets库加载数据集,

from datasets import load_dataset
dataset = load_dataset("imdb")

接着,初始化tokenizer然后进行预处理

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")

咱们运用bert的tokenizer,词表数目为30522。

在进行分词时,为了加快运行速度,设置最大的token序列长度为256。

def tokenize_function(examples):
    return tokenizer(examples["text"], padding="max_length",truncation=True,max_length=256)
tokenized_datasets = dataset.map(tokenize_function, batched=True)
tokenized_datasets.set_format("torch")  #将值转换为torch.Tensor目标

相同的,因为数据集过大,咱们这里只挑选1000个做train的样例,100个做evaluation样例。

SMALL_TRAIN_SIZE = 1000
SMALL_TEST_SIZE = 100
small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(SMALL_TRAIN_SIZE))
small_test_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(SMALL_TEST_SIZE))

然后咱们运用Pytorch原生的Dataloader来进行数据迭代,这里设置batch size为16,对练习和测试数据集采取相同的batch size:

train_dataloader = DataLoader(small_train_dataset, shuffle=True, batch_size=16)
test_dataloader = DataLoader(small_test_dataset, batch_size=16)

评价目标定义

这里,咱们仅挑选准确率作为评价目标,

metric=datasets.load_metric("accuracy")

而datasets库现已为咱们封装好了评价目标,能够直接一行代码调用,非常方便。

模型、优化器和scheduler的初始化

咱们直接运用Huggingface的bert模型进行初始化,同时挑选AdamW作为优化器,scheduler则是指的学习率的调度器,用于控制学习率的改变方法,比如BERT中常用的warmup操作。

model=AutoModelForSequenceClassification.from_pretrained("bert-base-uncased",num_labels=2)
optimizer = AdamW(model.parameters(), lr=2e-5)
num_epochs = 1
num_training_steps = num_epochs * len(train_dataloader)
lr_scheduler = get_scheduler(
    name="linear", optimizer=optimizer, num_warmup_steps=0, num_training_steps=num_training_steps
)

这里,咱们设置练习的epoch为1,学习率为2e-5,batch size现已在Dataloader中设置过为16.

模型的练习与验证

接下来,咱们运用Pytorch手写练习和验证流程。

progress_bar = tqdm(range(num_training_steps))
global_step = 0
print("Before training.")
metric=datasets.load_metric("accuracy")
model.eval()
for batch in test_dataloader:
    batch = {k: v.to(device) for k, v in batch.items()}
    with torch.no_grad():
        outputs = model(**batch)
    logits = outputs.logits
    predictions = torch.argmax(logits, dim=-1)
    metric.add_batch(predictions=predictions, references=batch["labels"])
print("step: ", global_step, metric.compute())
print()
print("Start training.")
model.train()
for epoch in range(num_epochs):
    for batch in train_dataloader:
        batch = {k: v.to(device) for k, v in batch.items()}
        outputs = model(**batch)
        loss = outputs.loss
        loss.backward()
        optimizer.step()
        lr_scheduler.step()
        optimizer.zero_grad()
        progress_bar.update(1)
        if (global_step+1) % 10 == 0:
            metric=datasets.load_metric("accuracy")
            model.eval()
            for batch in test_dataloader:
                batch = {k: v.to(device) for k, v in batch.items()}
                with torch.no_grad():
                    outputs = model(**batch)
                logits = outputs.logits
                predictions = torch.argmax(logits, dim=-1)
                metric.add_batch(predictions=predictions, references=batch["labels"])
            print("step: ", global_step+1, metric.compute())
        global_step += 1
    metric=datasets.load_metric("accuracy")
    model.eval()
    for batch in test_dataloader:
        batch = {k: v.to(device) for k, v in batch.items()}
        with torch.no_grad():
            outputs = model(**batch)
        logits = outputs.logits
        predictions = torch.argmax(logits, dim=-1)
        metric.add_batch(predictions=predictions, references=batch["labels"])
    print()
    print("Finish: ", global_step+1, metric.compute())

全体的代码分为三个部分:

  1. 练习前的验证:用以检查模型在练习之前的功能体现。
  2. 模型练习:包括以下流程,
    • 从Dataloader中读取数据
    • 输入给模型进行前向核算
    • 核算loss数值
    • loss进行梯度回传
    • 优化器进行参数更新
    • 优化器梯度清零
  3. 练习完成后进行验证:查验模型的最终体现

得到的打印输出如下:

Before training.
step:  0 {'accuracy': 0.47}
Start training.
step:  10 {'accuracy': 0.53}
step:  20 {'accuracy': 0.55}
step:  30 {'accuracy': 0.59}
step:  40 {'accuracy': 0.74}
step:  50 {'accuracy': 0.77}
step:  60 {'accuracy': 0.81}
Finish:  64 {'accuracy': 0.82}

能够看到,随着模型的练习,预测准确率从0.47上升到了0.82。

总结

本文运用Pytorch结构完成了Transformers库中的trainer模块对练习和验证的流程,自定义流程的好处在于灵敏,但相同编写复杂;一般而言,在没有太多的模型内部更改时,能够优先考虑运用trainer,结合datasets库直接做到Huggingface全家桶的一站式开发,非常方便。