如何检查两个 spaCy Doc 对象之间的差异?
How to check for differences between two spaCy Doc objects?
我有两个相同字符串的列表,除了第二个列表的字符串略有不同,即没有大写、拼写错误等。
我想检查 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 还没有得到解答,当然现在除了这个线程之外。
尝试使用 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
令牌级别比较
如果您想知道注释是否不同,您必须逐个标记地检查文档以比较 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 相同)。
这个python端口有一点不稳定,但基本上似乎可以工作:https://github.com/ppke-nlpg/whats-wrong-python
不过,他们似乎都假设我们有黄金 POS 标签,因此不会自动显示比较。您还可以连接 POS 列以便能够看到两者(就像使用标记一样),因为您确实需要 POS 标签来理解为什么解析不同。
对于令牌对和 POS 对,我认为很容易修改原始实现或 python 端口以在附加行中分别显示这两种替代方案,因此您不必进行骇人听闻的连接。
我有两个相同字符串的列表,除了第二个列表的字符串略有不同,即没有大写、拼写错误等。
我想检查 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 还没有得到解答,当然现在除了这个线程之外。
尝试使用 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
令牌级别比较
如果您想知道注释是否不同,您必须逐个标记地检查文档以比较 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 相同)。
这个python端口有一点不稳定,但基本上似乎可以工作:https://github.com/ppke-nlpg/whats-wrong-python
不过,他们似乎都假设我们有黄金 POS 标签,因此不会自动显示比较。您还可以连接 POS 列以便能够看到两者(就像使用标记一样),因为您确实需要 POS 标签来理解为什么解析不同。
对于令牌对和 POS 对,我认为很容易修改原始实现或 python 端口以在附加行中分别显示这两种替代方案,因此您不必进行骇人听闻的连接。