跳转到主要内容

spaCy预训练BERT和其他transformers的管道

项目描述

spaCy的PyTorch Transformers包装器

此软件包提供了spaCy模型管道,用于包装Hugging Face的pytorch-transformers软件包,以便您可以在spaCy中使用它们。结果是方便地访问最先进的transformer架构,如BERT、GPT-2、XLNet等。有关更多详细信息和方法背景,请参阅我们的博客文章

Azure Pipelines PyPi GitHub Code style: black Open demo in Colab

功能

  • 直接在spaCy管道中使用BERTRoBERTaXLNetGPT-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 英语 Facebook 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

扩展属性

此包装器在 DocSpanToken 对象上设置以下 自定义扩展属性

名称 类型 描述
._.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.binvocab.txtconfig.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

DocSpanToken 对象上注册自定义扩展属性。如果扩展属性已注册,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_piecespytt_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.tar.gz (56.5 kB 查看散列)

上传时间

构建分布

spacy_pytorch_transformers-0.4.0-py3-none-any.whl (62.1 kB 查看散列)

上传时间 Python 3

由以下支持