使用 spaCy 查找一个词是否在两个实体的依赖路径上

Finding whether or not, a word is on the dependency path of two entities with spaCy

我正在处理一个 nlp 问题,给定一个包含两个实体的句子,我需要为每个单词生成布尔值指示它是否位于这些实体之间的依赖路径上。

例如:

'A misty < e1 >ridge< /e1 > uprises from the < e2 >surge< /e2 >'

我想遍历每个词并判断它是否在 e1 和 e2 之间的依赖路径上

两个重要说明:

-如果你想帮助我(首先感谢),请不要费心考虑带有 的 xml 标记,我真的很感兴趣如何找到一个词是否是在 spaCy 的任意两个给定单词之间的依赖路径上,我自己处理哪些单词

-由于我不是nlp专家,我对"on the dependency path"的意思有点困惑,如果不够清楚,我很抱歉(这些是我的导师用的词)

提前致谢

依赖路径是一种描述从句如何在句子中构建的方式。 SpaCy 在他们的文档 here 中有一个非常好的例子,句子 Apple is looking at buying U.K. startup for billion.

请原谅我在此处缺乏良好的可视化效果,但要完成您的示例:

A misty ridge uprises from the surge.

在spaCy中,我们按照他们的例子来获取依赖:

import spacy
nlp = spacy.load('en_core_web_lg')
doc = nlp("A misty ridge uprises from the surge.")
for chunk in doc.noun_chunks:
    print(chunk.text, chunk.root.text, chunk.root.dep_, chunk.root.head.text)

这将得到构成你的句子的 "clauses"。您的输出将如下所示:

Text                  | root.text| root.dep_ | root.head.text
A misty ridge uprises   uprises    ROOT        uprises
the surge               surge      pobj        from

chunk.text 是组成你的从句的文本(注意,根据句子结构可能会有重叠)。 root.text 给出依赖树的根(或头)。树的 head 是一个 spaCy token 对象,并且有您可以遍历以检查依赖树上是否有另一个标记的子对象。

def find_dependencies(doc, word_to_check=None, dep_choice=None):
    """
    word_to_check is the word you'd like to see on the dependency tree
    example, word_to_check="misty"

    dep_choice is the text of the item you'd like the dependency check
    to be against. Example, dep_choice='ridge'
    """
    tokens, texts = [], []

    for tok in doc:
        tokens.append(tok)
        texts.append(tok.text)

    # grabs the index/indices of the token that you are interested in
    indices = [i for i,text in enumerate(texts) if text==dep_choice]

    words_in_path = []

    for i in indices:

        reference = tokens[i]
        child_elements = [t.text for t in reference.get_children()]
        if word_to_check in child_elements:
            words_in_path.append((word_to_check, reference))

    return words_in_path

该代码不是最漂亮的,但这是您可以获得元组列表的一种方式,其中包含您要检查的单词与关联的父标记。希望这对您有所帮助

编辑:

为了更适合您的用例(并大大简化我原来的答案):

# This will give you 'word':<spaCy doc object> key value lookup capability
tokens_lookup = {tok.text:tok for tok in doc}

if "misty" in tokens_lookup.get("ridge").children:
    # Extra logic here

所以我的解决方案是使用

找到的

有专门针对 spaCy 的回答

我对找到给定句子中两个词之间的依赖路径的实现

import networkx as nx
import spacy
enter code here
doc = nlp("Ships carrying equipment for US troops are already waiting off the Turkish coast")
    
def shortest_dependency_path(doc, e1=None, e2=None):
    edges = []
    for token in doc:
        for child in token.children:
            edges.append(('{0}'.format(token),
                          '{0}'.format(child)))
    graph = nx.Graph(edges)
    try:
        shortest_path = nx.shortest_path(graph, source=e1, target=e2)
    except nx.NetworkXNoPath:
        shortest_path = []
    return shortest_path

print(shortest_dependency_path(doc,'Ships','troops'))

输出:

['Ships', 'carrying', 'for', 'troops']

它实际上做的是首先为句子建立一个无向图,其中单词是节点,单词之间的依赖关系是边缘,然后找到两个节点之间的最短路径

为了我的需要,我只是检查每个单词是否在生成的依赖路径(最短路径)上