首页 > 解决方案 > 有没有一种方法可以从法语句子中提取名词-形容词对?

问题描述

我有这段代码可以使用 spacy 提取名词-形容词对,但是这段代码非常适合英语而不是法语,因为在法语中我们很难提取一对名词-形容词:

1- la voiture est belle,grande et jolie。(当我们有很多形容词时,CCONJ = "et") 2- le tableau qui est juste en dessous est grand et beau。(所以我们在这里有一个共指,我们应该将 grand et beau 与“tableau”相关联

我知道 spacy 中的dependencymatcher 是健壮的,但在我的情况下,有时我的文本没有被清理,因为它是关于人们的意见......所以我们需要手动执行此操作......

在输出中我们应该有这样的东西: {"voiture":["belle","grande","jolie"], "tableau":["beau","grand"]}

import spacy

nlp = spacy.load("fr_core_news_sm")
doc = nlp('la voiture est belle et jolie. le tableau qui est juste en dessous est grand ') 
noun_adj_pairs = {}
for chunk in doc.noun_chunks:
    adj = []
    noun = ""
    for tok in chunk:
        if tok.pos_ == "NOUN":
           noun = tok.text
        if tok.pos_ == "ADJ" or tok.pos_ == "CCONJ":
           adj.append(tok.text)
    if noun:
        noun_adj_pairs.update({noun:" ".join(adj)}) 

标签: pythonpython-3.xnlpspacy

解决方案


我通过使用stanza高质量的依赖解析写了一些东西。如果您特别需要,将其转换为 spaCy 应该不是很多工作。如果您需要查找嵌入式结构,则需要递归。请注意,这特别适用于形容词是您感兴趣的主题的父级而不适用于形容词位置的结构。例如,这不会找到像La belle voiture这样的形容词。

import stanza

nlp = stanza.Pipeline("fr")

doc = nlp("La voiture est belle et jolie, et grand. Le tableau qui est juste en dessous est grand. La femme intelligente et belle est grande. Le service est rapide et les plats sont délicieux.")

def recursive_find_adjs(root, sent):
    children = [w for w in sent.words if w.head == root.id]

    if not children:
        return []

    filtered_c = [w for w in children if w.deprel == "conj" and w.upos == "ADJ"]
    # Do not include an adjective if it is the parent of a noun to prevent
    results = [w for w in filtered_c if not any(sub.head == w.id and sub.upos == "NOUN" for sub in sent.words)]
    for w in children:
        results += recursive_find_adjs(w, sent)

    return results

for sent in doc.sentences:
    nouns = [w for w in sent.words if w.upos == "NOUN"]
    noun_adj_pairs = {}
    for noun in nouns:
        # Find constructions in the form of "La voiture est belle"
        # In this scenario, the adjective is the parent of the noun
        cop_root = sent.words[noun.head-1]
        adjs = [cop_root] + recursive_find_adjs(cop_root, sent) if cop_root.upos == "ADJ" else []

        # Find constructions in the form of "La femme intelligente et belle"
        # Here, the adjectives are descendants of the noun
        mod_adjs = [w for w in sent.words if w.head == noun.id and w.upos == "ADJ"]
        # This should only be one element because conjunctions are hierarchical
        if mod_adjs:
            mod_adj = mod_adjs[0]
            adjs.extend([mod_adj] + recursive_find_adjs(mod_adj, sent))

        if adjs:
            unique_adjs = []
            unique_ids = set()
            for adj in adjs:
                if adj.id not in unique_ids:
                    unique_adjs.append(adj)
                    unique_ids.add(adj.id)

            noun_adj_pairs[noun.text] = " ".join([adj.text for adj in unique_adjs])

    print(noun_adj_pairs)

这将输出:

{'voiture': 'belle jolie grand'}
{'tableau': 'grand'}
{'femme': 'grande belle intelligente'}
{'service': 'rapide', 'plats': 'délicieux'}

推荐阅读