Spacy:如何获取所有描述名词的单词?

8

我对Spacy和NLP都不熟悉。

为了理解Spacy的工作原理,我想创建一个函数,该函数接受一个句子并返回一个带有名词及其描述词的字典、元组或列表。

我知道Spacy会创建句子的树形结构,并知道每个单词的用法(在displacy中显示)。

但是怎样才能正确地从以下内容获取:

"A large room with two yellow dishwashers in it"

到:

{noun:"room",adj:"large"} {noun:"dishwasher",adj:"yellow",adv:"two"}

或者通过其他可用的方式将所有相关的单词捆绑在一起。

提前感谢!

2个回答

10

这是使用DependencyMatcher的非常直接的用法。

import spacy
from spacy.matcher import DependencyMatcher

nlp = spacy.load("en_core_web_sm")

pattern = [
  {
    "RIGHT_ID": "target",
    "RIGHT_ATTRS": {"POS": "NOUN"}
  },
  # founded -> subject
  {
    "LEFT_ID": "target",
    "REL_OP": ">",
    "RIGHT_ID": "modifier",
    "RIGHT_ATTRS": {"DEP": {"IN": ["amod", "nummod"]}}
  },
]

matcher = DependencyMatcher(nlp.vocab)
matcher.add("FOUNDED", [pattern])

text = "A large room with two yellow dishwashers in it"
doc = nlp(text)
for match_id, (target, modifier) in matcher(doc):
    print(doc[modifier], doc[target], sep="\t")

输出:

large   room
two dishwashers
yellow  dishwashers

将其转化为字典或您想要的任何内容应该很容易。 您可能还希望修改以将专有名词作为目标,或支持其他类型的依赖关系,但这应该是一个很好的开始。

您还可以查看名词块功能。


1
抱歉回复晚了,但是非常感谢你,这正好产生了我想要的输出!虽然我并不完全理解你的代码在干什么 :) 但我认为阅读你所发的文档会有所帮助 :) - mathi1651
希望你在我评论时能收到通知 :) 我已经理解了Attrs和模式本身,但似乎找不到关于ids的任何信息:有哪些可能的ids,以及目标和修饰符是什么意思?此外,我真的不明白相对运算符在这种情况下的用途..如果你能抽出时间给我一个简短的解释或文档链接,我会很高兴的 :) 谢谢! - mathi1651
ID是您自己编制的名称,可以是任何内容。操作符来自Semgrex。文档已经链接在我的答案顶部,并解释了这两个事情。 - polm23
RIGHT_ATTRS {"DEP": {"IN": ["amod", "nummod"]}} 的含义是什么? - Golden Lion

3
你想做的是称为“名词短语”:
import spacy
nlp = spacy.load('en_core_web_md')
txt = "A large room with two yellow dishwashers in it"
doc = nlp(txt)

chunks = []
for chunk in doc.noun_chunks:
    out = {}
    root = chunk.root
    out[root.pos_] = root
    for tok in chunk:
        if tok != root:
            out[tok.pos_] = tok
    chunks.append(out)
print(chunks)

[
 {'NOUN': room, 'DET': A, 'ADJ': large}, 
 {'NOUN': dishwashers, 'NUM': two, 'ADJ': yellow}, 
 {'PRON': it}
]

您可能会注意到,“名词块”并不保证其根始终是名词。如果您希望仅限于名词的结果:
chunks = []
for chunk in doc.noun_chunks:
    out = {}
    noun = chunk.root
    if noun.pos_ != 'NOUN':
        continue
    out['noun'] = noun
    for tok in chunk:
        if tok != noun:
            out[tok.pos_] = tok
    chunks.append(out)
    
print(chunks)

[
 {'noun': room, 'DET': A, 'ADJ': large}, 
 {'noun': dishwashers, 'NUM': two, 'ADJ': yellow}
]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接