如何识别句子的主语?

How to identify the subject of a sentence?

Python+NLTK可以用来识别句子的主语吗?据我所知,到目前为止,一个句子可以分解成一个头部及其附属物。例如"I shot an elephant"。在这句话中,I and elephant are dependent to shot。但是我怎么辨别这句话的主语是我。

正如 NLTK book(练习 29)所说,"One common way of defining the subject of a sentence S in English is as the noun phrase that is the child of S and the sibling of VP."

tree example:的确,"I"是VP的兄弟S的child的名词短语,而"elephant"不是。

英语有两种语态:主动语态和被动语态。让我们以最常用的语音为例:主动语音。

它遵循 subject-verb-object 模型。要标记主题,请编写带有 POS 标签的规则集。标记句子 I[NOUN] shot[VERB] an elephant[NOUN]。如果你看到第一个名词是主语,然后是动词,然后是宾语。

如果要复杂一点,就一句话——I shot an elephant with a gun。这里的介词或从属连词如 with, at, in 可以被赋予角色。这里的句子将被标记为I[NOUN] shot[VERB] an elephant[NOUN] with[IN] a gun[NOUN]。你可以很容易地说出这个词 with gets instrumentary role。您可以构建一个基于规则的系统来获取句子中每个单词的作用。

同时查看被动语态的模式并为其编写规则。

您可以使用 Spacy

代码

import spacy
nlp = spacy.load('en')
sent = "I shot an elephant"
doc=nlp(sent)

sub_toks = [tok for tok in doc if (tok.dep_ == "nsubj") ]

print(sub_toks) 

您可以通过类似 doc = nlp(text.decode('utf8')) 的方式来解决这个问题,但这可能会在未来给您带来更多错误。

致谢:https://github.com/explosion/spaCy/issues/380

rake_nltk (pip install rake_nltk) 是一个 python 库,它包装了 nltk 并且显然使用了 RAKE 算法。

from rake_nltk import Rake

rake = Rake()

kw = rake.extract_keywords_from_text("Can Python + NLTK be used to identify the subject of a sentence?")

ranked_phrases = rake.get_ranked_phrases()

print(ranked_phrases)

# outputs the keywords ordered by rank
>>> ['used', 'subject', 'sentence', 'python', 'nltk', 'identify']

默认使用 nltk 中的停用词列表。您可以通过在构造函数中传递它们来提供自定义停用词列表和标点字符:

rake = Rake(stopwords='mystopwords.txt', punctuations=''',;:!@#$%^*/\''')

默认情况下 string.punctuation 用于标点符号。

构造函数还接受一个 language 关键字,它可以是 nltk 支持的任何语言。

Stanford Corenlp 工具也可用于提取句子的 Subject-Relation-Object 信息。

附上相同的屏幕截图:

使用 spacy 的代码: 这里的 doc 是句子,dep='nsubj' 是主语,'dobj' 是宾语

import spacy 
nlp = spacy.load('en_core_web_lg')


def get_subject_object_phrase(doc, dep):
    doc = nlp(doc)
    for token in doc:
        if dep in token.dep_:
            subtree = list(token.subtree)
            start = subtree[0].i
            end = subtree[-1].i + 1
    return str(doc[start:end])