spaCy预训练BERT和其他transformers的管道
项目描述
spaCy的PyTorch Transformers包装器
此软件包提供了spaCy模型管道,用于包装Hugging Face的pytorch-transformers
软件包,以便您可以在spaCy中使用它们。结果是方便地访问最先进的transformer架构,如BERT、GPT-2、XLNet等。有关更多详细信息和方法背景,请参阅我们的博客文章。
功能
- 直接在spaCy管道中使用
BERT
、RoBERTa
、XLNet
和GPT-2
。 - 使用spaCy的API对预训练的transformer模型进行微调。
- 用于文本分类的定制组件,使用transformer特征。
- 自动对wordpieces和输出进行语言符号的对齐。
- 使用智能的每句预测处理多句子文档。
- 内置的上下文敏感向量相似性挂钩。
- 开箱即用的序列化和模型打包。
🚀 快速入门
使用pip安装包将自动安装所有依赖项,包括PyTorch和spaCy。请确保在安装模型之前安装此包。另外请注意,此包需要Python 3.6+和spaCy的最新版本,即v2.1.7或更高版本。
pip install spacy-pytorch-transformers
对于GPU安装,使用nvcc --version
查找您的CUDA版本,并在括号内添加版本,例如,对于CUDA9.2,请使用spacy-pytorch-transformers[cuda92]
;对于CUDA10.0,请使用spacy-pytorch-transformers[cuda100]
。
我们还预包装了一些预训练模型作为spaCy模型包。您可以使用spacy download
命令或从模型发布下载这些包。
包名 | 预训练模型 | 语言 | 作者 | 大小 | 发布 |
---|---|---|---|---|---|
en_pytt_bertbaseuncased_lg |
bert-base-uncased |
英语 | Google Research | 406MB | 📦️ |
de_pytt_bertbasecased_lg |
bert-base-german-cased |
德语 | deepset | 406MB | 📦️ |
en_pytt_xlnetbasecased_lg |
xlnet-base-cased |
英语 | CMU/Google Brain | 434MB | 📦️ |
en_pytt_robertabase_lg |
roberta-base |
英语 | 292MB | 📦️ | |
en_pytt_distilbertbaseuncased_lg |
distilbert-base-uncased |
英语 | Hugging Face | 245MB | 📦️ |
python -m spacy download en_pytt_bertbaseuncased_lg
python -m spacy download de_pytt_bertbasecased_lg
python -m spacy download en_pytt_xlnetbasecased_lg
python -m spacy download en_pytt_robertabase_lg
python -m spacy download en_pytt_distilbertbaseuncased_lg
安装模型后,您可以在spaCy中像其他模型包一样加载它。
import spacy
nlp = spacy.load("en_pytt_bertbaseuncased_lg")
doc = nlp("Apple shares rose on the news. Apple pie is delicious.")
print(doc[0].similarity(doc[7]))
print(doc._.pytt_last_hidden_state.shape)
💡如果您看到类似“没有模块名为‘spacy.lang.pytt’”的错误,请确保已安装
spacy-pytorch-transformers
。它需要可用,以便注册其语言入口点。还请确保您正在运行spaCy v2.1.7或更高版本。
📖 用法
迁移学习
预训练的transformer模型的主要用途是迁移学习。您加载一个在大量文本上预训练的大而通用的模型,并在您的较小数据集上开始训练,该数据集具有特定于您问题的标签。此包具有自定义管道组件,这使得迁移学习变得特别容易。我们提供了一个用于文本分类的示例组件。为其他任务开发类似组件应该相当直接。
pytt_textcat
组件基于spaCy内置的TextCategorizer
,并支持通过pytt_tok2vec
组件使用由PyTorch-Transformers模型分配的特征。这使您可以使用BERT之类的模型来预测上下文标记表示,然后在上面作为特定任务的“头部”学习文本分类器。API与任何其他spaCy管道相同。
TRAIN_DATA = [
("text1", {"cats": {"POSITIVE": 1.0, "NEGATIVE": 0.0}})
]
import spacy
from spacy.util import minibatch
import random
import torch
is_using_gpu = spacy.prefer_gpu()
if is_using_gpu:
torch.set_default_tensor_type("torch.cuda.FloatTensor")
nlp = spacy.load("en_pytt_bertbaseuncased_lg")
print(nlp.pipe_names) # ["sentencizer", "pytt_wordpiecer", "pytt_tok2vec"]
textcat = nlp.create_pipe("pytt_textcat", config={"exclusive_classes": True})
for label in ("POSITIVE", "NEGATIVE"):
textcat.add_label(label)
nlp.add_pipe(textcat)
optimizer = nlp.resume_training()
for i in range(10):
random.shuffle(TRAIN_DATA)
losses = {}
for batch in minibatch(TRAIN_DATA, size=8):
texts, cats = zip(*batch)
nlp.update(texts, cats, sgd=optimizer, losses=losses)
print(i, losses)
nlp.to_disk("/bert-textcat")
有关完整示例,请参阅examples/train_textcat.py
脚本。
向量和相似度
模型的PyTT_TokenVectorEncoder
组件设置自定义钩子,覆盖了Token、Span和Doc对象的默认行为.vector
属性和.similarity
方法。默认情况下,这些通常指的是在nlp.vocab.vectors
处的单词向量表。自然地,在transformer模型中,我们更愿意使用doc.tensor
属性,因为它包含一个更具有信息量的上下文敏感表示。
apple1 = nlp("Apple shares rose on the news.")
apple2 = nlp("Apple sold fewer iPhones this quarter.")
apple3 = nlp("Apple pie is delicious.")
print(apple1[0].similarity(apple2[0]))
print(apple1[0].similarity(apple3[0]))
序列化
保存和加载预训练的transformer模型以及将它们打包为spaCy模型✨只需这样✨(至少应该是这样的)。包装器和组件遵循spaCy的API,因此当您保存和加载nlp
对象时,它...
- 将预训练权重写入磁盘/字节并重新加载。
- 在
meta.json
中添加“lang_factory”:“pytt”,以便spaCy知道如何初始化Language
类。 - 在
meta.json
中的“requirements”中添加此包及其版本,以便当您运行spacy package
以创建可安装的Python包时,它会自动添加到设置中的install_requires
。
例如,如果您已训练自己的文本分类器,可以像这样打包它
python -m spacy package /bert-textcat /output
cd /output/en_pytt_bertbaseuncased_lg-1.0.0
python setup.py sdist
pip install dist/en_pytt_bertbaseuncased_lg-1.0.0.tar.gz
扩展属性
此包装器在 Doc
、Span
和 Token
对象上设置以下 自定义扩展属性。
名称 | 类型 | 描述 |
---|---|---|
._.pytt_alignment |
列表[列表[int]] |
单词片段和 spaCy 标记之间的对齐。包含每个 spaCy 标记的单词片段标记索引列表(每个 spaCy 标记一个),或者如果在一个 Token 上调用,则是一个索引列表。 |
._.pytt_word_pieces |
列表[int] |
单词片段 ID。 |
._.pytt_word_pieces_ |
列表[str] |
单词片段 ID 的字符串形式。 |
._.pytt_last_hidden_state |
ndarray |
PyTorch-Transformers 模型的 last_hidden_state 输出。 |
._.pytt_pooler_output |
列表[ndarray] |
PyTorch-Transformers 模型的 pooler_output 输出。 |
._.pytt_all_hidden_states |
列表[ndarray] |
PyTorch-Transformers 模型的 all_hidden_states 输出。 |
._.all_attentions |
列表[ndarray] |
PyTorch-Transformers 模型的 all_attentions 输出。 |
._.pytt_d_last_hidden_state |
ndarray |
PyTorch-Transformers 模型的 last_hidden_state 输出的梯度。 |
._.pytt_d_pooler_output |
列表[ndarray] |
PyTorch-Transformers 模型的 pooler_output 输出的梯度。 |
._.pytt_d_all_hidden_states |
列表[ndarray] |
PyTorch-Transformers 模型的 all_hidden_states 输出的梯度。 |
._.pytt_d_all_attentions |
列表[ndarray] |
PyTorch-Transformers 模型的 all_attentions 输出的梯度。 |
可以通过 ._
属性访问这些值。例如
doc = nlp("This is a text.")
print(doc._.pytt_word_pieces_)
设置管道
为了运行,使用 PyTT_Language
创建的 nlp
对象需要一些组件按顺序运行:一个分配句子边界的组件(例如 spaCy 内置的 Sentencizer
)、PyTT_WordPiecer
(分配单词片段标记)和 PyTT_TokenVectorEncoder
(分配标记向量)。pytt_name
参数定义了要使用的预训练模型的名称。使用 from_pretrained
方法通过 pytorch-transformers
加载预训练模型。
from spacy_pytorch_transformers import PyTT_Language, PyTT_WordPiecer, PyTT_TokenVectorEncoder
name = "bert-base-uncased"
nlp = PyTT_Language(pytt_name=name, meta={"lang": "en"})
nlp.add_pipe(nlp.create_pipe("sentencizer"))
nlp.add_pipe(PyTT_WordPiecer.from_pretrained(nlp.vocab, name))
nlp.add_pipe(PyTT_TokenVectorEncoder.from_pretrained(nlp.vocab, name))
print(nlp.pipe_names) # ['sentencizer', 'pytt_wordpiecer', 'pytt_tok2vec']
您还可以使用示例中的 init_model.py
脚本。
从路径加载模型
PyTorch-Transformers 模型也可以从文件路径加载,而不仅仅是名称。例如,假设您想使用 Allen AI 的 scibert
。首先,下载 PyTorch 模型文件,解压它们,解压 weights.tar
,将 bert_config.json
重命名为 config.json
,并将所有内容放入一个目录中。现在,您的目录应该有一个 pytorch_model.bin
、vocab.txt
和 config.json
。还请确保您的路径 包含模型名称。然后,您可以这样初始化 nlp
对象
from spacy_pytorch_transformers import PyTT_Language, PyTT_WordPiecer, PyTT_TokenVectorEncoder
name = "scibert-scivocab-uncased"
path = "/path/to/scibert-scivocab-uncased"
nlp = PyTT_Language(pytt_name=name, meta={"lang": "en"})
nlp.add_pipe(nlp.create_pipe("sentencizer"))
nlp.add_pipe(PyTT_WordPiecer.from_pretrained(nlp.vocab, path))
nlp.add_pipe(PyTT_TokenVectorEncoder.from_pretrained(nlp.vocab, path))
标记对齐
Transformer 模型通常在经过 "wordpiece" 算法预处理的文本上训练,这限制了模型需要考虑的不同标记类型数量。Wordpiece 对于训练神经网络来说很方便,但它不会产生与任何语言学术语中的 "词" 相匹配的分割。大多数罕见单词都会映射到多个单词片段标记,并且偶尔会出现多对多的对齐。spacy-pytorch-transformers
计算这种对齐,您可以在 doc._.pytt_alignment
处访问它。它是一个长度等于 spaCy 标记数的列表。列表中的每个值都是一个连续整数的列表,这些整数是单词片段列表中的索引。
如果您可以处理与实际单词不匹配的表示,最好使用 Transformer 的原始输出,可以在 doc._.pytt_last_hidden_state
处访问。这个变量提供了一个张量,其中每行对应一个单词片段标记。
如果您正在处理分词级别的任务,例如词性标注或拼写纠正,您将需要处理分词对齐特征,这些特征存储在 doc.tensor
变量中。
我们已经尽力以尽可能忠实的方式计算了对齐的 doc.tensor
表示,优先考虑避免信息损失。对齐的计算方式是确保 doc.tensor.sum(axis=1) == doc._.pytt_last_hidden_state.sum(axis=1)
。为了使这可行,doc.tensor
的每一行(对应于 spaCy 分词)都被设置为与该分词对齐的 last_hidden_state
张量行的一个加权求和,其中加权与对齐到该行的其他 spaCy 分词的数量成比例。为了包含来自(通常很重要 —— 参见 Clark 等人,2019)边界分词的信息,我们想象这些分词也被“对齐”到句子中的所有分词。
批量处理、填充和按句子处理
Transformer 模型的运行时间和内存复杂度与序列长度呈立方关系。这意味着需要将较长的文本分割成句子,以实现合理的效率。
spacy-pytorch-transformers
在内部处理此问题,并需要将此类句子边界检测组件添加到管道中。我们建议
sentencizer = nlp.create_pipe("sentencizer")
nlp.add_pipe(sentencizer, first=True)
内部,Transformer 模型将在句子上预测,并将生成的张量特征重建为文档级别的标注。
为了进一步提高效率和降低内存需求,spacy-pytorch-transformers
还在内部执行基于长度的子批量处理。子批量处理按序列长度重新分组批量句子,以最小化所需填充的数量。配置选项 words_per_batch
控制此行为。您可以将其设置为 0 以禁用子批量处理,或将其设置为整数以要求每个子批量的单词数(包括填充)的最大限制。默认值 3000 个单词在 Tesla V100 上表现良好。
许多预训练的 Transformer 模型都有一个最大序列长度。如果句子超过最大长度,它将被截断,受影响的结束分词将收到零向量。
🎛 API
class PyTT_Language
一个 Language
的子类,它包含 PyTorch-Transformer (PyTT) 管道。PyTT 管道的工作方式与 spaCy 的默认管道略有不同。具体来说,我们在管道的开始处引入了一个新的管道组件 PyTT_TokenVectorEncoder
。然后我们修改了 nlp.update
函数,在运行其他管道组件之前运行 PyTT_TokenVectorEncoder
,并在其他组件完成后进行反向传播。
staticmethod PyTT_Language.install_extensions
在 Doc
、Span
和 Token
对象上注册自定义扩展属性。如果扩展属性已注册,spaCy 将引发错误。有关将设置的扩展属性,请参阅此处。您通常不需要自己调用此方法 – 它在导入包时已经运行。
method PyTT_Language.__init__
请参阅 Language.__init__
。期望在 meta
中有一个 pytt_name
设置或作为关键字参数,指定预训练模型名称。这将用于设置特定于模型的分词器。
method PyTT_Language.update
更新管道中的模型。
名称 | 类型 | 描述 |
---|---|---|
docs |
可迭代对象 | 一个 Doc 对象的批次或 unicode。如果是 unicode,将根据文本创建一个 Doc 对象。 |
golds |
可迭代对象 | 一个 GoldParse 对象的批次或字典。将使用字典创建 GoldParse 对象。 |
drop |
浮点数 | 丢弃率。 |
sgd |
可调用对象 | 一个优化器。 |
losses |
字典 | 更新损失的字典,以管道组件为键。 |
component_cfg |
字典 | 特定管道组件的配置参数,以组件名称为键。 |
class PyTT_WordPiecer
spaCy 管道组件,用于将 PyTorch-Transformers 单词片段标记化分配给文档,之后可以被标记向量编码器使用。请注意,此组件不会修改 spaCy 的标记化。它只设置扩展属性 pytt_word_pieces_
、pytt_word_pieces
和 pytt_alignment
(单词片段标记和 spaCy 标记之间的对齐)。
该组件以 pytt_wordpiecer
的形式提供,并通过入口注册,因此也可以使用 nlp.create_pipe
创建。
wordpiecer = nlp.create_pipe("pytt_wordpiecer")
配置
该组件可以使用以下设置进行配置,通常通过 **cfg
传递。
名称 | 类型 | 描述 |
---|---|---|
pytt_name |
unicode | 预训练模型的名称,例如 "bert-base-uncased" 。 |
classmethod PyTT_WordPiecer.from_nlp
通过入口点添加到 Language.factories
的工厂。
名称 | 类型 | 描述 |
---|---|---|
nlp |
spacy.language.Language |
创建组件时使用的 nlp 对象。 |
**cfg |
- | 可选配置参数。 |
返回值 | PyTT_WordPiecer |
单词片段器。 |
method PyTT_WordPiecer.__init__
初始化组件。
名称 | 类型 | 描述 |
---|---|---|
vocab |
spacy.vocab.Vocab |
要使用的 spaCy 词汇表。 |
name |
unicode | 预训练模型的名称,例如 "bert-base-uncased" 。 |
**cfg |
- | 可选配置参数。 |
返回值 | PyTT_WordPiecer |
单词片段器。 |
method PyTT_WordPiecer.predict
对一批文档运行单词片段标记化器并返回提取的字符串。
名称 | 类型 | 描述 |
---|---|---|
docs |
可迭代对象 | 要处理的文档批次。 |
返回值 | tuple | 一个 (strings, None) 元组。字符串是每个 Doc 的字符串列表。 |
method PyTT_WordPiecer.set_annotations
将提取的标记和 ID 分配给 Doc
对象。
名称 | 类型 | 描述 |
---|---|---|
docs |
可迭代对象 | 一批 Doc 对象。 |
outputs |
可迭代对象 | 一批输出。 |
class PyTT_TokenVectorEncoder
spaCy 管道组件,用于使用 PyTorch-Transformers 模型。该组件将转换器的输出分配给扩展属性。我们还计算了单词片段标记和 spaCy 标记之间的对齐,以便我们可以使用最后一个隐藏状态来设置 doc.tensor
属性。当多个单词片段标记与同一个 spaCy 标记对齐时,spaCy 标记将接收它们值的总和。
该组件以 pytt_tok2vec
的形式提供,并通过入口注册,因此也可以使用 nlp.create_pipe
创建。
tok2vec = nlp.create_pipe("pytt_tok2vec")
配置
该组件可以使用以下设置进行配置,通常通过 **cfg
传递。
名称 | 类型 | 描述 |
---|---|---|
pytt_name |
unicode | 预训练模型的名称,例如 "bert-base-uncased" 。 |
words_per_batch |
int | 将句子分组为最大大小为 words_per_batch 的子批次。例如,一个包含一个 100 词句子和一个 10 词句子的批次大小将为 200(由于填充)。设置为 0 以禁用。默认为 2000 。 |
classmethod PyTT_TokenVectorEncoder.from_nlp
通过入口点添加到 Language.factories
的工厂。
名称 | 类型 | 描述 |
---|---|---|
nlp |
spacy.language.Language |
创建组件时使用的 nlp 对象。 |
**cfg |
- | 可选配置参数。 |
返回值 | PyTT_TokenVectorEncoder |
标记向量编码器。 |
classmethod PyTT_TokenVectorEncoder.from_pretrained
使用来自 PyTorch-Transformers 模型的预训练权重创建一个 PyTT_TokenVectorEncoder
实例,即使它没有作为 spaCy 包安装。
from spacy_pytorch_transformers import PyTT_TokenVectorEncoder
from spacy.tokens import Vocab
tok2vec = PyTT_TokenVectorEncoder.from_pretrained(Vocab(), "bert-base-uncased")
名称 | 类型 | 描述 |
---|---|---|
vocab |
spacy.vocab.Vocab |
要使用的 spaCy 词汇表。 |
name |
unicode | 预训练模型的名称,例如 "bert-base-uncased" 。 |
**cfg |
- | 可选配置参数。 |
返回值 | PyTT_TokenVectorEncoder |
标记向量编码器。 |
classmethod PyTT_TokenVectorEncoder.Model
创建一个 PyTT_Wrapper
实例,它包含 PyTorch-Transformers 模型。
名称 | 类型 | 描述 |
---|---|---|
name |
unicode | 预训练模型的名称,例如 "bert-base-uncased" 。 |
**cfg |
- | 可选配置参数。 |
返回值 | thinc.neural.Model |
包装的模型。 |
method PyTT_TokenVectorEncoder.__init__
初始化组件。
名称 | 类型 | 描述 |
---|---|---|
vocab |
spacy.vocab.Vocab |
要使用的 spaCy 词汇表。 |
model |
thinc.neural.Model / True |
组件的模型或 True 如果尚未初始化。 |
**cfg |
- | 可选配置参数。 |
返回值 | PyTT_TokenVectorEncoder |
标记向量编码器。 |
method PyTT_TokenVectorEncoder.__call__
处理一个 Doc
并分配提取的特征。
名称 | 类型 | 描述 |
---|---|---|
doc |
spacy.tokens.Doc |
要处理的 Doc 。 |
返回值 | spacy.tokens.Doc |
处理后的 Doc 。 |
method PyTT_TokenVectorEncoder.pipe
将 Doc
对象作为流处理并分配提取的特征。
名称 | 类型 | 描述 |
---|---|---|
stream |
可迭代对象 | 一个 Doc 对象流。 |
batch_size |
int | 要缓冲的文本数量。默认为 128 。 |
产出 | spacy.tokens.Doc |
按顺序处理的 Doc 。 |
方法 PyTT_TokenVectorEncoder.predict
在文档批次上运行transformer模型,并返回提取的特征。
名称 | 类型 | 描述 |
---|---|---|
docs |
可迭代对象 | 要处理的文档批次。 |
返回值 | namedtuple |
包含输出的命名元组。 |
方法 PyTT_TokenVectorEncoder.set_annotations
将提取的特征分配给Doc对象,并覆盖向量和相似性钩子。
名称 | 类型 | 描述 |
---|---|---|
docs |
可迭代对象 | 一批 Doc 对象。 |
outputs |
可迭代对象 | 一批输出。 |
类 PyTT_TextCategorizer
spaCy内置的TextCategorizer
组件的子类,支持通过token vector encoder使用PyTorch-Transformers模型分配的特征。它需要在管道中先于PyTT_TokenVectorEncoder
运行。
该组件以pytt_textcat
的形式提供,并通过入口点注册,因此也可以使用nlp.create_pipe
创建。
textcat = nlp.create_pipe("pytt_textcat")
classmethod PyTT_TextCategorizer.from_nlp
通过入口点添加到 Language.factories
的工厂。
名称 | 类型 | 描述 |
---|---|---|
nlp |
spacy.language.Language |
创建组件时使用的 nlp 对象。 |
**cfg |
- | 可选配置参数。 |
返回值 | PyTT_TextCategorizer |
文本分类器。 |
classmethod PyTT_TextCategorizer.Model
使用PyTorch-Transformers模型进行token vector编码来创建文本分类模型。
名称 | 类型 | 描述 |
---|---|---|
nr_class |
int | 类别数量。 |
width |
int | 分配的张量的宽度。 |
exclusive_classes |
bool | 使类别相互排斥。默认为False 。 |
**cfg |
- | 可选配置参数。 |
返回值 | thinc.neural.Model |
模型。 |
dataclass Activations
数据类,用于存储PyTorch-Transformers生成的特征。
属性 | 类型 | 描述 |
---|---|---|
last_hidden_state |
对象 | |
pooler_output |
对象 | |
all_hidden_states |
对象 | |
all_attentions |
对象 | |
is_grad |
bool |
入口点
此包公开了几个入口点,这些入口点告诉spaCy如何初始化其组件。如果spacy-pytorch-transformers
和spaCy安装在同一环境中,您将能够运行以下操作,并按预期工作
tok2vec = nlp.create_pipe("pytt_tok2vec")
这也意味着您的自定义模型可以提供pytt_tok2vec
组件,并在其管道中定义"pytt_tok2vec"
,当您反序列化模型时,spaCy将知道如何创建这些组件。以下入口点已设置
名称 | 目标 | 类型 | 描述 |
---|---|---|---|
pytt_wordpiecer |
PyTT_WordPiecer |
spacy_factories |
创建组件的工厂。 |
pytt_tok2vec |
PyTT_TokenVectorEncoder |
spacy_factories |
创建组件的工厂。 |
pytt_textcat |
PyTT_TextCategorizer |
spacy_factories |
创建组件的工厂。 |
pytt |
PyTT_Language |
spacy_languages |
自定义的Language 子类。 |
项目详情
下载文件
下载适用于您的平台文件。如果您不确定要选择哪个,请了解更多关于安装包的信息。
源分布
构建分布
spacy_pytorch_transformers-0.4.0-py3-none-any.whl的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 77ed625fb02001f73b55d62ff5388b33ad23995465e3a48334742317eac7a10f |
|
MD5 | 943c07c260ba7f3da26880cac4b0ab34 |
|
BLAKE2b-256 | fd463271586944ee5e0bd493df03b1ad189eb9ccdad1d2476aeb843b0d2f1b47 |