huggingface/transformers Quick tour 学习笔记

Posted 梆子井欢喜坨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了huggingface/transformers Quick tour 学习笔记相关的知识,希望对你有一定的参考价值。

现在做NLP方面的研究实在离不开预训练语言模型,尤其是BERT。

huggingface的transformers包是目前使用BERT最主流最方便的工具之一,写一遍博客记录自己学习其文档。文档版本为4.6,与我在实验室服务器上安装的transformers版本一致,至于为什么不用最新版本的,这个问题在这篇博客中有提到,目前还没有解决。

官方文档链接
Quick tour代码实时运行(google Colab)

1. pipeline API

在给定任务上使用预训练模型的最简单方法是使用pipeline()。Transformers为以下任务提供了开箱即用的接口:

  • 情感分析(Sentiment analysis)
  • 英语文本生成(Text generation in English)
  • 命令实体识别(Name entity recognition, NER)
  • QA
  • 文本填空: 给定带有被屏蔽词的文本(例如,用[mask]替换),然后填入空白处
  • 摘要(Summarization)
  • 翻译
  • 特征提取: 返回文本的向量表示

所有任务的示例代码

下面以情感分析任务为例

from transformers import pipeline
classifier = pipeline('sentiment-analysis')

第一次键入此命令时,将下载对应的预训练模型和它的分词器(tokenizer)。分词器的作用是将文本先进行预处理,然后将分词结果输入模型进行预测。管道将所有这些信息组合在一起,并对预测进行后期处理,使其可读。

简单使用:

classifier('We are very happy to show you the 🤗 Transformers library.')

彩蛋

也可以输入句子的list,返回的结果将是一个字典列表。

results = classifier(["We are very happy to show you the 🤗 Transformers library.",
           "We hope you don't hate it."])
for result in results:
    print(f"label: {result['label']}, with score: {round(result['score'], 4)}")
# label: POSITIVE, with score: 0.9998
# label: NEGATIVE, with score: 0.5309

默认这个pipeline下载的模型是“distilbert-base-uncased-finetuned-sst-2-english”,我们可以在huggingface的网站中找到更多用于文本分类的BERT模型,地址为https://huggingface.co/models?pipeline_tag=text-classification

选择使用模型的代码如下:

classifier = pipeline('sentiment-analysis', model="techthiyanes/chinese_sentiment")

我们也可以使用保存在本地的预训练模型。我们需要向pipeline中传递一个模型对象和其相应的分词器。(这里暂时没看懂)

我们将需要两个类来完成这个工作。 第一个是AutoTokenizer,我们将使用它下载与我们选择的模型关联的分词器,并对它进行实例化。 第二个是AutoModelForSequenceClassification,我们将使用它来下载模型本身。

from transformers import AutoTokenizer, AutoModelForSequenceClassification
model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
model = AutoModelForSequenceClassification.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
classifier = pipeline('sentiment-analysis', model=model, tokenizer=tokenizer)

请注意,如果我们在其他任务中使用该库,则模型的类将发生更改。详情见Summary of the tasks

2. pipeline的工作原理

如下面的代码所示,模型和分词器是通过from_pretrained方法创建的。

from transformers import AutoTokenizer, AutoModelForSequenceClassification
model_name = "distilbert-base-uncased-finetuned-sst-2-english"
pt_model = AutoModelForSequenceClassification.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)

2.1 使用分词器(tokenizer)

第一步,tokenizer会将输入文本分成单词(或单词的一部分,标点符号等),通常称为标记(token)。因为存在不同的预处理方式,所以我们在实例化tokenizer的时候,需要传入预训练模型的模型名称。

第二步,将tokens转换为数字,从而把输入文本转化成tensor的形式,输入对应的模型中。tokenizer中有一个词表(vocab),在调用from_pretrained方法时下载的,因为我们需要使用和模型在预训练阶段用的一样的词表。

为了实现上述的功能,我们可以直接把文本传给tokenizer。
返回一个字典,包含的是input_ids,还有attention mask
"input_ids"是输入的tokens在词表中的id,"attention_mask"告诉模型哪些词需要关注,哪些词不需要关注。

inputs = tokenizer("We are very happy to show you the 🤗 Transformers library.")
print(inputs)
# {'input_ids': [101, 2057, 2024, 2200, 3407, 2000, 2265, 2017, 1996, 100, 19081, 3075, 1012, 102], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

设置tokenizer的参数,比如将输入文本全部填充到相同的长度,将他们截断到模型可接受的最大长度,然后返回张量。

