Hugging Face 的 Transformers 库快速入门 (一)开箱即用的 pipelines
注:本系列教程僅供學(xué)習(xí)使用, 由原作者授權(quán), 均轉(zhuǎn)載自小昇的博客 。
文章目錄
- 前言
- 開箱即用的 pipelines
- 情感分析
- 零訓(xùn)練樣本分類
- 文本生成
- 遮蓋詞填充
- 命名實(shí)體識(shí)別
- 自動(dòng)問答
- 自動(dòng)摘要
- 這些 pipeline 背后做了什么?
- 使用分詞器進(jìn)行預(yù)處理
- 將預(yù)處理好的輸入送入模型
- 對(duì)模型輸出進(jìn)行后處理
- 總結(jié)
前言
Transformers 是由 Hugging Face 開發(fā)的一個(gè) NLP 包,支持加載目前絕大部分的預(yù)訓(xùn)練模型。隨著 BERT、GPT 等大規(guī)模語言模型的興起,越來越多的公司和研究者采用 Transformers 庫(kù)來構(gòu)建 NLP 應(yīng)用,因此熟悉 Transformers 庫(kù)的使用方法很有必要。
注:本系列教程只專注于處理文本,多模態(tài)方法請(qǐng)查閱相關(guān)文檔。
開箱即用的 pipelines
Transformers 庫(kù)將目前的 NLP 任務(wù)歸納為幾下幾類:
- 文本分類: 例如情感分析、句子對(duì)關(guān)系判斷等;
- 對(duì)文本中的詞語進(jìn)行分類: 例如詞性標(biāo)注 (POS)、命名實(shí)體識(shí)別 (NER) 等;
- 文本生成: 例如填充預(yù)設(shè)的模板 (prompt)、預(yù)測(cè)文本中被遮掩掉 (masked) 的詞語;
- 從文本中抽取答案: 例如根據(jù)給定的問題從一段文本中抽取出對(duì)應(yīng)的答案;
- 根據(jù)輸入文本生成新的句子: 例如文本翻譯、自動(dòng)摘要等。
Transformers 庫(kù)最基礎(chǔ)的對(duì)象就是 pipeline() 函數(shù),它封裝了預(yù)訓(xùn)練模型和對(duì)應(yīng)的前處理和后處理環(huán)節(jié)。我們只需輸入文本,就能得到預(yù)期的答案。目前常用的 pipelines 有:
- feature-extraction (獲得文本的向量化表示)
- fill-mask (填充被遮蓋的詞、片段)
- ner (命名實(shí)體識(shí)別)
- question-answering (自動(dòng)問答)
- sentiment-analysis (情感分析)
- summarization (自動(dòng)摘要)
- text-generation (文本生成)
- translation (機(jī)器翻譯)
- zero-shot-classification (零訓(xùn)練樣本分類)
下面我們以常見的幾個(gè) NLP 任務(wù)為例,展示如何調(diào)用這些 pipeline 模型。
情感分析
借助情感分析 pipeline,我們只需要輸入文本,就可以得到其情感標(biāo)簽(積極/消極)以及對(duì)應(yīng)的概率:
from transformers import pipelineclassifier = pipeline("sentiment-analysis") result = classifier("I've been waiting for a HuggingFace course my whole life.") print(result) results = classifier(["I've been waiting for a HuggingFace course my whole life.", "I hate this so much!"] ) print(results) No model was supplied, defaulted to distilbert-base-uncased-finetuned-sst-2-english (https://huggingface.co/distilbert-base-uncased-finetuned-sst-2-english)[{'label': 'POSITIVE', 'score': 0.9598048329353333}] [{'label': 'POSITIVE', 'score': 0.9598048329353333}, {'label': 'NEGATIVE', 'score': 0.9994558691978455}]pipeline 模型會(huì)自動(dòng)完成以下三個(gè)步驟:
pipeline 會(huì)自動(dòng)選擇合適的預(yù)訓(xùn)練模型來完成任務(wù)。例如對(duì)于情感分析,默認(rèn)就會(huì)選擇微調(diào)好的英文情感模型 distilbert-base-uncased-finetuned-sst-2-english。
Transformers 庫(kù)會(huì)在創(chuàng)建對(duì)象時(shí)下載并且緩存模型,只有在首次加載模型時(shí)才會(huì)下載,后續(xù)會(huì)直接調(diào)用緩存好的模型。
零訓(xùn)練樣本分類
零訓(xùn)練樣本分類 pipeline 允許我們?cè)诓惶峁┤魏螛?biāo)注數(shù)據(jù)的情況下自定義分類標(biāo)簽。
from transformers import pipelineclassifier = pipeline("zero-shot-classification") result = classifier( "This is a course about the Transformers library", candidate_labels=["education", "politics", "business"], ) print(result) No model was supplied, defaulted to facebook/bart-large-mnli (https://huggingface.co/facebook/bart-large-mnli){'sequence': 'This is a course about the Transformers library', 'labels': ['education', 'business', 'politics'], 'scores': [0.8445973992347717, 0.11197526752948761, 0.043427325785160065]}可以看到,pipeline 自動(dòng)選擇了預(yù)訓(xùn)練好的 facebook/bart-large-mnli 模型來完成任務(wù)。
文本生成
我們首先根據(jù)任務(wù)需要構(gòu)建一個(gè)模板 (prompt),然后將其送入到模型中來生成后續(xù)文本。注意,由于文本生成具有隨機(jī)性,因此每次運(yùn)行都會(huì)得到不同的結(jié)果。
這種模板被稱為前綴模板 (Pre?x Prompt),了解更多詳細(xì)信息可以查看《Prompt 方法簡(jiǎn)介》。
from transformers import pipelinegenerator = pipeline("text-generation") results = generator("In this course, we will teach you how to") print(results) results = generator("In this course, we will teach you how to",num_return_sequences=2,max_length=50 ) print(results) No model was supplied, defaulted to gpt2 (https://huggingface.co/gpt2)[{'generated_text': "In this course, we will teach you how to use data and models that can be applied in any real-world, everyday situation. In most cases, the following will work better than other courses I've offered for an undergrad or student. In order"}] [{'generated_text': 'In this course, we will teach you how to make your own unique game called "Mono" from scratch by doing a game engine, a framework and the entire process starting with your initial project. We are planning to make some basic gameplay scenarios and'}, {'generated_text': 'In this course, we will teach you how to build a modular computer, how to run it on a modern Windows machine, how to install packages, and how to debug and debug systems. We will cover virtualization and virtualization without a programmer,'}]可以看到,pipeline 自動(dòng)選擇了預(yù)訓(xùn)練好的 gpt2 模型來完成任務(wù)。我們也可以指定要使用的模型。對(duì)于文本生成任務(wù),我們可以在 Model Hub 頁面左邊選擇 Text Generation tag 查詢支持的模型。例如,我們?cè)谙嗤?pipeline 中加載 distilgpt2 模型:
from transformers import pipelinegenerator = pipeline("text-generation", model="distilgpt2") results = generator("In this course, we will teach you how to",max_length=30,num_return_sequences=2, ) print(results) [{'generated_text': 'In this course, we will teach you how to use React in any form, and how to use React without having to worry about your React dependencies because'}, {'generated_text': 'In this course, we will teach you how to use a computer system in order to create a working computer. It will tell you how you can use'}]還可以通過左邊的語言 tag 選擇其他語言的模型。例如加載專門用于生成中文古詩(shī)的 gpt2-chinese-poem 模型:
from transformers import pipelinegenerator = pipeline("text-generation", model="uer/gpt2-chinese-poem") results = generator("[CLS] 萬 疊 春 山 積 雨 晴 ,",max_length=40,num_return_sequences=2, ) print(results) [{'generated_text': '[CLS] 萬 疊 春 山 積 雨 晴 , 孤 舟 遙 送 子 陵 行 。 別 情 共 嘆 孤 帆 遠(yuǎn) , 交 誼 深 憐 一 座 傾 。 白 日 風(fēng) 波 身 外 幻'}, {'generated_text': '[CLS] 萬 疊 春 山 積 雨 晴 , 滿 川 煙 草 踏 青 行 。 何 人 喚 起 傷 春 思 , 江 畔 畫 船 雙 櫓 聲 。 桃 花 帶 雨 弄 晴 光'}] 模型輸入與輸出中的 CLS 并沒有什么意義, 主要是為了與預(yù)訓(xùn)練模型中的輸入輸出格式保持一致 。遮蓋詞填充
給定一段部分詞語被遮蓋掉 (masked) 的文本,使用預(yù)訓(xùn)練模型來預(yù)測(cè)能夠填充這些位置的詞語。
與前面介紹的文本生成類似,這個(gè)任務(wù)其實(shí)也是先構(gòu)建模板然后運(yùn)用模型來完善模板,稱為填充模板 (Cloze Prompt)。了解更多詳細(xì)信息可以查看《Prompt 方法簡(jiǎn)介》。
from transformers import pipelineunmasker = pipeline("fill-mask") results = unmasker("This course will teach you all about <mask> models.", top_k=2) print(results) No model was supplied, defaulted to distilroberta-base (https://huggingface.co/distilroberta-base)[{'sequence': 'This course will teach you all about mathematical models.', 'score': 0.19619858264923096, 'token': 30412, 'token_str': ' mathematical'}, {'sequence': 'This course will teach you all about computational models.', 'score': 0.04052719101309776, 'token': 38163, 'token_str': ' computational'}]可以看到,pipeline 自動(dòng)選擇了預(yù)訓(xùn)練好的 distilroberta-base 模型來完成任務(wù)。
命名實(shí)體識(shí)別
命名實(shí)體識(shí)別 (NER) pipeline 負(fù)責(zé)從文本中抽取出指定類型的實(shí)體,例如人物、地點(diǎn)、組織等等。
from transformers import pipelinener = pipeline("ner", grouped_entities=True) results = ner("My name is Sylvain and I work at Hugging Face in Brooklyn.") print(results) No model was supplied, defaulted to dbmdz/bert-large-cased-finetuned-conll03-english (https://huggingface.co/dbmdz/bert-large-cased-finetuned-conll03-english)[{'entity_group': 'PER', 'score': 0.9981694, 'word': 'Sylvain', 'start': 11, 'end': 18}, {'entity_group': 'ORG', 'score': 0.97960186, 'word': 'Hugging Face', 'start': 33, 'end': 45}, {'entity_group': 'LOC', 'score': 0.99321055, 'word': 'Brooklyn', 'start': 49, 'end': 57}]可以看到,模型正確地識(shí)別出了 Sylvain 是一個(gè)人物,Hugging Face 是一個(gè)組織,Brooklyn 是一個(gè)地名。
這里通過設(shè)置參數(shù) grouped_entities=True ,使得 pipeline 自動(dòng)合并屬于同一個(gè)實(shí)體的多個(gè)子詞 (token),例如這里將“Hugging”和“Face”合并為一個(gè)組織實(shí)體,實(shí)際上 Sylvain 也進(jìn)行了子詞合并,因?yàn)榉衷~器會(huì)將 Sylvain 切分為 S 、 ##yl 、 ##va 和 ##in 四個(gè) token。
自動(dòng)問答
自動(dòng)問答 pipeline 可以根據(jù)給定的上下文回答問題,例如:
from transformers import pipelinequestion_answerer = pipeline("question-answering") answer = question_answerer(question="Where do I work?",context="My name is Sylvain and I work at Hugging Face in Brooklyn", ) print(answer) No model was supplied, defaulted to distilbert-base-cased-distilled-squad (https://huggingface.co/distilbert-base-cased-distilled-squad){'score': 0.6949771046638489, 'start': 33, 'end': 45, 'answer': 'Hugging Face'}可以看到,pipeline 自動(dòng)選擇了在 SQuAD 數(shù)據(jù)集上訓(xùn)練好的 distilbert-base 模型來完成任務(wù)。這里的自動(dòng)問答 pipeline 實(shí)際上是一個(gè)抽取式問答模型,即從給定的上下文中抽取答案,而不是生成答案。
根據(jù)形式的不同,自動(dòng)問答 (QA) 系統(tǒng)可以分為三種:
- 抽取式 QA (extractive QA): 假設(shè)答案就包含在文檔中,因此直接從文檔中抽取答案;
- 多選 QA (multiple-choice QA): 從多個(gè)給定的選項(xiàng)中選擇答案,相當(dāng)于做閱讀理解題;
- 無約束 QA (free-form QA): 直接生成答案文本,并且對(duì)答案文本格式?jīng)]有任何限制。
自動(dòng)摘要
自動(dòng)摘要 pipeline 旨在將長(zhǎng)文本壓縮成短文本,并且還要盡可能保留原文的主要信息,例如:
from transformers import pipelinesummarizer = pipeline("summarization") results = summarizer("""America has changed dramatically during recent years. Not only has the number of graduates in traditional engineering disciplines such as mechanical, civil, electrical, chemical, and aeronautical engineering declined, but in most of the premier American universities engineering curricula now concentrate on and encourage largely the study of engineering science. As a result, there are declining offerings in engineering subjects dealing with infrastructure, the environment, and related issues, and greater concentration on high technology subjects, largely supporting increasingly complex scientific developments. While the latter is important, it should not be at the expense of more traditional engineering.Rapidly developing economies such as China and India, as well as other industrial countries in Europe and Asia, continue to encourage and advance the teaching of engineering. Both China and India, respectively, graduate six and eight times as many traditional engineers as does the United States. Other industrial countries at minimum maintain their output, while America suffers an increasingly serious decline in the number of engineering graduates and a lack of well-educated engineers.""" ) print(results) No model was supplied, defaulted to sshleifer/distilbart-cnn-12-6 (https://huggingface.co/sshleifer/distilbart-cnn-12-6)[{'summary_text': ' America has changed dramatically during recent years . The number of engineering graduates in the U.S. has declined in traditional engineering disciplines such as mechanical, civil, electrical, chemical, and aeronautical engineering . Rapidly developing economies such as China and India, as well as other industrial countries in Europe and Asia, continue to encourage and advance engineering .'}]可以看到,pipeline 自動(dòng)選擇了預(yù)訓(xùn)練好的 distilbart-cnn-12-6 模型來完成任務(wù)。與文本生成類似,我們也可以通過 max_length 或 min_length 參數(shù)來控制返回摘要的長(zhǎng)度。
這些 pipeline 背后做了什么?
這些簡(jiǎn)單易用的 pipeline 模型實(shí)際上封裝了許多操作,下面我們就來了解一下它們背后究竟做了啥。以第一個(gè)情感分析 pipeline 為例,我們運(yùn)行下面的代碼:
from transformers import pipelineclassifier = pipeline("sentiment-analysis") result = classifier("I've been waiting for a HuggingFace course my whole life.") print(result)就會(huì)得到結(jié)果:
[{'label': 'POSITIVE', 'score': 0.9598048329353333}]實(shí)際上它的背后經(jīng)過了三個(gè)步驟:
使用分詞器進(jìn)行預(yù)處理
因?yàn)樯窠?jīng)網(wǎng)絡(luò)模型無法直接處理文本,因此首先需要通過預(yù)處理環(huán)節(jié)將文本轉(zhuǎn)換為模型可以理解的數(shù)字。具體地,我們會(huì)使用每個(gè)模型對(duì)應(yīng)的分詞器 (tokenizer) 來進(jìn)行:
我們對(duì)輸入文本的預(yù)處理需要與模型自身預(yù)訓(xùn)練時(shí)的操作完全一致,只有這樣模型才可以正常地工作。注意,每個(gè)模型都有特定的預(yù)處理操作,如果對(duì)要使用的模型不熟悉,可以通過 Model Hub 查詢。這里我們使用 AutoTokenizer 類和它的 from_pretrained() 函數(shù),它可以自動(dòng)根據(jù)模型 checkpoint 名稱來獲取對(duì)應(yīng)的分詞器。
情感分析 pipeline 的默認(rèn) checkpoint 是 distilbert-base-uncased-finetuned-sst-2-english,下面我們手工下載并調(diào)用其分詞器:
from transformers import AutoTokenizercheckpoint = "distilbert-base-uncased-finetuned-sst-2-english" tokenizer = AutoTokenizer.from_pretrained(checkpoint)raw_inputs = ["I've been waiting for a HuggingFace course my whole life.","I hate this so much!", ] inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt") print(inputs) {'input_ids': tensor([[ 101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012, 102],[ 101, 1045, 5223, 2023, 2061, 2172, 999, 102, 0, 0,0, 0, 0, 0, 0, 0]]), 'attention_mask': tensor([[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, 0, 0, 0, 0, 0]]) }可以看到,輸出中包含兩個(gè)鍵 input_ids 和 attention_mask,其中 input_ids 對(duì)應(yīng)分詞之后的 tokens 映射到的數(shù)字編號(hào)列表,而 attention_mask 則是用來標(biāo)記哪些 tokens 是被填充的(這里“1”表示是原文,“0”表示是填充字符)。
先不要關(guān)注 padding、truncation 這些參數(shù),以及 attention_mask 項(xiàng),后面我們會(huì)詳細(xì)介紹:)。
將預(yù)處理好的輸入送入模型
預(yù)訓(xùn)練模型的下載方式和分詞器 (tokenizer) 類似,Transformers 包提供了一個(gè) AutoModel 類和對(duì)應(yīng)的 from_pretrained() 函數(shù)。下面我們手工下載這個(gè) distilbert-base 模型:
from transformers import AutoModelcheckpoint = "distilbert-base-uncased-finetuned-sst-2-english" model = AutoModel.from_pretrained(checkpoint)預(yù)訓(xùn)練模型的本體只包含基礎(chǔ)的 Transformer 模塊,對(duì)于給定的輸入,它會(huì)輸出一些神經(jīng)元的值,稱為 hidden states 或者特征 (features)。對(duì)于 NLP 模型來說,可以理解為是文本的高維語義表示。這些 hidden states 通常會(huì)被輸入到其他的模型部分(稱為 head),以完成特定的任務(wù),例如送入到分類頭中完成文本分類任務(wù)。
其實(shí)前面我們舉例的所有 pipelines 都具有類似的模型結(jié)構(gòu),只是模型的最后一部分會(huì)使用不同的 head 以完成對(duì)應(yīng)的任務(wù)。
Transformers 庫(kù)封裝了很多不同的結(jié)構(gòu),常見的有:
Transformer 模塊的輸出是一個(gè)維度為 (Batch size, Sequence length, Hidden size) 的三維張量,其中 Batch size 表示每次輸入的樣本(文本序列)數(shù)量,即每次輸入多少個(gè)句子,上例中為 2;Sequence length 表示文本序列的長(zhǎng)度,即每個(gè)句子被分為多少個(gè) token,上例中為 16;Hidden size 表示每一個(gè) token 經(jīng)過模型編碼后的輸出向量(語義表示)的維度。
預(yù)訓(xùn)練模型編碼后的輸出向量的維度通常都很大,例如 Bert 模型 base 版本的輸出為 768 維,一些大模型的輸出維度為 3072 甚至更高。
我們可以打印出這里使用的 distilbert-base 模型的輸出維度:
from transformers import AutoTokenizer, AutoModelcheckpoint = "distilbert-base-uncased-finetuned-sst-2-english" tokenizer = AutoTokenizer.from_pretrained(checkpoint) model = AutoModel.from_pretrained(checkpoint)raw_inputs = ["I've been waiting for a HuggingFace course my whole life.","I hate this so much!", ] inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt") outputs = model(**inputs) print(outputs.last_hidden_state.shape) torch.Size([2, 16, 768])Transformers 模型的輸出格式類似 namedtuple 或字典,可以像上面那樣通過屬性訪問,也可以通過鍵(outputs["last_hidden_state"]),甚至索引訪問(outputs[0])。
對(duì)于情感分析任務(wù),很明顯我們最后需要使用的是一個(gè)文本分類 head。因此,實(shí)際上我們不會(huì)使用 AutoModel 類,而是使用 AutoModelForSequenceClassification:
from transformers import AutoTokenizer from transformers import AutoModelForSequenceClassificationcheckpoint = "distilbert-base-uncased-finetuned-sst-2-english" tokenizer = AutoTokenizer.from_pretrained(checkpoint) model = AutoModelForSequenceClassification.from_pretrained(checkpoint)raw_inputs = ["I've been waiting for a HuggingFace course my whole life.","I hate this so much!", ] inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt") outputs = model(**inputs) print(outputs.logits.shape) torch.Size([2, 2])可以看到,對(duì)于 batch 中的每一個(gè)樣本,模型都會(huì)輸出一個(gè)兩維的向量(每一維對(duì)應(yīng)一個(gè)標(biāo)簽,positive 或 negative)。
對(duì)模型輸出進(jìn)行后處理
由于模型的輸出只是一些數(shù)值,因此并不適合人類閱讀。例如我們打印出上面例子的輸出:
from transformers import AutoTokenizer from transformers import AutoModelForSequenceClassificationcheckpoint = "distilbert-base-uncased-finetuned-sst-2-english" tokenizer = AutoTokenizer.from_pretrained(checkpoint) model = AutoModelForSequenceClassification.from_pretrained(checkpoint)raw_inputs = ["I've been waiting for a HuggingFace course my whole life.","I hate this so much!", ] inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt") outputs = model(**inputs) print(outputs.logits) tensor([[-1.5607, 1.6123],[ 4.1692, -3.3464]], grad_fn=<AddmmBackward0>)模型對(duì)第一個(gè)句子輸出 [?1.5607,1.6123],對(duì)第二個(gè)句子輸出 [4.1692,?3.3464],它們并不是概率值,而是模型最后一層輸出的 logits 值。要將他們轉(zhuǎn)換為概率值,還需要讓它們經(jīng)過一個(gè) SoftMax 層,例如:
import torch predictions = torch.nn.functional.softmax(outputs.logits, dim=-1) print(predictions) tensor([[4.0195e-02, 9.5980e-01],[9.9946e-01, 5.4418e-04]], grad_fn=<SoftmaxBackward0>)所有 Transformers 模型都會(huì)輸出 logits 值,因?yàn)橛?xùn)練時(shí)的損失函數(shù)通常會(huì)自動(dòng)結(jié)合激活函數(shù)(例如 SoftMax)與實(shí)際的損失函數(shù)(例如交叉熵 cross entropy)。
這樣模型的預(yù)測(cè)結(jié)果就是容易理解的概率值:第一個(gè)句子 [0.0402,0.9598],第二個(gè)句子 [0.9995,0.0005]。最后,為了得到對(duì)應(yīng)的標(biāo)簽,可以讀取模型 config 中提供的 id2label 屬性:
print(model.config.id2label) {0: 'NEGATIVE', 1: 'POSITIVE'}于是我們可以得到最終的預(yù)測(cè)結(jié)果:
總結(jié)
在本文中我們初步介紹了如何使用 Transformers 包提供的 pipeline 對(duì)象來處理各種 NLP 任務(wù),并且對(duì) pipeline 背后的工作原理進(jìn)行了簡(jiǎn)單的說明。在下一篇轉(zhuǎn)載文章中,我們會(huì)具體介紹組成 pipeline 的兩個(gè)重要組件模型(Models 類)和分詞器(Tokenizers 類)的參數(shù)以及使用方式。
參考資料:
小昇的博客
Transformers 官方文檔
HuggingFace 在線教程
小昇的Github項(xiàng)目
總結(jié)
以上是生活随笔為你收集整理的Hugging Face 的 Transformers 库快速入门 (一)开箱即用的 pipelines的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript的输出语句
- 下一篇: 计算机在中医学有哪些最新应用,计算机与中