先上開源地址:html
https://github.com/huggingface/pytorch-transformers#quick-tournode
官網:python
https://huggingface.co/pytorch-transformers/index.htmlgit
PyTorch-Transformers(正式名稱爲 pytorch-pretrained-bert)是一個用於天然語言處理(NLP)的最早進的預訓練模型庫。github
該庫目前包含下列模型的 PyTorch 實現、預訓練模型權重、使用腳本和下列模型的轉換工具:json
-
BERT (來自 Google):做者 Jacob Devlin、Ming-Wei Chang、Kenton Lee 和 Kristina Toutanova:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding(《BERT:用於語言理解的深度雙向 Transformer 的預訓練》)服務器
-
GPT (來自 OpenAI):做者 Alec Radford、Karthik Narasimhan、Tim Salimans 和 Ilya Sutskever:Improving Language Understanding by Generative Pre-Training (《經過生成式預訓練提升語言理解能力》)架構
-
GPT-2 (來自 OpenAI):做者
Alec Radford、Jeffrey Wu、Rewon Child、David Luan、Dario Amodei 和 Ilya Sutskever: Language Models are Unsupervised Multitask Learners (《語言模型是無監督的多任務學習器》)分佈式 -
Transformer-XL (來自 Google/CMU):做者 Zihang Dai、Zhilin Yang、Yiming Yang, Jaime Carbonell、Quoc V. Le、Ruslan Salakhutdinov:Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context (《Transformer-XL:超長上下文關係的注意力語言模型》)ide
-
XLNet (來自 Google/CMU):做者 Zihang Dai、Zhilin Yang、Yiming Yang、Jaime Carbonell、Quoc V. Le、Ruslan Salakhutdinov:XLNet: Generalized Autoregressive Pretraining for Language Understanding (《XLNet:用於語言理解的廣義自迴歸預訓練》)
-
XLM (來自 Facebook):做者 Guillaume Lample 和 Alexis Conneau:Cross-lingual Language Model Pretraining (《跨語言的語言模型預訓練》)
這些實現已在幾個數據集上進行測試(參見示例腳本),應該與原始實現的性能至關(例如,BERT 全詞覆蓋(Whole-Word-Masking)在 SQUAD 數據集上的 F1 分數爲 93,OpenAI GPT 在 RocStories 上的 F1 分數爲 88,Transformer-XL 在 WikiText 103 上的 困惑度爲 18.三、XLNet 的 STS-B 上的皮爾遜積矩相關係數爲 0.916)。用戶能夠在官方網站的文檔示例部分中,找到有關性能的更多詳細信息。
安 裝
此 repo 在 Python 2.7 和 3.5+(示例代碼僅在 Python 3.5+ 上經過測試)以及 PyTorch 0.4.1 到 1.1.0 上進行了測試。
使用 pip 進行安裝
pip
install pytorch-transformers
|
從源進行安裝
克隆存儲庫並運行以下命令:
pip install [--editable] .
|
測試
該庫和示例腳本包含了一系列測試。庫測試可在 「tests」 文件夾中找到,示例腳本的測試能夠在 「examples」文件夾 中找到。
這些測試可使用 pytest 運行(若是須要,可使用 pip install pytest 來安裝 pytest)。
你可使用如下命令從克隆存儲庫的根目錄進行測試:
python -m pytest -sv ./pytorch_transformers/tests/
|
|
python -m pytest -sv ./examples/
|
快速指南
讓咱們快速導覽一下 PyTorch-Transformer。每一個模型架構(Bert、GPT、GPT-二、Transformer-XL、XLNet、XLM)的詳細示例都可在完整的文檔中找到。
import torch
|
|
from pytorch_transformers
import *
|
|
# PyTorch-Transformers has a unified API
|
|
# for 6 transformer architectures and 27 pretrained weights.
|
|
# Model | Tokenizer | Pretrained weights shortcut
|
|
MODELS = [(BertModel, BertTokenizer, 'bert-base-uncased'),
|
|
(OpenAIGPTModel, OpenAIGPTTokenizer, 'openai-gpt'),
|
|
(GPT2Model, GPT2Tokenizer, 'gpt2'),
|
|
(TransfoXLModel, TransfoXLTokenizer, 'transfo-xl-wt103'),
|
|
(XLNetModel, XLNetTokenizer, 'xlnet-base-cased'),
|
|
(XLMModel, XLMTokenizer, 'xlm-mlm-enfr-
1024')]
|
|
# Let's encode some text in a sequence of hidden-states using each model:
|
|
for model_class, tokenizer_class, pretrained_weights
in MODELS:
|
|
# Load pretrained model/tokenizer
|
|
tokenizer = tokenizer_class.from_pretrained(pretrained_weights)
|
|
model = model_class.from_pretrained(pretrained_weights)
|
|
# Encode text
|
|
input_ids = torch.tensor([tokenizer.encode("Here is some text to encode")])
|
|
last_hidden_states = model(input_ids)[0] # Models outputs are now tuples
|
|
# Each architecture is provided with several class for fine-tuning on down-stream tasks, e.g.
|
|
BERT_MODEL_CLASSES = [BertModel, BertForPreTraining, BertForMaskedLM, BertForNextSentencePrediction,
|
|
BertForSequenceClassification, BertForMultipleChoice, BertForTokenClassification,
|
|
BertForQuestionAnswering]
|
|
# All the classes for an architecture can be initiated from pretrained weights for this architecture
|
|
# Note that additional weights added for fine-tuning are only initialized
|
|
# and need to be trained on the down-stream task
|
|
tokenizer = BertTokenizer.from_pretrained(from_pretrained('bert-base-uncased')
|
|
for model_class
in BERT_MODEL_CLASSES:
|
|
# Load pretrained model/tokenizer
|
|
model = model_class.from_pretrained('bert-base-uncased')
|
|
# Models can return full list of hidden-states & attentions weights at each layer
|
|
model = model_class.from_pretrained(pretrained_weights,
|
|
output_hidden_states=True,
|
|
output_attentions=True)
|
|
input_ids = torch.tensor([tokenizer.encode("Let's see all hidden-states and attentions on this text")])
|
|
all_hidden_states,
all_attentions = model(input_ids)[-2:]
|
|
# Models are compatible with Torchscript
|
|
model = model_class.from_pretrained(pretrained_weights, torchscript=True)
|
|
traced_model = torch.jit.trace(model, (input_ids,))
|
|
# Simple serialization for models and tokenizers
|
|
model.save_pretrained('./directory/to/save/')
# save
|
|
model = model_class.from_pretrained('./directory/to/save/') # re-load
|
|
tokenizer.save_pretrained('./directory/to/save/')
# save
|
|
tokenizer = tokenizer_class.from_pretrained(pretrained_weights)
|
|
# SOTA examples for GLUE, SQUAD, text generation...
|
微調 / 用法腳本的快速指南
該庫包含幾個示例腳本,這些腳本具備用於 NLU 和 NLG 任務的 SOTA 性能:
-
run_glue.py :一個針對九個不一樣的 GLUE 任務(序列級分類)對 BERT、XLNet 和 XLM 進行微調的示例
-
run_squad.py :一個針對問答數據集 square 2.0(令牌級分類)對 BERT、XLNet 和 XLM 的示例
-
run_generation.py :一個使用 GPT、GPT-二、Transformer-XL 和 XLNet 生成條件語言的示例
-
其餘特定於模型的示例(請參閱文檔)
如下是這些腳本的三個快速使用示例:
run_glue.py :對 GLUE 任務進行微調用於序列分類
通用語言理解評估(General Language Understanding Evaluation benchmark,GLUE)基準是由九條句子或句子對語言理解任務的集合,用於評估和分析天然語言理解系統。
在運行這些 GLUE 任務以前,你應該經過運行此腳本下載 GLUE 數據,並將其解壓縮到某個目錄 $GLUE_DIR。
你還應該安裝示例所需的附加包:
pip install -r ./examples/requirements
.txt
|
export GLUE_DIR=/path/to/glue
|
|
export TASK_NAME=MRPC
|
|
python ./examples/run_glue.py \
|
|
-
-model_type bert \
|
|
-
-model_name_or_path bert-base-uncased \
|
|
-
-task_name $TASK_NAME \
|
|
-
-do_train \
|
|
-
-do_eval \
|
|
-
-do_lower_case \
|
|
-
-data_dir $GLUE_DIR/$TASK_NAME \
|
|
-
-max_seq_length 128 \
|
|
-
-per_gpu_eval_batch_size=8 \
|
|
-
-per_gpu_train_batch_size=8 \
|
|
-
-learning_rate 2e-5 \
|
|
-
-num_train_epochs 3.0 \
|
|
-
-output_dir /tmp/$TASK_NAME/
|
|
其中任務名稱能夠是 CoLA、SST-二、MRPC、STS-B、QQP、MNLI、QNLI、RTE、WNLI 中的一個。
開發集的結果將出如今指定 output_dir 的文本文件「eval_results.txt」中。對於 MNLI,因爲有兩個單獨的 dev 集,匹配的和不匹配的,除了「/tmp/MNLI/」以外,還有一個單獨的輸出文件夾,名爲「/tmp/MNLI-MM/」。
在 STS-B 迴歸任務上對 XLNet 模型進行微調
此示例代碼使用 4 塊 V100 GPU 的服務器上的並行訓練,在 STS-B 語料庫上對 XLNet 進行微調。秉性訓練是使用多個 GPU 的一種簡單方法(但比分佈式訓練速度更慢,靈活性也不如分佈式訓練,見下文)。
export GLUE_DIR=/path/to/glue
|
|
python ./examples/run_glue.py \
|
|
--model_type xlnet \
|
|
--model_name_or_path xlnet-large-cased \
|
|
--do_train \
|
|
--do_eval \
|
|
--task_name=sts-b \
|
|
--data_dir=${GLUE_DIR}/STS-B \
|
|
--output_dir=./proc_data/sts-b-110 \
|
|
--max_seq_length=128 \
|
|
--per_gpu_eval_batch_size=8 \
|
|
--per_gpu_train_batch_size=8 \
|
|
--gradient_accumulation_steps=1 \
|
|
--max_steps=1200 \
|
|
--model_name=xlnet-large-cased \
|
|
--overwrite_output_dir \
|
|
--overwrite_cache \
|
|
--warmup_steps=120
|
在這臺機器上,咱們的批大小爲 32,若是你的機器配置較差,請增長 gradient_accumulation_steps 以達到相同的批大小。這些超參數應該致使在開發集上的皮爾遜積矩相關係數(Pearson correlation coefficient )爲 +0.917 。
在 MRPC 分類任務上對 Bert 模型進行微調
此示例代碼使用 8 塊 V100 GPU 上的分佈式訓練,對 Microsoft Research 語句改寫語料庫(Microsoft Research Paraphrase Corpus,MRPC)中的 Bert 全詞覆蓋模型進行微調,使其達到 F1>92。
使用這些超參數進行訓練,咱們獲得瞭如下結果:
python -m torch.distributed.launch
--nproc_per_node 8 ./examples/run_glue.py \
|
|
--model_type bert \
|
|
--model_name_or_path bert-large-uncased-whole-word-masking \
|
|
--task_name MRPC \
|
|
--do_train \
|
|
--do_eval \
|
|
--do_lower_case \
|
|
--data_dir $GLUE_DIR/MRPC/ \
|
|
--max_seq_length 128 \
|
|
--per_gpu_eval_batch_size=8 \
|
|
--per_gpu_train_batch_size=8 \
|
|
--learning_rate 2e-5 \
|
|
--num_train_epochs 3.0 \
|
|
--output_dir /tmp/mrpc_output/ \
|
|
--overwrite_output_dir \
|
|
--overwrite_cache \
|
使用這些超參數進行訓練,咱們獲得瞭如下結果:
acc =
0.8823529411764706
|
|
acc_and_f1 =
0.901702786377709
|
|
eval_loss =
0.3418912578906332
|
|
f1 =
0.9210526315789473
|
|
global_step =
174
|
|
loss =
0.07231863956341798
|
run_squad.py :對 SQuAD 進行微調用於問答系統
此示例代碼使用 8 塊 V100 GPU 上的分佈式訓練和 BERT 全詞覆蓋模型對 SQuAD 數據集上的 BERT 進行微調,以在 SQuAD 上達到 F1 的分數大於 93:
python -m torch.distributed.launch
--nproc_per_node=8 ./examples/run_squad.py \
|
|
--model_type bert \
|
|
--model_name_or_path bert-large-uncased-whole-word-masking \
|
|
--do_train \
|
|
--do_eval \
|
|
--do_lower_case \
|
|
--train_file $SQUAD_DIR/train-v1.1.json \
|
|
--predict_file $SQUAD_DIR/dev-v1.1.json \
|
|
--learning_rate 3e-5 \
|
|
--num_train_epochs 2 \
|
|
--max_seq_length 384 \
|
|
--doc_stride 128 \
|
|
--output_dir ../models/wwm_uncased_finetuned_squad/ \
|
|
--per_gpu_eval_batch_size=3 \
|
|
--per_gpu_train_batch_size=3 \
|
使用這些超參數進行訓練,咱們獲得瞭如下結果:
python
$SQUAD_DIR/evaluate-v1.1.py $SQUAD_DIR/dev-v1.1.json ../models/wwm_uncased_finetuned_squad/predictions.json
|
|
{
"exact_match": 86.91579943235573, "f1": 93.1532499015869}
|
這是做爲 bert-large-uncased-whole-word-masking-finetuned-squad 提供的模型。
run_generation.py :使用 GPT、GPT-二、Transformer-XL 和 XLNet 生成文本
還包括一個條件生成腳本,用於根據提示生成文本。生成腳本包括 Aman Rusia 提出的技巧,利用 Transformer-XL 和 XLNet 等內存模型得到高質量的生成(包括一個預約義的文本,使短輸入更長)。
下面是演示如何使用 OpenAI GPT-2 模型的小版原本運行腳本:
python ./examples/run_generation.py \
|
|
--model_type=gpt2 \
|
|
--length=20 \
|
|
--model_name_or_path=gpt2 \
|
從 pytorch-pretrained-bert 遷移到 pytorch-transformers
下面是一個快速總結,闡述了從 pytorch-pretrained-bert 遷移到 pytorch-transformers 時應該注意的事項。
模型老是輸出 tuples
從 pytorch-pretrained-bert 遷移到 pytorch-transformers 時,主要的突破性變化是模型的正演方法始終根據模型和配置參數輸出包含各類元素的 tuple。
每一個模型的元組的確切內容,在模型的文檔註釋和文檔中有詳細說明。
在幾乎全部狀況下,你均可以將輸出的第一個元素做爲以前在 pytorch-pretrained-bert 中使用的輸出。
下面是一個 pytorch-pretrained-bert 到 pytorch-transformers 轉換的示例,用於 BertForSequenceClassification 分類模型:
# Let's load our model
|
|
model = BertForSequenceClassification.from_pretrained('bert-base-uncased')
|
|
# If you used to have this line in pytorch-pretrained-bert:
|
|
loss = model(input_ids, labels=labels)
|
|
# Now just use this line in pytorch-transformers to extract the loss from the output tuple:
|
|
outputs = model(input_ids, labels=labels)
|
|
loss = outputs[0]
|
|
# In pytorch-transformers you can also have access to the logits:
|
|
loss, logits = outputs[:2]
|
|
# And even the attention weigths if you configure the model to output them (and other outputs too, see the docstrings and documentation)
|
|
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', output_attentions=True)
|
|
outputs = model(input_ids, labels=labels)
|
|
loss, logits, attentions = outputs
|
序列化
突破性更改:當時用 from_pretrained() 方法實例化時,模型如今默認設置爲評估模式。要訓練它們,不要忘記將它們設置回訓練模式 ( model.train() ),以激活 dropout 模塊。
此外,雖然不是突破性更改,但序列化方法已經標準化,若是你之前使用過任何其餘序列化方法,你可能應該切換到新方法 save_pretrained(save_directory) 。
下面是一個例子:
### Let's load a model
and tokenizer
|
|
model =
BertForSequenceClassification.from_pretrained('bert-base-uncased')
|
|
tokenizer =
BertTokenizer.from_pretrained('bert-base-uncased')
|
|
### Do some stuff
to our model and tokenizer
|
|
# Ex: add
new tokens to the vocabulary and embeddings of our model
|
|
tokenizer.add
_tokens(['[SPECIAL_TOKEN_1]', '[SPECIAL_TOKEN_2]'])
|
|
model.resize
_token_embeddings(len(tokenizer))
|
|
# Train our model
|
|
train(model)
|
|
### Now
let's save our model and tokenizer to a directory
|
|
model.save
_pretrained('./my_saved_model_directory/')
|
|
tokenizer.save
_pretrained('./my_saved_model_directory/')
|
|
### Reload the model
and the tokenizer
|
|
model =
BertForSequenceClassification.from_pretrained('./my_saved_model_directory/')
|
|
tokenizer =
BertTokenizer.from_pretrained('./my_saved_model_directory/')
|
優化器:BertAdam 和 OpenAIAdam 如今是 AdamW,定時任務是標準的 PyTorch schedules。
以前包含的兩個優化器 BertAdam 和 OpenAIAdam ,如今已被單個 AdamW 優化器取代。新的優化器 AdamW 與 PyTorch AdamW 優化器 API 相匹配。
任務調度如今是標準的 PyTorch learning rate schedulers 程序,而再也不是優化器的一部分。
下面是 BertAdam 到 AdamW 的轉換示例,前者具備線性預熱(linear warmup)和衰減計劃,後者有相同的任務調度。
# Parameters:
|
|
lr = 1e-3
|
|
num_total_steps = 1000
|
|
num_warmup_steps = 100
|
|
warmup_proportion = float(num_warmup_steps) / float(num_total_steps) # 0.1
|
|
### Previously BertAdam optimizer was instantiated like this:
|
|
optimizer = BertAdam(model.parameters(),
lr=lr, schedule='warmup_linear', warmup=warmup_proportion, t_total=num_total_steps)
|
|
### and used like this:
|
|
for batch in train_data:
|
|
loss = model(batch)
|
|
loss.backward()
|
|
optimizer.
step()
|
|
### In PyTorch-Transformers, optimizer and schedules are splitted and instantiated like this:
|
|
optimizer = AdamW(model.parameters(),
lr=lr, correct_bias=False) # To reproduce BertAdam specific behavior set correct_bias=False
|
|
scheduler = WarmupLinearSchedule(optimizer,
warmup_steps=num_warmup_steps, t_total=num_total_steps) # PyTorch scheduler
|
|
### and used like this:
|
|
for batch in train_data:
|
|
loss = model(batch)
|
|
loss.backward()
|
|
scheduler.
step()
|
|
optimizer.
step()
|