pt_batch = tokenizer(
    ["We are very happy to show you the 🤗 Transformers library.", "We hope you don't hate it."],
    padding=True,
    truncation=True,
    max_length=512,
    return_tensors="pt"
)
for key, value in pt_batch.items():
    print(f"{key}: {value.numpy().tolist()}")

# input_ids: [[101, 2057, 2024, 2200, 3407, 2000, 2265, 2017, 1996, 100, 19081, 3075, 1012, 102], [101, 2057, 3246, 2017, 2123, 1005, 1056, 5223, 2009, 1012, 102, 0, 0, 0]]
# attention_mask: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]]

注意padding出来的地方,attention_mask为0。对于填充的部分,也会生成对应的attention mask,但值为0,因为填充部分不需要模型进行关注。更多关于tokenizer见文档

2.2 使用模型(model)

一旦tokenizer处理好了对应的文本,我们就可以直接把处理好的结果传给对应的模型。

pt_outputs = pt_model(**pt_batch)
print(pt_outputs)
SequenceClassifierOutput(loss=None, logits=tensor([[-4.0833,  4.3364],
    [ 0.0818, -0.0418]], grad_fn=<AddmmBackward>), hidden_states=None, attentions=None)

输出的logits:
logits (torch.FloatTensor of shape (batch_size, config.num_labels)) – Classification (or regression if config.num_labels==1) scores (before SoftMax).

全部的Transformers models(PyTorch或TensorFlow)返回模型在最终激活函数(如SoftMax)之前的激活,因为该最终激活功能通常与损失函数混淆。

在最后的结果中使用softmax函数来获得最终的预测

import torch.nn.functional as F
pt_predictions = F.softmax(pt_outputs.logits, dim=-1)
print(pt_predictions)

tensor([[2.2043e-04, 9.9978e-01],
        [5.3086e-01, 4.6914e-01]], grad_fn=<SoftmaxBackward>)

训练完成后,保存模型

tokenizer.save_pretrained(save_directory)
model.save_pretrained(save_directory)

也可以这样载入模型,即不使用AutoModel和AutoTokenizer。
transformers库中每个架构加类的组合有一个模型类,因此如果需要,代码很容易访问和调整。

from transformers import DistilBertTokenizer, DistilBertForSequenceClassification
model_name = "distilbert-base-uncased-finetuned-sst-2-english"
model = DistilBertForSequenceClassification.from_pretrained(model_name)
tokenizer = DistilBertTokenizer.from_pretrained(model_name)

2.3 定制模型参数

如果要更改模型本身的构建方式,可以定义自定义配置类。每个体系结构都有自己的相关配置。例如,DistilBertConfig允许您为DistilBERT指定隐藏层维度、dropout rate等参数。如果您进行核心修改,例如更改隐藏层大小(hidden size),您将无法再使用预训练模型,需要从头开始训练。然后,您将直接从此配置实例化模型。

下面,我们使用from_pretrained()方法加载tokenizer的预定义词汇表。然而,我们希望从头开始初始化模型。因此,我们从配置实例化模型,而不是使用from_pretrained()方法。

from transformers import DistilBertConfig, DistilBertTokenizer, DistilBertForSequenceClassification
config = DistilBertConfig(n_heads=8, dim=512, hidden_dim=4*512)
tokenizer = DistilBertTokenizer.from_pretrained('distilbert-base-uncased')
model = DistilBertForSequenceClassification(config)

对于仅更改模型头部(例如,标签数量)的对象,仍然可以对主体使用预训练模型。例如,让我们使用预训练体为10个不同的标签定义一个分类器。我们可以将配置需要的任何参数传递给from_pretrained()方法,它将适当地更新默认配置,而不是创建一个具有所有默认值的新配置来更改标签的数量:

from transformers import DistilBertConfig, DistilBertTokenizer, DistilBertForSequenceClassification
model_name = "distilbert-base-uncased"
model = DistilBertForSequenceClassification.from_pretrained(model_name, num_labels=10)
tokenizer = DistilBertTokenizer.from_pretrained(model_name)

以上是关于huggingface/transformers Quick tour 学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

huggingface/transformers数据预处理

从零预训练huggingface/transformers的GPT-2代码

huggingface/transformers Quick tour 学习笔记

huggingface/transformers快速上手

huggingface/transformers快速上手

下载huggingface-transformers模型至本地,并使用from_pretrained方法加载