使用 spaCy 删除包含停用词的名词短语

Removing noun phrases containing stop words using spaCy

我一直在使用 spaCy 寻找最常用的名词 noun_phrases

我在查找单个名词时可以成功去掉标点符号和停用词

docx = nlp('The bird is flying high in the sky blue of color')

# Just looking at nouns
nouns = []
for token in docx:
    if token.is_stop != True and token.is_punct != True and token.pos_ == 'NOUN':
        nouns.append(token)

# Count and look at the most frequent nouns #
word_freq = Counter(nouns)
common_nouns = word_freq.most_common(10)

使用 noun_chunks 来确定短语但是会导致属性错误

noun_phrases = []
for noun in docx.noun_chunks: 
    if len(noun) > 1 and '-PRON-' not in noun.lemma_ and noun.is_stop:
        noun_phrases.append(noun)

AttributeError: 'spacy.tokens.span.Span' object has no attribute> 'is_stop'

我理解消息的本质,但我终其一生都无法正确地理解语法,其中在词形化字符串中出现停用词将被排除在附加到 noun_phrases 列表之外

不删除停用词的输出

[{'word': 'The bird', 'lemma': 'the bird', 'len': 2}, {'word': 'the sky blue', 'lemma': 'the sky blue', 'len': 3}]

预期输出(删除包含停用词的词条,其中包括 "the"

[{}]

您使用的是什么版本的 spacy 和 python?

我在 mac high sierra 上使用 Python 3.6.5 和 spacy 2.0.12。 您的代码似乎显示了预期的输出。

import spacy
from collections import Counter

nlp = spacy.load('en_core_web_sm')

docx = nlp('The bird is flying high in the sky blue of color')

# Just looking at nouns
nouns = []
for token in docx:
    if token.is_stop != True and token.is_punct != True and token.pos_ == 'NOUN':
        nouns.append(token)

# Count and look at the most frequent nouns #
word_freq = Counter(nouns)
common_nouns = word_freq.most_common(10)

print( word_freq)
print(common_nouns)


$python3  /tmp/nlp.py
Counter({bird: 1, sky: 1, blue: 1, color: 1})
[(bird, 1), (sky, 1), (blue, 1), (color, 1)]

此外,'is_stop'docx 的属性。您可以通过

查看
>>> dir(docx)

您可能想要升级 spacy 及其依赖项,看看是否有帮助。

此外,flying 是一个动词,因此即使在词素化之后,它也不会根据您的情况附加。

token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
          token.shape_, token.is_alpha, token.is_stop
flying fly VERB VBG ROOT xxxx True False

EDIT-1

你可以尝试这样的事情。 由于我们不能直接在词块上使用 is_stop,我们可以遍历每个词块并根据您的要求检查条件。 (例如,没有 stop_word 并且长度 > 1 等)。 如果满意,那么我们将追加到列表中。

noun_phrases = []
for chunk in docx.noun_chunks:
    print(chunk)
    if all(token.is_stop != True and token.is_punct != True and '-PRON-' not in token.lemma_ for token in chunk) == True:
        if len(chunk) > 1:
            noun_phrases.append(chunk)
print(noun_phrases)

结果:

python3 /tmp/so.py
Counter({bird: 1, sky: 1, blue: 1, color: 1})
[(bird, 1), (sky, 1), (blue, 1), (color, 1)]
The bird
the sky blue
color
[]   # contents of noun_phrases is empty here.

希望这对您有所帮助。您可以调整 if all 中的条件以满足您的要求。

您可能还想尝试 Berkeley Natural 解析器。 https://spacy.io/universe/project/self-attentive-parser 有人告诉我,它为您提供了 Penn Treebank 解析树。我还被告知它很慢:-(

另外,如果我没记错的话,一个名词块由tokens组成,tokens带有is_stop_、pos_和tag_;即,您可以相应地进行过滤。

我发现关于名词组块的两个令人沮丧的问题是它在右边界上跟在 N+Ps 之后,在两个名词组块之间断断续续 "and"!关于第一个问题,它不会将 "the University of California" 作为一个块,而是将 "the University" 和 "California" 作为两个单独的名词块。
此外,它不一致,这让我很生气。 Jim Smith 和 Jain Jones 可以作为 "Jim Smith" 加上 "Jain Jones" 作为两个名词组;这是正确的答案。或者 "Jim Smith and Jain Jones" 全部作为一个名词块!?!