跳转到主要内容

PyTorch版本的Google AI BERT模型,包含加载Google预训练模型的脚本

项目描述

PyTorch预训练BERT:预训练变换器的庞大且不断扩展的存储库

CircleCI

此存储库包含与原始TensorFlow实现一对一的PyTorch重实现、预训练模型和微调示例,用于

这些实现已在几个数据集上进行了测试(见示例),并且应该与相关TensorFlow实现的性能相匹配(例如,BERT在SQuAD上约为91 F1,OpenAI GPT在RocStories上约为88 F1,Transformer-XL在WikiText 103上的困惑度约为18.3)。您可以在下面的示例部分找到更多详细信息。

以下是有关这些模型的一些信息

BERT 与由Jacob Devlin、Ming-Wei Chang、Kenton Lee和Kristina Toutanova撰写的论文 BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 同时发布。此PyTorch实现的BERT附带Google的预训练模型、示例、笔记本,以及一个命令行界面,用于加载BERT的任何预训练TensorFlow检查点。

OpenAI GPT 与论文《通过生成预训练改进语言理解》一同发布,该论文由Alec Radford、Karthik Narasimhan、Tim Salimans和Ilya Sutskever撰写。[链接](https://blog.openai.com/language-unsupervised/)。这是OpenAI GPT的PyTorch实现,是对[HuggingFace的PyTorch实现](https://github.com/huggingface/pytorch-openai-transformer-lm)的改编,并提供了[OpenAI的预训练模型](https://github.com/openai/finetune-transformer-lm)和用于将预训练的NumPy检查点转换为PyTorch的命令行界面。

Google/CMU的Transformer-XL 与论文《Transformer-XL: 超越固定长度上下文的注意力语言模型》一同发布,该论文由Zihang Dai*、Zhilin Yang*、Yiming Yang、Jaime Carbonell、Quoc V. Le和Ruslan Salakhutdinov撰写。[链接](http://arxiv.org/abs/1901.02860)。这是Transformer-XL的PyTorch实现,是对[原始PyTorch实现](https://github.com/kimiyoung/transformer-xl)的改编,略微修改以匹配TensorFlow实现的性能,并允许复用预训练的权重。提供命令行界面以将TensorFlow检查点转换为PyTorch模型。

OpenAI GPT-2 与论文《语言模型是未监督的多任务学习器》一同发布,该论文由Alec Radford*、Jeffrey Wu*、Rewon Child、David Luan、Dario Amodei**和Ilya Sutskever**撰写。[链接](https://blog.openai.com/better-language-models/)。这是OpenAI GPT-2的PyTorch实现,是对[OpenAI的实现](https://github.com/openai/gpt-2)的改编,并提供了[OpenAI的预训练模型](https://github.com/openai/gpt-2)和用于将TensorFlow检查点转换为PyTorch的命令行界面。

内容

章节 描述
安装 如何安装包
概述 包的概述
用法 快速入门示例
文档 详细文档
示例 如何微调Bert的详细示例
笔记本 关于提供的Jupyter笔记本的介绍
TPU 关于TPU支持和预训练脚本的说明
命令行界面 将TensorFlow检查点转换为PyTorch的转储

安装

该仓库已在Python 2.7和3.5+(示例仅在python 3.5+上测试)以及PyTorch 0.4.1/1.0.0上进行了测试

使用pip

以下是通过pip安装PyTorch预训练bert的方法

pip install pytorch-pretrained-bert

如果您想重现《OpenAI GPT》论文中的原始标记过程,您需要安装ftfy(如果您使用Python 2,则限制在版本4.4.3)和SpaCy

pip install spacy ftfy==4.4.3
python -m spacy download en

如果您不安装ftfySpaCy,则OpenAI GPT标记器将默认使用BERT的BasicTokenizer进行标记,然后是字节对编码(对于大多数使用应该没问题,不用担心)。

从源码

克隆仓库并运行

pip install [--editable] .

这里,如果您想重现OpenAI GPT模型中的原始标记过程,您需要安装ftfy(如果您使用Python 2,则限制在版本4.4.3)和SpaCy

pip install spacy ftfy==4.4.3
python -m spacy download en

同样,如果您不安装ftfySpaCy,OpenAI GPT标记器将默认使用BERT的BasicTokenizer进行标记,然后是字节对编码(对于大多数使用应该没问题)。

测试文件夹中包含一系列测试,可以使用pytest运行(如果需要安装pytest:pip install pytest)。

您可以使用以下命令运行测试

python -m pytest -sv tests/

概述

此包包含以下类,可以在Python中导入,并在readme的文档部分中详细说明

  • 八个预训练权重的Bert PyTorch模型(在modeling.py文件中)

    • BertModel - 原始BERT Transformer模型(完全预训练
    • BertForMaskedLM - BERT Transformer,顶部添加了预训练的掩码语言模型头(完全预训练
    • BertForNextSentencePrediction - BERT Transformer,顶部添加了预训练的下一句预测分类器(完全预训练
    • BertForPreTraining - BERT Transformer,顶部添加了掩码语言模型头和下一句预测分类器(完全预训练
    • BertForSequenceClassification - BERT Transformer,顶部添加了序列分类头(BERT Transformer是 预训练,序列分类头 仅初始化,需要训练
    • BertForMultipleChoice - BERT Transformer,顶部添加了多选分类头(用于Swag等任务)(BERT Transformer是 预训练,多选分类头 仅初始化,需要训练
    • BertForTokenClassification - BERT Transformer,顶部添加了标记分类头(BERT Transformer是 预训练,标记分类头 仅初始化,需要训练
    • BertForQuestionAnswering - BERT Transformer,顶部添加了标记分类头(BERT Transformer是 预训练,标记分类头 仅初始化,需要训练
  • 三个 OpenAI GPT PyTorch模型(torch.nn.Module)带有预训练权重(在modeling_openai.py文件中)

    • OpenAIGPTModel - 原始OpenAI GPT Transformer模型(完全预训练
    • OpenAIGPTLMHeadModel - OpenAI GPT Transformer,顶部添加了绑定语言模型头(完全预训练
    • OpenAIGPTDoubleHeadsModel - OpenAI GPT Transformer,顶部添加了绑定语言模型头和多个选择分类头(OpenAI GPT Transformer是 预训练,多个选择分类头 仅初始化,需要训练
  • 两个 Transformer-XL PyTorch模型(torch.nn.Module)带有预训练权重(在modeling_transfo_xl.py文件中)

    • TransfoXLModel - Transformer-XL模型,输出最后隐藏状态和记忆单元(完全预训练
    • TransfoXLLMHeadModel - Transformer-XL,顶部添加了绑定自适应softmax头用于语言模型,输出logits/loss和记忆单元(完全预训练
  • 三个 OpenAI GPT-2 PyTorch模型(torch.nn.Module)带有预训练权重(在modeling_gpt2.py文件中)

    • GPT2Model - 原始OpenAI GPT-2 Transformer模型(完全预训练
    • GPT2LMHeadModel - OpenAI GPT-2 Transformer,顶部添加了绑定语言模型头(完全预训练
    • GPT2DoubleHeadsModel - OpenAI GPT-2 Transformer,顶部添加了绑定语言模型头和多个选择分类头(OpenAI GPT-2 Transformer是 预训练,多个选择分类头 仅初始化,需要训练
  • BERT分词器(使用word-piece)(在tokenization.py文件中)

    • BasicTokenizer - 基础分词(标点分割、小写化等),
    • WordpieceTokenizer - WordPiece分词,
    • BertTokenizer - 执行端到端分词,即先进行基础分词,然后进行WordPiece分词。
  • OpenAI GPT分词器(使用Byte-Pair-Encoding)(在tokenization_openai.py文件中)

    • OpenAIGPTTokenizer - 执行Byte-Pair-Encoding(BPE)分词。
  • Transformer-XL分词器(按频率排序的词token,用于自适应softmax)(在tokenization_transfo_xl.py文件中)

    • OpenAIGPTTokenizer - 执行词分词,并可按语料库中的词频排序,用于自适应softmax。
  • OpenAI GPT-2分词器(使用字节级Byte-Pair-Encoding)(在tokenization_gpt2.py文件中)

    • GPT2Tokenizer - 执行字节级Byte-Pair-Encoding(BPE)分词。
  • BERT优化器(在optimization.py文件中)

    • BertAdam - 带权重衰减修正、预热和线性衰减学习率的Adam算法的BERT版本。
  • OpenAI GPT优化器(在optimization_openai.py文件中)

    • OpenAIAdam - 带权重衰减修正、预热和线性衰减学习率的OpenAI GPT版本的Adam算法。
  • BERT、OpenAI GPT和Transformer-XL的配置类(在相应的modeling.pymodeling_openai.pymodeling_transfo_xl.py文件中)

    • BertConfig - 配置类,用于存储BertModel的配置,并提供了从JSON配置文件中读取和写入的实用工具。
    • OpenAIGPTConfig - 配置类,用于存储OpenAIGPTModel的配置,并提供了从JSON配置文件中读取和写入的实用工具。
    • GPT2Config - 配置类,用于存储GPT2Model的配置,并提供了从JSON配置文件中读取和写入的实用工具。
    • TransfoXLConfig - 配置类,用于存储TransfoXLModel的配置,并提供了从JSON配置文件中读取和写入的实用工具。

存储库还包含

  • 五个使用BERT的示例(在examples文件夹中)

    • extract_features.py - 展示如何从BertModel的实例中提取隐藏状态,
    • run_classifier.py - 展示如何将BertForSequenceClassification的实例微调在GLUE的MRPC任务上,
    • run_squad.py - 展示如何将BertForQuestionAnswering的实例微调在SQuAD v1.0和SQuAD v2.0任务上。
    • run_swag.py - 展示如何将BertForMultipleChoice的实例微调在Swag任务上。
    • simple_lm_finetuning.py - 展示如何将BertForPretraining的实例微调在目标文本语料库上。
  • 一个使用OpenAI GPT的示例(在examples文件夹中)

    • run_openai_gpt.py - 展示如何将OpenGPTDoubleHeadsModel的实例微调在RocStories任务上。
  • 一个使用Transformer-XL的示例(在examples文件夹中)

    • run_transfo_xl.py - 展示如何在 WikiText 103 上加载和评估 TransfoXLLMHeadModel 的预训练模型。
  • 一个如何在不限条件和交互模式下使用 OpenAI GPT-2 的示例(在 examples 文件夹 中)

    • run_gpt2.py - 展示如何使用 OpenAI GPT-2 的一个实例 GPT2LMHeadModel 生成文本(与原始 OpenAI GPT-2 示例相同)。

    这些示例在本文档的 示例 部分中详细说明。

  • 三个用于检查 TensorFlow 和 PyTorch 模型行为是否一致的笔记本(在 notebooks 文件夹 中)

    这些笔记本在本文档的 笔记本 部分中详细说明。

  • 一个命令行界面,用于将 TensorFlow 检查点(BERT、Transformer-XL)或 NumPy 检查点(OpenAI)转换为相关 PyTorch 模型的 PyTorch 保存格式

    此 CLI 在本文档的 命令行界面 部分中详细说明。

用法

BERT

以下是一个使用 Google AI 的预训练 Bert base uncased 模型,结合 BertTokenizerBertModelBertForMaskedLM 类的快速入门示例。有关这些类的详细信息,请参阅下面的 doc 部分。

首先,让我们使用 BertTokenizer 准备一个标记化输入

import torch
from pytorch_pretrained_bert import BertTokenizer, BertModel, BertForMaskedLM

# OPTIONAL: if you want to have more information on what's happening, activate the logger as follows
import logging
logging.basicConfig(level=logging.INFO)

# Load pre-trained model tokenizer (vocabulary)
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

# Tokenized input
text = "[CLS] Who was Jim Henson ? [SEP] Jim Henson was a puppeteer [SEP]"
tokenized_text = tokenizer.tokenize(text)

# Mask a token that we will try to predict back with `BertForMaskedLM`
masked_index = 8
tokenized_text[masked_index] = '[MASK]'
assert tokenized_text == ['[CLS]', 'who', 'was', 'jim', 'henson', '?', '[SEP]', 'jim', '[MASK]', 'was', 'a', 'puppet', '##eer', '[SEP]']

# Convert token to vocabulary indices
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)
# Define sentence A and B indices associated to 1st and 2nd sentences (see paper)
segments_ids = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1]

# Convert inputs to PyTorch tensors
tokens_tensor = torch.tensor([indexed_tokens])
segments_tensors = torch.tensor([segments_ids])

让我们看看如何使用 BertModel 获取隐藏状态

# Load pre-trained model (weights)
model = BertModel.from_pretrained('bert-base-uncased')
model.eval()

# If you have a GPU, put everything on cuda
tokens_tensor = tokens_tensor.to('cuda')
segments_tensors = segments_tensors.to('cuda')
model.to('cuda')

# Predict hidden states features for each layer
with torch.no_grad():
    encoded_layers, _ = model(tokens_tensor, segments_tensors)
# We have a hidden states for each of the 12 layers in model bert-base-uncased
assert len(encoded_layers) == 12

以及如何使用 BertForMaskedLM

# Load pre-trained model (weights)
model = BertForMaskedLM.from_pretrained('bert-base-uncased')
model.eval()

# If you have a GPU, put everything on cuda
tokens_tensor = tokens_tensor.to('cuda')
segments_tensors = segments_tensors.to('cuda')
model.to('cuda')

# Predict all tokens
with torch.no_grad():
    predictions = model(tokens_tensor, segments_tensors)

# confirm we were able to predict 'henson'
predicted_index = torch.argmax(predictions[0, masked_index]).item()
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
assert predicted_token == 'henson'

OpenAI GPT

以下是一个使用 OpenAI 的预训练模型以及 OpenAIGPTTokenizerOpenAIGPTModelOpenAIGPTLMHeadModel 类的快速入门示例。有关这些类的详细信息,请参阅下面的 doc 部分。

首先,让我们使用 OpenAIGPTTokenizer 准备一个标记化输入

import torch
from pytorch_pretrained_bert import OpenAIGPTTokenizer, OpenAIGPTModel, OpenAIGPTLMHeadModel

# OPTIONAL: if you want to have more information on what's happening, activate the logger as follows
import logging
logging.basicConfig(level=logging.INFO)

# Load pre-trained model tokenizer (vocabulary)
tokenizer = OpenAIGPTTokenizer.from_pretrained('openai-gpt')

# Tokenized input
text = "Who was Jim Henson ? Jim Henson was a puppeteer"
tokenized_text = tokenizer.tokenize(text)

# Convert token to vocabulary indices
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)

# Convert inputs to PyTorch tensors
tokens_tensor = torch.tensor([indexed_tokens])

让我们看看如何使用 OpenAIGPTModel 获取隐藏状态

# Load pre-trained model (weights)
model = OpenAIGPTModel.from_pretrained('openai-gpt')
model.eval()

# If you have a GPU, put everything on cuda
tokens_tensor = tokens_tensor.to('cuda')
model.to('cuda')

# Predict hidden states features for each layer
with torch.no_grad():
    hidden_states = model(tokens_tensor)

以及如何使用 OpenAIGPTLMHeadModel

# Load pre-trained model (weights)
model = OpenAIGPTLMHeadModel.from_pretrained('openai-gpt')
model.eval()

# If you have a GPU, put everything on cuda
tokens_tensor = tokens_tensor.to('cuda')
model.to('cuda')

# Predict all tokens
with torch.no_grad():
    predictions = model(tokens_tensor)

# get the predicted last token
predicted_index = torch.argmax(predictions[0, -1, :]).item()
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
assert predicted_token == '.</w>'

Transformer-XL

以下是一个使用在 WikiText-103 上预训练的 Transformer-XL 模型以及 TransfoXLTokenizerTransfoXLModelTransfoXLLMHeadModel 类的快速入门示例。有关这些类的详细信息,请参阅下面的 doc 部分。

首先,让我们使用 TransfoXLTokenizer 准备一个标记化输入

import torch
from pytorch_pretrained_bert import TransfoXLTokenizer, TransfoXLModel, TransfoXLLMHeadModel

# OPTIONAL: if you want to have more information on what's happening, activate the logger as follows
import logging
logging.basicConfig(level=logging.INFO)

# Load pre-trained model tokenizer (vocabulary from wikitext 103)
tokenizer = TransfoXLTokenizer.from_pretrained('transfo-xl-wt103')

# Tokenized input
text_1 = "Who was Jim Henson ?"
text_2 = "Jim Henson was a puppeteer"
tokenized_text_1 = tokenizer.tokenize(text_1)
tokenized_text_2 = tokenizer.tokenize(text_2)

# Convert token to vocabulary indices
indexed_tokens_1 = tokenizer.convert_tokens_to_ids(tokenized_text_1)
indexed_tokens_2 = tokenizer.convert_tokens_to_ids(tokenized_text_2)

# Convert inputs to PyTorch tensors
tokens_tensor_1 = torch.tensor([indexed_tokens_1])
tokens_tensor_2 = torch.tensor([indexed_tokens_2])

让我们看看如何使用 TransfoXLModel 获取隐藏状态

# Load pre-trained model (weights)
model = TransfoXLModel.from_pretrained('transfo-xl-wt103')
model.eval()

# If you have a GPU, put everything on cuda
tokens_tensor_1 = tokens_tensor_1.to('cuda')
tokens_tensor_2 = tokens_tensor_2.to('cuda')
model.to('cuda')

with torch.no_grad():
    # Predict hidden states features for each layer
    hidden_states_1, mems_1 = model(tokens_tensor_1)
    # We can re-use the memory cells in a subsequent call to attend a longer context
    hidden_states_2, mems_2 = model(tokens_tensor_2, mems=mems_1)

以及如何使用 TransfoXLLMHeadModel

# Load pre-trained model (weights)
model = TransfoXLLMHeadModel.from_pretrained('transfo-xl-wt103')
model.eval()

# If you have a GPU, put everything on cuda
tokens_tensor_1 = tokens_tensor_1.to('cuda')
tokens_tensor_2 = tokens_tensor_2.to('cuda')
model.to('cuda')

with torch.no_grad():
    # Predict all tokens
    predictions_1, mems_1 = model(tokens_tensor_1)
    # We can re-use the memory cells in a subsequent call to attend a longer context
    predictions_2, mems_2 = model(tokens_tensor_2, mems=mems_1)

# get the predicted last token
predicted_index = torch.argmax(predictions_2[0, -1, :]).item()
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
assert predicted_token == 'who'

OpenAI GPT-2

以下是一个使用 OpenAI 的预训练模型以及 GPT2TokenizerGPT2ModelGPT2LMHeadModel 类的快速入门示例。有关这些类的详细信息,请参阅下面的 doc 部分。

首先,让我们使用 GPT2Tokenizer 准备一个标记化输入

import torch
from pytorch_pretrained_bert import GPT2Tokenizer, GPT2Model, GPT2LMHeadModel

# OPTIONAL: if you want to have more information on what's happening, activate the logger as follows
import logging
logging.basicConfig(level=logging.INFO)

# Load pre-trained model tokenizer (vocabulary)
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')

# Encode some inputs
text_1 = "Who was Jim Henson ?"
text_2 = "Jim Henson was a puppeteer"
indexed_tokens_1 = tokenizer.encode(text_1)
indexed_tokens_2 = tokenizer.encode(text_2)

# Convert inputs to PyTorch tensors
tokens_tensor_1 = torch.tensor([indexed_tokens_1])
tokens_tensor_2 = torch.tensor([indexed_tokens_2])

让我们看看如何使用 GPT2Model 获取隐藏状态

# Load pre-trained model (weights)
model = GPT2Model.from_pretrained('gpt2')
model.eval()

# If you have a GPU, put everything on cuda
tokens_tensor_1 = tokens_tensor_1.to('cuda')
tokens_tensor_2 = tokens_tensor_2.to('cuda')
model.to('cuda')

# Predict hidden states features for each layer
with torch.no_grad():
    hidden_states_1, past = model(tokens_tensor_1)
    # past can be used to reuse precomputed hidden state in a subsequent predictions
    # (see beam-search examples in the run_gpt2.py example).
    hidden_states_2, past = model(tokens_tensor_2, past=past)

以及如何使用 GPT2LMHeadModel

# Load pre-trained model (weights)
model = GPT2LMHeadModel.from_pretrained('gpt2')
model.eval()

# If you have a GPU, put everything on cuda
tokens_tensor_1 = tokens_tensor_1.to('cuda')
tokens_tensor_2 = tokens_tensor_2.to('cuda')
model.to('cuda')

# Predict all tokens
with torch.no_grad():
    predictions_1, past = model(tokens_tensor_1)
    # past can be used to reuse precomputed hidden state in a subsequent predictions
    # (see beam-search examples in the run_gpt2.py example).
    predictions_2, past = model(tokens_tensor_2, past=past)

# get the predicted last token
predicted_index = torch.argmax(predictions_2[0, -1, :]).item()
predicted_token = tokenizer.decode([predicted_index])

文档

以下是该包中类的详细文档以及如何使用它们

子章节 描述
加载预训练权重 如何加载 Google AI/OpenAI 的预训练权重或 PyTorch 保存实例
序列化最佳实践 如何保存和重新加载微调模型
配置 BERT、GPT、GPT-2 和 Transformer-XL 的配置类 API
模型 BERT、GPT、GPT-2 和 Transformer-XL 的 PyTorch 模型类 API
标记化器 BERT、GPT、GPT-2 和 Transformer-XL 的标记化器类 API
优化器 优化器 API

加载 Google AI 或 OpenAI 预训练权重或 PyTorch 导出文件

要加载Google AI或OpenAI的预训练模型或PyTorch保存的模型(使用torch.save()保存的BertForPreTraining实例),可以实例化PyTorch模型类和分词器,如下所示:

model = BERT_CLASS.from_pretrained(PRE_TRAINED_MODEL_NAME_OR_PATH, cache_dir=None)

其中

  • BERT_CLASS可以是加载词汇表的分词器(BertTokenizerOpenAIGPTTokenizer类)或以下八个BERT或三个OpenAI GPT PyTorch模型类之一(用于加载预训练权重):BertModelBertForMaskedLMBertForNextSentencePredictionBertForPreTrainingBertForSequenceClassificationBertForTokenClassificationBertForMultipleChoiceBertForQuestionAnsweringOpenAIGPTModelOpenAIGPTLMHeadModelOpenAIGPTDoubleHeadsModel,以及

  • PRE_TRAINED_MODEL_NAME_OR_PATH可以是

    • 列表中选择的Google AI或OpenAI预训练模型的快捷名称

      • bert-base-uncased:12层,768个隐藏层,12个头,1.1亿参数
      • bert-large-uncased:24层,1024个隐藏层,16个头,3.4亿参数
      • bert-base-cased:12层,768个隐藏层,12个头,1.1亿参数
      • bert-large-cased:24层,1024个隐藏层,16个头,3.4亿参数
      • bert-base-multilingual-uncased:(原版,不建议)102种语言,12层,768个隐藏层,12个头,1.1亿参数
      • bert-base-multilingual-cased(新版,推荐)104种语言,12层,768个隐藏层,12个头,1.1亿参数
      • bert-base-chinese:简体中文和繁体中文,12层,768个隐藏层,12个头,1.1亿参数
      • openai-gpt:OpenAI英语模型,12层,768个隐藏层,12个头,1.1亿参数
      • transfo-xl-wt103:在wikitext-103上训练的Transformer-XL英语模型,18层,1024个隐藏层,16个头,2.57亿参数
      • gpt2:OpenAI GPT-2英语模型,12层,768个隐藏层,12个头,1.17亿参数
    • 指向包含以下内容的预训练模型存档的路径或URL:

      • bert_config.jsonopenai_gpt_config.json:模型的配置文件,以及
      • pytorch_model.bin:使用torch.save()保存的预训练实例的PyTorch存档(BertForPreTrainingOpenAIGPTModelTransfoXLModelGPT2LMHeadModel

    如果PRE_TRAINED_MODEL_NAME_OR_PATH是快捷名称,预训练权重将从AWS S3下载(请参阅此处链接链接)并存储在缓存文件夹中,以避免未来的下载(缓存文件夹位于~/.pytorch_pretrained_bert/)。

  • cache_dir可以是下载和缓存预训练模型权重的特定目录的路径。此选项特别适用于您使用分布式训练时:为了避免对相同权重的并发访问,您可以设置例如cache_dir='./pretrained_model_{}'.format(args.local_rank)(有关更多信息,请参阅分布式训练部分)。

Uncased表示在WordPiece分词之前文本已被转换为小写,例如,John Smith变为john smith。未标记的大小写模型还会删除任何重音标记。Cased表示保留真实的字母大小写和重音标记。通常,未标记的大小写模型更好,除非您知道大小写信息对于您的任务很重要(例如,命名实体识别或词性标注)。有关多语言和中文模型的信息,请参阅多语言README或原始TensorFlow存储库。

当使用uncased模型时,请确保将--do_lower_case传递给示例训练脚本(如果您使用自己的脚本并自行加载分词器,则可以将do_lower_case=True传递给FullTokenizer)。

示例

# BERT
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased', do_lower_case=True, do_basic_tokenize=True)
model = BertForSequenceClassification.from_pretrained('bert-base-uncased')

# OpenAI GPT
tokenizer = OpenAIGPTTokenizer.from_pretrained('openai-gpt')
model = OpenAIGPTModel.from_pretrained('openai-gpt')

# Transformer-XL
tokenizer = TransfoXLTokenizer.from_pretrained('transfo-xl-wt103')
model = TransfoXLModel.from_pretrained('transfo-xl-wt103')

# OpenAI GPT-2
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
model = GPT2Model.from_pretrained('gpt2')

序列化最佳实践

本节解释了如何保存和重新加载微调模型(BERT、GPT、GPT-2和Transformer-XL)。您需要保存以下三种类型的文件才能重新加载微调模型

  • 模型本身,应按照PyTorch序列化最佳实践进行保存,
  • 模型的配置文件,它被保存为JSON文件,以及
  • 词汇表(以及基于BPE的模型GPT和GPT-2的合并)。

以下是推荐将模型、配置和词汇表保存到output_dir目录的方法,并在之后重新加载模型和分词器。

from pytorch_pretrained_bert import WEIGHTS_NAME, CONFIG_NAME

output_dir = "./models/"

# Step 1: Save a model, configuration and vocabulary that you have fine-tuned

# If we have a distributed model, save only the encapsulated model
# (it was wrapped in PyTorch DistributedDataParallel or DataParallel)
model_to_save = model.module if hasattr(model, 'module') else model

# If we save using the predefined names, we can load using `from_pretrained`
output_model_file = os.path.join(output_dir, WEIGHTS_NAME)
output_config_file = os.path.join(output_dir, CONFIG_NAME)

torch.save(model_to_save.state_dict(), output_model_file)
model_to_save.config.to_json_file(output_config_file)
tokenizer.save_vocabulary(output_dir)

# Step 2: Re-load the saved model and vocabulary

# Example for a Bert model
model = BertForQuestionAnswering.from_pretrained(output_dir)
tokenizer = BertTokenizer.from_pretrained(output_dir, do_lower_case=args.do_lower_case)  # Add specific options if needed
# Example for a GPT model
model = OpenAIGPTDoubleHeadsModel.from_pretrained(output_dir)
tokenizer = OpenAIGPTTokenizer.from_pretrained(output_dir)

如果您想为每种类型的文件使用特定的路径,以下是另一种保存和重新加载模型的方法。

output_model_file = "./models/my_own_model_file.bin"
output_config_file = "./models/my_own_config_file.bin"
output_vocab_file = "./models/my_own_vocab_file.bin"

# Step 1: Save a model, configuration and vocabulary that you have fine-tuned

# If we have a distributed model, save only the encapsulated model
# (it was wrapped in PyTorch DistributedDataParallel or DataParallel)
model_to_save = model.module if hasattr(model, 'module') else model

torch.save(model_to_save.state_dict(), output_model_file)
model_to_save.config.to_json_file(output_config_file)
tokenizer.save_vocabulary(output_vocab_file)

# Step 2: Re-load the saved model and vocabulary

# We didn't save using the predefined WEIGHTS_NAME, CONFIG_NAME names, we cannot load using `from_pretrained`.
# Here is how to do it in this situation:

# Example for a Bert model
config = BertConfig.from_json_file(output_config_file)
model = BertForQuestionAnswering(config)
state_dict = torch.load(output_model_file)
model.load_state_dict(state_dict)
tokenizer = BertTokenizer(output_vocab_file, do_lower_case=args.do_lower_case)

# Example for a GPT model
config = OpenAIGPTConfig.from_json_file(output_config_file)
model = OpenAIGPTDoubleHeadsModel(config)
state_dict = torch.load(output_model_file)
model.load_state_dict(state_dict)
tokenizer = OpenAIGPTTokenizer(output_vocab_file)

配置

模型(BERT、GPT、GPT-2和Transformer-XL)是由包含模型参数(层数、维度等)的配置类定义和构建的,还包含一些从JSON配置文件读取和写入的实用工具。相应的配置类包括:

  • BertConfig用于BertModel和BERT类实例。
  • OpenAIGPTConfig用于OpenAIGPTModel和OpenAI GPT类实例。
  • GPT2Config用于GPT2Model和OpenAI GPT-2类实例。
  • TransfoXLConfig用于TransfoXLModel和Transformer-XL类实例。

这些配置类包含一些加载和保存配置的实用工具。

  • from_dict(cls, json_object):一个类方法,用于从Python参数字典中构建配置。返回配置类的实例。
  • from_json_file(cls, json_file):一个类方法,用于从参数的json文件中构建配置。返回配置类的实例。
  • to_dict():将实例序列化为Python字典。返回一个字典。
  • to_json_string():将实例序列化为JSON字符串。返回一个字符串。
  • to_json_file(json_file_path):将实例保存到JSON文件。

模型

1. BertModel

BertModel是一个基本的BERT Transformer模型,包含一个求和的标记、位置和序列嵌入层,随后是一系列相同的自注意力块(BERT-base为12个,BERT-large为24个)。

输入和输出与TensorFlow模型的输入和输出相同。

我们在这里详细说明。此模型以输入modeling.py

  • input_ids:一个形状为[batch_size, sequence_length]的torch.LongTensor,包含词汇中的词标记索引(参见脚本中的标记预处理逻辑 extract_features.pyrun_classifier.pyrun_squad.py),以及
  • token_type_ids:一个可选的形状为[batch_size, sequence_length]的torch.LongTensor,包含选择的标记类型索引,范围在[0, 1]。类型0对应于sentence A标记,类型1对应于sentence B标记(参见BERT论文以获取更多详细信息)。
  • attention_mask:一个可选的形状为[batch_size, sequence_length]的torch.LongTensor,包含选择的索引,范围在[0, 1]。它是一个掩码,用于当某些输入序列长度小于当前批次的最大输入序列长度时。它是我们通常用于长度可变句子的批次的注意力的掩码。
  • output_all_encoded_layers:一个布尔值,用于控制encoded_layers输出的内容,如下所述。默认值:True

此模型输出一个元组,由以下组成:

  • encoded_layers:由output_encoded_layers参数的值控制

    • output_all_encoded_layers=True:输出每个注意力块末尾的编码隐藏状态列表(即BERT-base为12个完整序列,BERT-large为24个),每个编码隐藏状态是一个形状为[batch_size, sequence_length, hidden_size]的torch.FloatTensor,
    • output_all_encoded_layers=False:仅输出最后一个注意力块对应的编码隐藏状态,即一个形状为[batch_size, sequence_length, hidden_size]的单一torch.FloatTensor,
  • pooled_output:一个形状为[batch_size, hidden_size]的torch.FloatTensor,它是与输入的第一个字符关联的隐藏状态上预训练的分类器(CLF)的输出,用于Next-Sentence任务(参见BERT的论文)。

以下是如何使用此类的一个示例,见 extract_features.py 脚本,该脚本可以用于提取给定输入的模型隐藏状态。

2. BertForPreTraining

BertForPreTraining 包含跟随两个预训练头的 BertModel Transformer

  • 掩码语言模型头,以及
  • 下一句分类头。

输入 包含了 BertModel 类的输入以及两个可选标签

  • masked_lm_labels:掩码语言模型标签:形状为 [batch_size, sequence_length] 的 torch.LongTensor,索引选择在 [-1, 0, ..., vocab_size] 中。所有设置为 -1 的标签将被忽略(掩码),只计算在 [0, ..., vocab_size] 中设置的标签的损失
  • next_sentence_label:下一句分类损失:形状为 [batch_size] 的 torch.LongTensor,索引选择在 [0, 1] 中。0 => 下一句是延续,1 => 下一句是随机句子。

输出:

  • 如果 masked_lm_labelsnext_sentence_label 不是 None:输出总损失,它是掩码语言模型损失和下一句分类损失的加和。

  • 如果 masked_lm_labelsnext_sentence_labelNone:输出一个包含

    • 掩码语言模型的对数几率,以及
    • 下一句分类的对数几率的元组。

以下是如何使用此类的一个示例,见 run_lm_finetuning.py 脚本,该脚本可用于在您特定的不同文本语料库上微调 BERT 语言模型。如果语言风格与原始 BERT 训练语料库(Wiki + BookCorpus)不同,这应该会提高模型性能。

3. BertForMaskedLM

BertForMaskedLM 包含跟随(可能)预训练的掩码语言模型头的 BertModel Transformer

输入 包含了 BertModel 类的输入以及可选标签

  • masked_lm_labels:掩码语言模型标签:形状为 [batch_size, sequence_length] 的 torch.LongTensor,索引选择在 [-1, 0, ..., vocab_size] 中。所有设置为 -1 的标签将被忽略(掩码),只计算在 [0, ..., vocab_size] 中设置的标签的损失

输出:

  • 如果 masked_lm_labels 不是 None:输出掩码语言模型损失。
  • 如果 masked_lm_labelsNone:输出掩码语言模型的对数几率。

4. BertForNextSentencePrediction

BertForNextSentencePrediction 包含跟随下一句分类头的 BertModel Transformer

输入 包含了 BertModel 类的输入以及一个可选标签

  • next_sentence_label:下一句分类损失:形状为 [batch_size] 的 torch.LongTensor,索引选择在 [0, 1] 中。0 => 下一句是延续,1 => 下一句是随机句子。

输出:

  • 如果 next_sentence_label 不是 None:输出下一句分类损失。
  • 如果 next_sentence_labelNone:输出下一句分类的对数几率。

5. BertForSequenceClassification

BertForSequenceClassification 是一个微调模型,包含 BertModel 以及在 BertModel 上方的序列级(序列或序列对)分类器。

序列级分类器是一个线性层,它以输入序列中第一个字符的最后一个隐藏状态作为输入(参见 BERT 论文中的图 3a 和 3b)。

以下是如何使用此类的一个示例,见 run_classifier.py 脚本,该脚本可用于使用 BERT 微调单个序列(或序列对)分类器,例如用于 MRPC 任务。

6. BertForMultipleChoice

BertForMultipleChoice 是一个微调模型,包含 BertModel 以及在 BertModel 上方的线性层。

线性层为多项选择题的每个选项输出一个值,然后所有对应实例的输出都通过 softmax 得到模型选择。

本实现主要受到OpenAI在通过生成预训练改进语言理解以及Jacob Devlin在以下问题中的回答的启发。

如何使用此类的一个示例在run_swag.py脚本中给出,该脚本可用于使用BERT微调一个多项选择分类器,例如用于Swag任务。

7. BertForTokenClassification

BertForTokenClassification是一个微调模型,它包括BertModel并在BertModel之上有一个基于标记的分类器。

标记级分类器是一个线性层,它以序列的最后一个隐藏状态作为输入。

8. BertForQuestionAnswering

BertForQuestionAnswering是一个微调模型,它包括BertModel并在最后一个隐藏状态的完整序列之上有一个标记级分类器。

标记级分类器以最后一个隐藏状态的完整序列作为输入,并计算每个标记的多个(例如两个)得分,例如分别可以是标记是start_spanend_span标记的得分(参见BERT论文中的图3c和3d)。

如何使用此类的一个示例在run_squad.py脚本中给出,该脚本可用于使用BERT微调一个标记分类器,例如用于SQuAD任务。

9. OpenAIGPTModel

OpenAIGPTModel是基本的OpenAI GPT Transformer模型,它包含一个求和标记和位置嵌入层,之后是一系列12个相同的自注意力块。

OpenAI GPT使用单个嵌入矩阵存储单词和特殊嵌入。特殊标记嵌入是额外的标记,它们没有经过预训练:[SEP][CLS]... 如果使用特殊标记,需要在微调期间对它们进行训练。可以使用set_num_special_tokens(num_special_tokens)函数控制特殊嵌入的数量。

嵌入在标记嵌入矩阵中的顺序如下

    [0,                                                         ----------------------
      ...                                                        -> word embeddings
      config.vocab_size - 1,                                     ______________________
      config.vocab_size,
      ...                                                        -> special embeddings
      config.vocab_size + config.n_special - 1]                  ______________________

其中total_tokens_embeddings可以通过config.total_tokens_embeddings获得,如下所示:total_tokens_embeddings = config.vocab_size + config.n_special 应该使用关联的索引来索引嵌入。

输入和输出与TensorFlow模型的输入和输出相同。

我们在此详细说明。该模型以输入modeling_openai.py

  • input_ids:一个形状为[batch_size, sequence_length]的torch.LongTensor(或更一般地[],其中d_1 ... d_n是任意维度)的单词BPE标记索引,在范围[0, total_tokens_embeddings]内选择
  • position_ids:一个可选的形状与input_ids相同的torch.LongTensor,包含位置索引(在范围[0, config.n_positions - 1]内选择)
  • token_type_ids:一个可选的形状与input_ids相同的torch.LongTensor,您可以使用它为序列中的每个输入标记添加第三种嵌入(前两种是单词和位置嵌入)。输入、位置和token_type嵌入在Transformer的第一个自注意力块之前相加。

此模型输出

  • hidden_states:模型顶部的编码隐藏状态,作为一个形状为[batch_size, sequence_length, hidden_size]的torch.FloatTensor(或更一般地[],其中d_1 ... d_n是input_ids的维度)

10. OpenAIGPTLMHeadModel

OpenAIGPTLMHeadModel包括OpenAIGPTModel Transformer,后面跟着一个与输入嵌入权重绑定的语言模型头部(没有额外的参数)。

输入OpenAIGPTModel类的输入相同,加上可选的标签

  • lm_labels:可选的语言建模标签:形状为[batch_size, sequence_length]的torch.LongTensor,索引选择在[-1, 0, ..., vocab_size]范围内。所有设置为-1的标签将被忽略(掩码),只计算[0, ..., vocab_size]范围内的标签的损失。

输出:

  • 如果lm_labels不是None:输出语言建模损失。
  • 否则:输出lm_logits:语言建模的logits,形状为[batch_size, sequence_length, total_tokens_embeddings]的torch.FloatTensor(或者更一般地,[d_1, ..., d_n, total_tokens_embeddings],其中d_1 ... d_n是input_ids的维度)

11. OpenAIGPTDoubleHeadsModel

OpenAIGPTDoubleHeadsModel包括一个OpenAIGPTModel Transformer,后面跟着两个头部

  • 一个语言建模头部,其权重与输入嵌入相关联(没有额外的参数),
  • 一个多选题分类器(线性层,输入一个序列中的隐藏状态来计算一个分数,详细信息见论文)。

输入OpenAIGPTModel类的输入相同,加上一个分类掩码和两个可选标签

  • multiple_choice_token_ids:形状为[batch_size, num_choices]的torch.LongTensor,表示用作多选题分类器输入的token的索引(通常是每个选择的[CLS] token)。
  • lm_labels:可选的语言建模标签:形状为[batch_size, sequence_length]的torch.LongTensor,索引选择在[-1, 0, ..., vocab_size]范围内。所有设置为-1的标签将被忽略(掩码),只计算[0, ..., vocab_size]范围内的标签的损失。
  • multiple_choice_labels:可选的多选题标签:形状为[batch_size]的torch.LongTensor,索引选择在[0, ..., num_choices]范围内。

输出:

  • 如果lm_labelsmultiple_choice_labels都不是None:输出一个包含语言建模损失和多选题损失的损失元组。
  • 否则输出一个包含
    • lm_logits:语言建模的logits,形状为[batch_size, num_choices, sequence_length, total_tokens_embeddings]的torch.FloatTensor
    • multiple_choice_logits:多选题的logits,形状为[batch_size, num_choices]的torch.FloatTensor

12. TransfoXLModel

Transformer-XL模型在《Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context》中描述。

Transformer XL使用带有正弦波模式的相对位置和自适应softmax输入,这意味着

  • 你不需要指定位置嵌入索引
  • 词汇表中的token必须按降序排序。

此模型将作为输入modeling_transfo_xl.py

  • input_ids:形状为[batch_size, sequence_length]的torch.LongTensor,表示在[0, self.config.n_token[
  • mems:可选的从前向传递中得到的隐藏状态内存,作为每个层入口的隐藏状态列表(num layers)。每个隐藏状态具有形状[self.config.mem_len, bsz, self.config.d_model]。注意,与input_ids相比,mems中的前两个维度是转置的。

此模型输出一个包含(last_hidden_state, new_mems)的元组

  • last_hidden_state:模型顶部的编码-隐藏状态,形状为[batch_size, sequence_length, self.config.d_model]的torch.FloatTensor
  • new_mems:列表(num layers),包含每个层入口的更新后的mem状态,每个mem状态是一个形状为[self.config.mem_len, batch_size, self.config.d_model]的torch.FloatTensor。注意,与input_ids相比,mems中的前两个维度是转置的。
last_hidden_statenew_mems中提取Transformer-XL每个层的隐藏状态列表

new_mems包含所有隐藏状态以及嵌入的输出(new_mems[0])。new_mems[-1]是低于最后一层的隐藏状态的输出,last_hidden_state是最后一层的输出(即当我们顶部有语言建模头部时softmax的输入)。

new_memslast_hidden_state的形状之间有两个区别:new_mems有转置的第一个维度,并且更长(大小为self.config.mem_len)。以下是从模型输出中提取完整隐藏状态列表的方法

hidden_states, mems = model(tokens_tensor)
seq_length = hidden_states.size(1)
lower_hidden_states = list(t[-seq_length:, ...].transpose(0, 1) for t in mems)
all_hidden_states = lower_hidden_states + [hidden_states]

13. TransfoXLLMHeadModel

TransfoXLLMHeadModel 包含一个跟随自适应 softmax 头的 TransfoXLModel Transformer,该头部的权重与输入嵌入相关联。

输入TransfoXLModel 类的输入相同,此外还有可选的标签

  • target:一个可选的形状为 [batch_size, sequence_length] 的 torch.LongTensor,其中包含了在范围 [0, self.config.n_token] 内选定的目标标记索引

输出 一个包含 (last_hidden_state, new_mems) 的元组

  • softmax_output:自适应 softmax 的输出
    • 如果 target 为 None:标记的 log 概率,形状为 [batch_size, sequence_length, n_tokens]
    • 否则:目标标记的负对数似然,形状为 [batch_size, sequence_length]
  • new_mems:列表(num layers),包含每个层入口的更新后的mem状态,每个mem状态是一个形状为[self.config.mem_len, batch_size, self.config.d_model]的torch.FloatTensor。注意,与input_ids相比,mems中的前两个维度是转置的。

14. GPT2Model

GPT2Model 是 OpenAI GPT-2 Transformer 模型,包含一层加和的标记和位置嵌入,之后是 12 个相同的自注意力块。

输入和输出与TensorFlow模型的输入和输出相同。

这里详细说明。该模型将以下作为 输入modeling_gpt2.py

  • input_ids:一个形状为 [batch_size, sequence_length] 的 torch.LongTensor(或更一般地,[d_1, ..., d_n, sequence_length],其中 d_1 ... d_n 是任意维度)的 BPE 标记索引,范围在 [0, vocab_size]
  • position_ids:一个可选的形状与input_ids相同的torch.LongTensor,包含位置索引(在范围[0, config.n_positions - 1]内选择)
  • token_type_ids:一个可选的形状与input_ids相同的torch.LongTensor,您可以使用它为序列中的每个输入标记添加第三种嵌入(前两种是单词和位置嵌入)。输入、位置和token_type嵌入在Transformer的第一个自注意力块之前相加。
  • past:一个可选的 torch.LongTensor 列表,包含预计算的隐藏状态(注意力块中的键和值),以加速序列解码(这是模型的 presents 输出,见下文)。

此模型输出

  • hidden_states:模型顶部的编码隐藏状态,作为一个形状为[batch_size, sequence_length, hidden_size]的torch.FloatTensor(或更一般地[],其中d_1 ... d_n是input_ids的维度)
  • presents:一个包含预计算的隐藏状态(每个注意力块中的键和值)的列表,作为 torch.FloatTensors。它们可以被重复使用以加速序列解码(参见 run_gpt2.py 示例)。

15. GPT2LMHeadModel

GPT2LMHeadModel 包含一个 GPT2Model Transformer,后面跟随一个语言建模头,该头部的权重与输入嵌入相关联(没有额外的参数)。

输入GPT2Model 类的输入相同,此外还有可选的标签

  • lm_labels:可选的语言建模标签:形状为[batch_size, sequence_length]的torch.LongTensor,索引选择在[-1, 0, ..., vocab_size]范围内。所有设置为-1的标签将被忽略(掩码),只计算[0, ..., vocab_size]范围内的标签的损失。

输出:

  • 如果lm_labels不是None:输出语言建模损失。
  • else:一个包含
    • lm_logits:语言建模的对数几率,作为一个大小为 [batch_size, sequence_length, total_tokens_embeddings] 的 torch.FloatTensor(或更一般地,[d_1, ..., d_n, total_tokens_embeddings],其中 d_1 ... d_n 是 input_ids 的维度)
    • presents:一个包含预计算的隐藏状态(每个注意力块中的键和值)的列表,作为 torch.FloatTensors。它们可以被重复使用以加速序列解码(参见 run_gpt2.py 示例)。

16. GPT2DoubleHeadsModel

GPT2DoubleHeadsModel 包含一个 GPT2Model Transformer,后面跟随两个头部

  • 一个语言建模头部,其权重与输入嵌入相关联(没有额外的参数),
  • 一个多选题分类器(线性层,输入一个序列中的隐藏状态来计算一个分数,详细信息见论文)。

输入GPT2Model 类的输入相同,包括一个分类掩码和两个可选的标签

  • multiple_choice_token_ids:形状为[batch_size, num_choices]的torch.LongTensor,表示用作多选题分类器输入的token的索引(通常是每个选择的[CLS] token)。
  • lm_labels:可选的语言建模标签:形状为[batch_size, sequence_length]的torch.LongTensor,索引选择在[-1, 0, ..., vocab_size]范围内。所有设置为-1的标签将被忽略(掩码),只计算[0, ..., vocab_size]范围内的标签的损失。
  • multiple_choice_labels:可选的多选题标签:形状为[batch_size]的torch.LongTensor,索引选择在[0, ..., num_choices]范围内。

输出:

  • 如果lm_labelsmultiple_choice_labels都不是None:输出一个包含语言建模损失和多选题损失的损失元组。
  • 否则输出一个包含
    • lm_logits:语言建模的logits,形状为[batch_size, num_choices, sequence_length, total_tokens_embeddings]的torch.FloatTensor
    • multiple_choice_logits:多选题的logits,形状为[batch_size, num_choices]的torch.FloatTensor
    • presents:一个包含预计算的隐藏状态(每个注意力块中的键和值)的列表,作为 torch.FloatTensors。它们可以被重复使用以加速序列解码(参见 run_gpt2.py 示例)。

标记化器

BertTokenizer

BertTokenizer 执行端到端的标记化,即基本标记化后跟随 WordPiece 标记化。

这个类有五个参数

  • vocab_file:词汇文件的路径。
  • do_lower_case:在标记化时将文本转换为小写。默认值 = True。
  • max_len:要过滤 Transformer 输入的最大长度。如果为 None,则默认为模型的预训练值。默认值 = None。
  • do_basic_tokenize:在 wordpiece 标记化之前执行基本标记化。如果文本是预标记化的,则设置为 false。默认值 = True。
  • never_split:一个应在其标记化过程中不分割的标记列表。默认值 = ["[UNK]", "[SEP]", "[PAD]", "[CLS]", "[MASK]"]

以及三个方法

  • tokenize(text):通过(1)执行基本标记化和(2)WordPiece 标记化将 str 转换为 str 标记列表。
  • convert_tokens_to_ids(tokens):将 str 标记列表转换为词汇表中的 int 索引列表。
  • convert_ids_to_tokens(tokens):将词汇表中的 int 索引列表转换为 str 标记列表。
  • save_vocabulary(directory_path):将词汇表文件保存到directory_path。返回保存的词汇表文件路径:vocab_file_path。可以通过BertTokenizer.from_pretrained('vocab_file_path')BertTokenizer.from_pretrained('directory_path')重新加载词汇表。

请参阅tokenization.py中的文档字符串和代码(链接:[./pytorch_pretrained_bert/tokenization.py]),了解BasicTokenizerWordpieceTokenizer类的详细信息。通常建议使用BertTokenizer,除非您非常清楚自己在做什么。

OpenAIGPTTokenizer

OpenAIGPTTokenizer执行字节对编码(BPE)标记化。

此类有四个参数

  • vocab_file:词汇文件的路径。
  • merges_file:包含BPE合并的文件的路径。
  • max_len:要过滤 Transformer 输入的最大长度。如果为 None,则默认为模型的预训练值。默认值 = None。
  • special_tokens:要添加到词汇表以进行微调的标记列表。如果未安装SpaCy并且使用BERT的BasicTokenizer作为预BPE标记化器,则不会分割这些标记。默认值= None

和五个方法

  • tokenize(text):通过执行BPE标记化将str转换为标记列表。
  • convert_tokens_to_ids(tokens):将 str 标记列表转换为词汇表中的 int 索引列表。
  • convert_ids_to_tokens(tokens):将词汇表中的 int 索引列表转换为 str 标记列表。
  • set_special_tokens(self, special_tokens):更新特殊标记列表(见上述参数)
  • encode(text):通过执行BPE编码将str转换为标记列表。
  • decode(ids, skip_special_tokens=False, clean_up_tokenization_spaces=False):将标记列表解码为字符串,并在需要时执行一些后处理:(i)从输出中移除特殊标记(ii)清理标记化空间。
  • save_vocabulary(directory_path):将词汇表、合并和特殊标记文件保存到directory_path。返回三个文件的路径:vocab_file_pathmerge_file_pathspecial_tokens_file_path。可以通过OpenAIGPTTokenizer.from_pretrained('directory_path')重新加载词汇表。

请参阅tokenization_openai.py中的文档字符串和代码(链接:[./pytorch_pretrained_bert/tokenization_openai.py]),了解OpenAIGPTTokenizer的详细信息。

TransfoXLTokenizer

TransfoXLTokenizer执行词标记化。此标记化器可用于自适应softmax,并具有用于在语料库中计数标记以创建按标记频率排序的词汇表的实用程序(用于自适应softmax)。有关更多详细信息,请参阅自适应softmax论文(《Efficient softmax approximation for GPUs》)。

API与BertTokenizer的API类似(见上文)。

请参阅tokenization_transfo_xl.py中的文档字符串和代码(链接:[./pytorch_pretrained_bert/tokenization_transfo_xl.py]),了解TransfoXLTokenizer中这些额外方法的详细信息。

GPT2Tokenizer

GPT2Tokenizer执行字节级别的字节对编码(BPE)标记化。

此类有三个参数

  • vocab_file:词汇文件的路径。
  • merges_file:包含BPE合并的文件的路径。
  • errors:如何处理Unicode解码错误。默认值 = replace

和两个方法

  • tokenize(text):通过执行字节级别的BPE将str转换为标记列表。
  • convert_tokens_to_ids(tokens):将 str 标记列表转换为词汇表中的 int 索引列表。
  • convert_ids_to_tokens(tokens):将词汇表中的 int 索引列表转换为 str 标记列表。
  • set_special_tokens(self, special_tokens):更新特殊标记列表(见上述参数)
  • encode(text):通过执行字节级别的BPE将str转换为标记列表。
  • decode(tokens):将标记列表转换回str
  • save_vocabulary(directory_path):将词汇表、合并和特殊标记文件保存到directory_path。返回三个文件的路径:vocab_file_pathmerge_file_pathspecial_tokens_file_path。可以通过OpenAIGPTTokenizer.from_pretrained('directory_path')重新加载词汇表。

请参阅tokenization_gpt2.py(链接:[./pytorch_pretrained_bert/tokenization_gpt2.py])以获取有关GPT2Tokenizer的更多详细信息。

优化器

BertAdam

BertAdam是一个适应于BERT在TensorFlow实现中使用的优化器的torch.optimizer。与PyTorch Adam优化器的不同之处在于:

  • BertAdam实现了权重衰减修复;
  • BertAdam不像常规Adam优化器那样补偿偏差。

优化器接受以下参数:

  • lr:学习率
  • warmup:预热部分t_total-1表示没有预热。默认:-1
  • t_total:学习率计划的总训练步数,-1表示恒定学习率。默认:-1
  • schedule : 用于预热(见上文)的调度。可以是 'warmup_linear''warmup_constant''warmup_cosine''none'None 或一个 _LRSchedule 对象(见下文)。如果为 None'none',则学习率始终保持不变。默认:'warmup_linear'
  • b1 : Adam的b1。默认:0.9
  • b2 : Adam的b2。默认:0.999
  • e : Adam的epsilon。默认:1e-6
  • weight_decay: 权重衰减。默认:0.01
  • max_grad_norm : 梯度的最大范数(-1 表示不剪辑)。默认:1.0

OpenAIAdam

OpenAIAdamBertAdam 类似。与 BertAdam 的不同之处在于,OpenAIAdam 补偿了与常规Adam优化器相同的偏差。

OpenAIAdam 接受与 BertAdam 相同的参数。

学习率调度

.optimization 模块还提供了以 _LRSchedule 继承对象形式存在的一些额外调度。所有 _LRSchedule 子类在构造时都接受 warmupt_total 参数。当将 _LRSchedule 对象传递给 BertAdamOpenAIAdam 时,优化器上的 warmupt_total 参数将被忽略,而使用 _LRSchedule 对象中的参数。实现调度的概述

  • ConstantLR:始终返回学习率为1。
  • WarmupConstantSchedule:在训练步骤的 warmup 分数内线性增加学习率从0到1。预热后保持学习率为1。
  • WarmupLinearSchedule:在训练步骤的 warmup 分数内线性增加学习率从0到1。在剩余的 1 - warmup 步骤内从1.线性减少到0.。
  • WarmupCosineSchedule:在训练步骤的 warmup 分数内线性增加学习率从0到1。在剩余的 1 - warmup 步骤内根据余弦曲线从1.减少到0.。如果 cycles(默认=0.5)与默认值不同,则预热后学习率遵循余弦函数。
  • WarmupCosineWithHardRestartsSchedule:在训练步骤的 warmup 分数内线性增加学习率从0到1。如果 cycles(默认=1.)与默认值不同,则学习率将遵循 cycles 倍的余弦衰减学习率(带有硬重启)。
  • WarmupCosineWithWarmupRestartsSchedule:将所有训练进度分为长度相等的 cycles(默认=1.)部分。每个部分都遵循一个在训练步骤的前 warmup 分数内线性从0.增加到1.的调度,之后是按照余弦曲线从1.减少到0.的学习率。请注意,所有周期中所有预热步骤的总数等于 warmup * cycles

示例

子章节 描述
训练大型模型:介绍、工具和示例 如何使用梯度累积、多GPU训练、分布式训练、CPU优化和16位训练来训练BERT模型
使用BERT进行微调:运行示例 ./examples 运行示例:extract_classif.pyrun_classifier.pyrun_squad.pyrun_lm_finetuning.py
使用OpenAI GPT、Transformer-XL和GPT-2进行微调 ./examples目录下运行示例:run_openai_gpt.pyrun_transfo_xl.pyrun_gpt2.py
在GPU上微调BERT-large 如何微调BERT large

训练大型模型:介绍、工具和示例

BERT-base和BERT-large分别是110M和340M参数模型,在单GPU上使用推荐的批大小进行微调可能比较困难(通常批大小为32)。

为了帮助微调这些模型,我们在微调脚本中包含了几种技术,您可以在run_classifier.pyrun_squad.py脚本中激活这些技术:梯度累积、多GPU训练、分布式训练和16位训练。有关如何使用这些技术的更多详细信息,您可以阅读我上个月发布的关于在PyTorch中训练大批次的技巧(点击查看)

以下是如何在我们的脚本中使用这些技术的方法

  • 梯度累积:可以通过向--gradient_accumulation_steps参数提供一个大于1的整数来使用梯度累积。每个步骤的批次将除以这个整数,梯度将在gradient_accumulation_steps步骤中累积。
  • 多GPU:当检测到多个GPU时,自动激活多GPU,并将批次分割到各个GPU上。
  • 分布式训练:可以通过向--local_rank参数提供一个大于等于0的整数来激活分布式训练(见下文)。
  • 16位训练:16位训练,也称为混合精度训练,可以通过使用半精度训练来减少模型在GPU上的内存需求,基本上可以将批大小加倍。如果您有最新的GPU(从NVIDIA Volta架构开始),您应该不会看到速度下降。有关混合精度训练的良好介绍,请(点击查看)。完整的文档请(点击查看)。在我们的脚本中,此选项可以通过设置--fp16标志来激活,您可以使用--loss_scale标志来调整损失缩放(有关损失缩放的详细信息,请参阅先前链接的文档)。损失缩放可以是0,在这种情况下,缩放是动态调整的,或者是一个正的2的幂,在这种情况下,缩放是静态的。

要使用16位训练和分布式训练,您需要安装NVIDIA的apex扩展(点击查看详细安装说明)。您可以在文档和相关仓库中找到有关apex内部机制以及如何使用apex的更多信息。您可以在本仓库的相关PR中查看NVIDIA团队对pytorch-BERT进行的测试结果(以及我尝试复现的结果)。

注意:要使用分布式训练,您需要在每台机器上运行一个训练脚本。例如,您可以在每个服务器上运行以下命令(有关更多详细信息,请参阅上述提到的博客文章

python -m torch.distributed.launch --nproc_per_node=4 --nnodes=2 --node_rank=$THIS_MACHINE_INDEX --master_addr="192.168.1.1" --master_port=1234 run_classifier.py (--arg1 --arg2 --arg3 and all other arguments of the run_classifier script)

其中$THIS_MACHINE_INDEX是分配给每台机器的顺序索引(0,1,2...),具有rank 0的机器的IP地址为192.168.1.1,开放的端口号为1234

使用BERT进行微调:运行示例

我们展示了几个基于(并扩展自)原始实现的微调示例

  • 在九个不同的GLUE任务上的一个序列级分类器
  • 在问答数据集SQuAD上的一个标记级分类器
  • 在SWAG分类语料库上的一个序列级多选分类器
  • 在另一个目标语料库上的BERT语言模型

在开发集上的GLUE结果。

使用未分词的BERT base模型,在GLUE基准测试的开发集上我们得到了以下结果。所有实验都在P100 GPU上以32个批次的规模运行。

任务 指标 结果
CoLA Matthew's corr. 57.29
SST-2 准确率 93.00
MRPC F1/准确率 88.85/83.82
STS-B Pearson/Spearman corr. 89.70/89.37
QQP 准确率/F1 90.72/87.41
MNLI 匹配准确率/不匹配准确率 83.95/84.39
QNLI 准确率 89.04
RTE 准确率 61.01
WNLI 准确率 53.52

其中一些结果与网站GLUE基准测试测试集上报告的结果有显著差异。对于QQP和WNLI,请参阅网站上的FAQ #12

在运行这些GLUE任务之前,您应该通过运行以下脚本来下载GLUE数据,并将其解压缩到某个目录$GLUE_DIR

export GLUE_DIR=/path/to/glue
export TASK_NAME=MRPC

python run_classifier.py \
  --task_name $TASK_NAME \
  --do_train \
  --do_eval \
  --do_lower_case \
  --data_dir $GLUE_DIR/$TASK_NAME \
  --bert_model bert-base-uncased \
  --max_seq_length 128 \
  --train_batch_size 32 \
  --learning_rate 2e-5 \
  --num_train_epochs 3.0 \
  --output_dir /tmp/$TASK_NAME/

其中任务名称可以是CoLA、SST-2、MRPC、STS-B、QQP、MNLI、QNLI、RTE或WNLI之一。

开发集的结果将显示在指定输出目录中的文本文件'eval_results.txt'中。对于MNLI,由于存在两个单独的开发集(匹配和不匹配),除了'/tmp/MNLI/'之外,还会存在一个单独的输出文件夹'/tmp/MNLI-MM/'。

除了MRPC、MNLI、CoLA、SST-2以外的GLUE任务,尚未用apex进行半精度训练进行测试。以下部分提供了如何使用apex进行MRPC半精度训练的详细信息。尽管如此,由于每个任务的数据处理器都继承自基类DataProcessor,因此应该没有问题,也可以用剩余的GLUE任务进行半精度训练。

MRPC

此示例代码在Microsoft Research Paraphrase Corpus (MRPC)语料库上微调BERT,在单个K-80上运行不到10分钟,在安装了apex的单个Tesla V100 16GB上仅需27秒。

在运行此示例之前,您应该通过运行以下脚本来下载GLUE数据,并将其解压缩到某个目录$GLUE_DIR

export GLUE_DIR=/path/to/glue

python run_classifier.py \
  --task_name MRPC \
  --do_train \
  --do_eval \
  --do_lower_case \
  --data_dir $GLUE_DIR/MRPC/ \
  --bert_model bert-base-uncased \
  --max_seq_length 128 \
  --train_batch_size 32 \
  --learning_rate 2e-5 \
  --num_train_epochs 3.0 \
  --output_dir /tmp/mrpc_output/

我们在几个种子上运行了测试,使用原始实现超参数给出了84%至88%的评估结果。

使用apex和16位精度快速运行:在27秒内微调MRPC!首先按照以下链接指示安装apex。然后运行

export GLUE_DIR=/path/to/glue

python run_classifier.py \
  --task_name MRPC \
  --do_train \
  --do_eval \
  --do_lower_case \
  --data_dir $GLUE_DIR/MRPC/ \
  --bert_model bert-base-uncased \
  --max_seq_length 128 \
  --train_batch_size 32 \
  --learning_rate 2e-5 \
  --num_train_epochs 3.0 \
  --output_dir /tmp/mrpc_output/ \
  --fp16

SQuAD

此示例代码在SQuAD数据集上微调BERT。它在单个Tesla V100 16GB上(使用BERT-base)运行24分钟或(使用BERT-large)68分钟。

SQuAD数据可以通过以下链接下载,并应保存在$SQUAD_DIR目录中。

export SQUAD_DIR=/path/to/SQUAD

python run_squad.py \
  --bert_model bert-base-uncased \
  --do_train \
  --do_predict \
  --do_lower_case \
  --train_file $SQUAD_DIR/train-v1.1.json \
  --predict_file $SQUAD_DIR/dev-v1.1.json \
  --train_batch_size 12 \
  --learning_rate 3e-5 \
  --num_train_epochs 2.0 \
  --max_seq_length 384 \
  --doc_stride 128 \
  --output_dir /tmp/debug_squad/

使用先前超参数进行训练给出了以下结果

{"f1": 88.52381567990474, "exact_match": 81.22043519394512}

SWAG

SWAG数据可以通过克隆以下仓库下载

export SWAG_DIR=/path/to/SWAG

python run_swag.py \
  --bert_model bert-base-uncased \
  --do_train \
  --do_lower_case \
  --do_eval \
  --data_dir $SWAG_DIR/data \
  --train_batch_size 16 \
  --learning_rate 2e-5 \
  --num_train_epochs 3.0 \
  --max_seq_length 80 \
  --output_dir /tmp/swag_output/ \
  --gradient_accumulation_steps 4

在单个GPU上使用先前超参数进行训练给出了以下结果

eval_accuracy = 0.8062081375587323
eval_loss = 0.5966546792367169
global_step = 13788
loss = 0.06423990014260186

语言模型微调

数据应该是与sample_text.txt相同格式的文本文件(每行一个句子,文档之间由空行分隔)。您可以下载一个示例训练语料库,该语料库由维基百科文章生成并使用spaCy分割成约50万个句子。在4个NVIDIA Tesla P100上使用train_batch_size=200max_seq_length=128训练一个epoch需要大约1小时20分钟。

感谢@Rocketknight1和@tholor的工作,现在有多个脚本可以使用预训练目标(掩码语言模型和下一个句子预测损失的组合)来微调BERT。这些脚本在examples/lm_finetuning/文件夹的README中详细说明。

运行OpenAI GPT、Transformer-XL和GPT-2的示例

我们提供了基于(并扩展自)相应原始实现的OpenAI GPT、Transformer-XL和OpenAI GPT-2的三个脚本示例

  • 在ROCStories数据集上微调OpenAI GPT
  • 在WikiText 103上评估Transformer-XL
  • 从预训练的OpenAI GPT-2模型进行无条件和有条件生成

在ROCStories数据集上微调OpenAI GPT

此示例代码在ROCStories数据集上微调OpenAI GPT。

在运行此示例之前,您应该下载RocStories数据集并将其解压到某个目录$ROC_STORIES_DIR

export ROC_STORIES_DIR=/path/to/RocStories

python run_openai_gpt.py \
  --model_name openai-gpt \
  --do_train \
  --do_eval \
  --train_dataset $ROC_STORIES_DIR/cloze_test_val__spring2016\ -\ cloze_test_ALL_val.csv \
  --eval_dataset $ROC_STORIES_DIR/cloze_test_test__spring2016\ -\ cloze_test_ALL_test.csv \
  --output_dir ../log \
  --train_batch_size 16 \

此命令在单个K-80上大约运行10分钟,给出约87.7%的评估准确率(作者报告的TensorFlow代码的中位数准确率为85.8%,OpenAI GPT论文报告的最佳单次运行准确率为86.5%)。

评估预训练的Transformer-XL在WikiText 103数据集上的表现

此示例代码评估预训练的Transformer-XL在WikiText 103数据集上的表现。此命令将下载WikiText 103数据集的预处理版本,其中已计算词汇表。

python run_transfo_xl.py --work_dir ../log

此命令在V100上大约运行1分钟,在WikiText-103上的评估困惑度为18.22(作者报告在此数据集上使用TensorFlow代码的困惑度约为18.3)。

从OpenAI的GPT-2模型进行无条件和有条件生成

此示例代码与原始的无条件和有条件生成代码相同。

有条件生成

python run_gpt2.py

无条件生成

python run_gpt2.py --unconditional

提供了与原始脚本相同的选项,请参考示例代码和OpenAI的原始仓库。

在GPU上微调BERT-large

我们列出的选项允许您轻松地在GPU(而不是原始实现中使用的TPU)上微调BERT-large。

例如,在具有4个k-80(这些现在相当老了)的服务器上,可以在18小时内完成SQuAD上的BERT-large微调。我们的结果与TensorFlow实现的结果相似(实际上略高)

{"exact_match": 84.56953642384106, "f1": 91.04028647786927}

为了得到这些结果,我们使用了以下组合

  • 多GPU训练(在多GPU服务器上自动激活),
  • 2步梯度累积,
  • 在CPU上执行优化步骤以将Adam的平均值存储在RAM中。

以下是此运行的完整超参数列表

export SQUAD_DIR=/path/to/SQUAD

python ./run_squad.py \
  --bert_model bert-large-uncased \
  --do_train \
  --do_predict \
  --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 /tmp/debug_squad/ \
  --train_batch_size 24 \
  --gradient_accumulation_steps 2

如果您有较新的GPU(从NVIDIA Volta系列开始),您应该尝试使用16位微调(FP16)。

以下是FP16运行尝试的超参数示例

export SQUAD_DIR=/path/to/SQUAD

python ./run_squad.py \
  --bert_model bert-large-uncased \
  --do_train \
  --do_predict \
  --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 /tmp/debug_squad/ \
  --train_batch_size 24 \
  --fp16 \
  --loss_scale 128

结果与上述FP32结果相似(实际上略高)

{"exact_match": 84.65468306527909, "f1": 91.238669287002}

笔记本

我们包括了三个Jupyter Notebook,可以用来检查PyTorch模型的预测与原始TensorFlow模型的预测是否相同。

  • 第一个NoteBook(Comparing-TF-and-PT-models.ipynb)从TensorFlow和PyTorch模型的每一层提取整个序列的隐藏状态,并计算它们之间的标准差。在给定示例中,我们得到1.5e-7到9e-7的模型各种隐藏状态的标准差。

  • 第二个NoteBook(Comparing-TF-and-PT-models-SQuAD.ipynb)比较了TensorFlow和PyTorch模型在相同初始化的BertForQuestionAnswering微调层上计算的损失,并计算它们之间的标准差。在给定示例中,我们得到了模型之间的标准差为2.5e-7。

  • 第三个NoteBook(Comparing-TF-and-PT-models-MLM-NSP.ipynb)比较了使用预训练的掩码语言模型进行掩码标记语言建模时,TensorFlow和PyTorch模型的预测。

请按照notebook中给出的说明来运行和修改它们。

命令行界面

提供了一个命令行界面,用于将TensorFlow的BertForPreTraining类(针对BERT)的PyTorch存档转换为NumPy存档,或者将NumPy的OpenAIGPTModel类(针对OpenAI GPT)的PyTorch存档转换为NumPy存档。

BERT

您可以使用convert_tf_checkpoint_to_pytorch.py脚本将BERT(特别是谷歌发布的预训练模型)的任何TensorFlow存档转换为PyTorch保存文件。

此CLI将TensorFlow存档(以bert_model.ckpt开头的三个文件)和相关配置文件(bert_config.json)作为输入,并为该配置创建一个PyTorch模型,在PyTorch模型中加载从TensorFlow存档的权重,并将结果模型保存为标准的PyTorch保存文件,可以使用torch.load()导入(参见extract_features.pyrun_classifier.pyrun_squad.py中的示例)。

您只需要运行此转换脚本一次以获得PyTorch模型。然后您可以忽略TensorFlow存档(以bert_model.ckpt开头的三个文件),但务必保留配置文件(bert_config.json)和词汇表文件(vocab.txt),因为它们对PyTorch模型也是必需的。

要运行此特定转换脚本,您需要安装TensorFlow和PyTorch(pip install tensorflow)。其余的存储库只需要PyTorch。

以下是预训练BERT-Base Uncased模型的转换过程示例

export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12

pytorch_pretrained_bert convert_tf_checkpoint_to_pytorch \
  $BERT_BASE_DIR/bert_model.ckpt \
  $BERT_BASE_DIR/bert_config.json \
  $BERT_BASE_DIR/pytorch_model.bin

您可以从这里下载用于转换的谷歌预训练模型(在此)

OpenAI GPT

以下是预训练OpenAI GPT模型的转换过程示例,假设您的NumPy存档保存的格式与OpenAI预训练模型相同(参见在此

export OPENAI_GPT_CHECKPOINT_FOLDER_PATH=/path/to/openai/pretrained/numpy/weights

pytorch_pretrained_bert convert_openai_checkpoint \
  $OPENAI_GPT_CHECKPOINT_FOLDER_PATH \
  $PYTORCH_DUMP_OUTPUT \
  [OPENAI_GPT_CONFIG]

Transformer-XL

以下是预训练Transformer-XL模型的转换过程示例(参见在此

export TRANSFO_XL_CHECKPOINT_FOLDER_PATH=/path/to/transfo/xl/checkpoint

pytorch_pretrained_bert convert_transfo_xl_checkpoint \
  $TRANSFO_XL_CHECKPOINT_FOLDER_PATH \
  $PYTORCH_DUMP_OUTPUT \
  [TRANSFO_XL_CONFIG]

GPT-2

以下是预训练OpenAI GPT-2模型的转换过程示例。

export GPT2_DIR=/path/to/gpt2/checkpoint

pytorch_pretrained_bert convert_gpt2_checkpoint \
  $GPT2_DIR/model.ckpt \
  $PYTORCH_DUMP_OUTPUT \
  [GPT2_CONFIG]

TPU

TPU支持和预训练脚本

PyTorch当前稳定版本(0.4.1)不支持TPU。然而,PyTorch的下一个版本(v1.0)应该支持在TPU上训练,并预期很快发布(参见最近的官方公告)。

我们将在下一个版本发布时添加TPU支持。

原始TensorFlow代码还包括两个用于预训练BERT的脚本:create_pretraining_data.pyrun_pretraining.py

由于预训练BERT是一个特别昂贵的操作,基本上需要一或多个TPU以合理的时间完成(参见此处的详细信息),我们决定等待PyTorch包含TPU支持后,再转换这些预训练脚本。

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分发

pytorch_pretrained_bert-0.6.2.tar.gz (127.4 kB 查看哈希值)

上传时间 源代码

构建分发

pytorch_pretrained_bert-0.6.2-py3-none-any.whl (123.8 kB 查看哈希值)

上传时间 Python 3

pytorch_pretrained_bert-0.6.2-py2-none-any.whl (106.9 kB 查看哈希值)

上传时间 Python 2

支持者: