【问题标题】:How to check for differences between two spaCy Doc objects?如何检查两个 spaCy Doc 对象之间的差异?
【发布时间】:2023-03-14 15:06:02
【问题描述】:

我有两个相同字符串的列表,除了第二个列表的字符串略有不同,即没有大写、拼写错误等。

我想检查 spaCy 是否在两个字符串之间做任何不同的事情。这意味着即使字符串不等价,我也想知道标记和解析是否存在差异。

我尝试了以下方法:

import spacy
import en_core_web_sm
nlp = en_core_web_sm.load()

doc = nlp("foo")
doc2 = nlp("foo")

print(doc == doc2)

这会打印出False,所以== 不是要走的路。

理想情况下,我希望我的代码找出潜在差异所在,但检查是否有任何不同之处将是非常有用的第一步。

编辑:

== 已更改为在较新的 SpaCy 版本中工作。但是,它只比较文本级别。对于依赖,这是一个完全不同的故事,除了现在这个线程之外,还没有回答 spaCy 的问题。

【问题讨论】:

标签: nlp spacy equivalence


【解决方案1】:

尝试使用 spaCy 的doc.similarity() 函数。

例如:

import spacy

nlp = spacy.load('en_core_web_md')  # make sure to use larger model!
tokens = nlp(u'dog cat banana')

for token1 in tokens:
    for token2 in tokens:
        print(token1.text, token2.text, token1.similarity(token2))

结果将是:

参考来自:https://spacy.io

【讨论】:

  • 这不是正确的方向。此示例使用词汇/语义相似度度量来比较一个文档中的标记,而不是比较两个不同文档之间的语言注释
【解决方案2】:

令牌级比较

如果您想知道注释是否不同,则必须逐个标记地检查文档以比较 POS 标签、依赖标签等。假设两个版本的文本的标记化相同,您可以比较:

import spacy
nlp = spacy.load('en')
doc1 = nlp("What's wrong with my NLP?")
doc2 = nlp("What's wring wit my nlp?")
for token1, token2 in zip(doc1, doc2):
    print(token1.pos_, token2.pos_, token1.pos1 == token2.pos1)

输出:

NOUN NOUN True
VERB VERB True
ADJ VERB False
ADP NOUN False
ADJ ADJ True
NOUN NOUN True
PUNCT PUNCT True

解析比较的可视化

如果您想直观地检查差异,您可能正在寻找类似What's Wrong With My NLP? 的内容。如果文档的两个版本的标记化相同,那么我认为您可以执行以下操作来比较解析:

首先,您需要将注释导出为受支持的格式(用于依赖解析的某些版本的 CoNLL),这是 textacy 可以做到的。 (见:https://www.pydoc.io/pypi/textacy-0.4.0/autoapi/export/index.html#export.export.doc_to_conll

from textacy import export
export.doc_to_conll(nlp('What's wrong with my NLP?'))

输出:

# sent_id 1
1       What    what    NOUN    WP      _       2       nsubj   _       SpaceAfter=No
2       's      be      VERB    VBZ     _       0       root    _       _
3       wrong   wrong   ADJ     JJ      _       2       acomp   _       _
4       with    with    ADP     IN      _       3       prep    _       _
5       my      -PRON-  ADJ     PRP$    _       6       poss    _       _
6       NLP     nlp     NOUN    NN      _       4       pobj    _       SpaceAfter=No
7       ?       ?       PUNCT   .       _       2       punct   _       SpaceAfter=No

然后您需要决定如何修改内容,以便您可以在分析中看到两个版本的令牌。我建议在有变化的地方连接标记,比如:

1       What         what    NOUN    WP      _       2       nsubj   _       SpaceAfter=No
2       's           be      VERB    VBZ     _       0       root    _       _
3       wrong_wring  wrong   ADJ     JJ      _       2       acomp   _       _
4       with_wit     with    ADP     IN      _       3       prep    _       _
5       my           -PRON-  ADJ     PRP$    _       6       poss    _       _
6       NLP_nlp      nlp     NOUN    NN      _       4       pobj    _       SpaceAfter=No
7       ?            ?       PUNCT   .       _       2       punct   _       SpaceAfter=No

对比What's wring wit my nlp? 的注解:

1       What         what    NOUN    WP      _       3       nsubj   _       SpaceAfter=No
2       's           be      VERB    VBZ     _       3       aux     _       _
3       wrong_wring  wr      VERB    VBG     _       4       csubj   _       _
4       with_wit     wit     NOUN    NN      _       0       root    _       _
5       my           -PRON-  ADJ     PRP$    _       6       poss    _       _
6       NLP_nlp      nlp     NOUN    NN      _       4       dobj    _       SpaceAfter=No
7       ?            ?       PUNCT   .       _       4       punct   _       SpaceAfter=No

然后您需要将这两个文件都转换为 whatswrong 支持的旧版 CoNLL。 (主要问题只是删除以# 开头的注释行。)现有的一个选项是UD 工具CoNLL-U 到CoNLL-X 转换器:https://github.com/UniversalDependencies/tools/blob/master/conllu_to_conllx.pl,然后你有:

1       What         what    NOUN    NOUN_WP _       2       nsubj   _       _
2       's           be      VERB    VERB_VBZ        _       0       root    _       _
3       wrong_wring  wrong   ADJ     ADJ_JJ  _       2       acomp   _       _
4       with_wit     with    ADP     ADP_IN  _       3       prep    _       _
5       my           -PRON-  ADJ     ADJ_PRP$        _       6       poss    _       _
6       NLP_nlp      nlp     NOUN    NOUN_NN _       4       pobj    _       _
7       ?            ?       PUNCT   PUNCT_. _       2       punct   _       _

您可以加载这些文件(一个作为黄金,一个作为猜测)并使用 whatswrong 进行比较。选择格式为 CoNLL 2006(CoNLL 2006 与 CoNLL-X 相同)。

whatswrong的这个python端口有点不稳定,但也基本可以用:https://github.com/ppke-nlpg/whats-wrong-python

不过,他们似乎都假设我们有黄金 POS 标签,因此不会自动显示比较。您还可以连接 POS 列以便能够看到两者(就像使用标记一样),因为您确实需要 POS 标签来了解解析不同的原因。

对于令牌对和 POS 对,我认为修改原始实现或 python 端口以在附加行中分别显示两种替代方案很容易,因此您不必进行 hacky 连接。

【讨论】:

  • 非常感谢您为此花费的时间和精力。这正是我想要的,还有更多!
猜你喜欢
  • 2019-05-02
  • 1970-01-01
  • 1970-01-01
  • 2017-03-08
  • 1970-01-01
  • 2014-06-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多