使用带有 AllenNLP Interpret 或 Textattack 的 spaCy 模型

Posted

技术标签:

【中文标题】使用带有 AllenNLP Interpret 或 Textattack 的 spaCy 模型【英文标题】:Using spaCy models with AllenNLP Interpret or Textattack 【发布时间】:2020-09-05 10:12:21 【问题描述】:

AllenNLP Interpret 和 Textattack 应该“攻击”模型以找出它们生成输出的原因。我主要使用 spaCy 来训练我的模型,并且想尝试其中的任何一个框架,看看它们是否能让我更好地理解我的模型。但似乎它们与 spaCy 模型不兼容(或者我做错了什么)。对于 Textattack,我尝试按照以下示例进行操作: https://textattack.readthedocs.io/en/latest/quickstart/overview.html 但是用 spaCy 模型交换模型。那效果不好,因为在 TokenizedText 类里面有

ids = tokenizer.encode(text)

这会引发错误,因为 spaCy 的 Tokenizer 对象没有名为 encode() 的方法。我注意到 Textattack 的 Tokenizer 和 SpacyTokenizer 有多个子类。如果那是 Tokenizer 的兼容版本,为什么不自动检测并调用它呢?我尝试交换它们,但我对 SpacyTokenizer 所需的一些参数感到困惑:

def __init__(self, word2id, oov_id, pad_id, max_seq_length=128)

word2id 是 word-id 配对,但是什么样的 id?它是针对词汇中的所有单词还是仅针对这个特定句子的标记? oov_id 更令人困惑,因为“oov”代表“o​​ut-of-variable”,而不是 spaCy 中的“out-of-vocabulary”。此外,在 spaCy 中,它是一个布尔值,而不是一个 id。 pad_id 根本没有解释,我也不知道它是什么。

因此,Textattack 和 spaCy 之间似乎存在某种联系,但我不知道如何将它们组合成一个工作示例。

当谈到 AllenNLP 解释时,我尝试使用 hotflip 攻击,但首先发生的是以下错误消息:

for i in self.vocab._index_to_token[self.namespace]:
AttributeError: 'spacy.vocab.Vocab' object has no attribute '_index_to_token'

所以这个框架似乎也不适合 spaCy,因为它需要 _index_to_token,但 spaCy 的 Vocab 没有。

谁能帮帮我?

【问题讨论】:

【参考方案1】:

我是 TextAttack 的创建者之一。我们内置的 SpaCyTokenizer 使用 SpaCy 将单词转换为标记,但需要一个字典,该字典应该将标记转换为相应的 ID。这样您就可以传入嵌入的单词到 ID 映射,并将这些 ID 与 SpaCy 令牌一起使用。这就是我们的模型在幕后工作的方式。

我需要更多信息来提供帮助。训练模型时,如何将文本转换为 ID?你能给我提供一个使用你的标记器将字符串转换为标记 ID 列表的代码的 sn-p 吗?然后我可以向您展示如何包装您的标记器以使用 TextAttack。

希望这是有道理的。默认情况下,我们肯定可以更聪明地使用标记器并支持标记器,我们将在未来的更新中继续努力。

【讨论】:

嗨,感谢您的回答 :) 看起来 spaCy 使用 Vocab 将字符串 ID 映射存储在 Vocab.strings 中。示例:``` import spacy nlp = spacy.load('spacy_models/news4') eple_id = nlp.vocab.strings['eple'] ``` eple_id 是单词 ' 的哈希值eple'(显然 spaCy 将 id 转换为哈希值)。 Vocab 也是创建 Tokenizer 所必需的:``` tokenizer = Tokenizer(nlp.vocab) ``` 这有帮助吗? 嗨@KaisaK - 这是我需要的信息的一部分。你能解释一下你如何使用 Vocab 来查询你的模型吗?请举例说明如何标记字符串并将其传递给模型。然后我将向您展示如何为 TextAttack 配置它! 当您将字符串传递给 Language 对象 (nlp) 时,它会创建一个传递字符串的 Tokenizer 对象。 Tokenizer 然后拆分文本并将令牌的跨度和哈希保存到包含所有令牌的 Doc 对象(Doc 定义如下: cdef Doc doc = Doc(self.vocab))。请注意,TokenizerDoc 是用 Cython/C++ 编写的(取决于 spaCy 版本),不幸的是我不太熟悉,所以我正在尽我所能: ) 要获取令牌 ID,请执行以下操作:doc = nlp(text_string) for token in doc: hash_id = nlp.vocab.strings[token.text] 每个 Doc 对象由多个 Token 对象组成,这些对象将其字符串值存储在 .text 中,而 Vocab 是“跨语言共享的词汇和其他数据的存储类”,因此它是基于查找表为每种语言创建的。希望它以某种方式有意义:) @KaisaK -- 好的,我想我可以帮助你!你介意在我们的 Github repo 上提出问题,以便我们可以在那里更快地响应吗?谢谢。

以上是关于使用带有 AllenNLP Interpret 或 Textattack 的 spaCy 模型的主要内容,如果未能解决你的问题,请参考以下文章

在 allennlp 中使用 Transformer QA 预训练模型进行阅读理解的通过限制

Allennlp coref 模型最新版本

将 AllenNLP 解释与 HuggingFace 模型一起使用

与非多处理情况相比,使用 AllenNLP 解码的多处理是缓慢的

使用预训练的掩码语言模型训练 AllenNLP 对抗性偏见缓解器时出错

将 HuggingFace 模型加载到 AllenNLP 中会给出不同的预测