如何修改 Wordnet Lemmatizer 以对特定单词进行 lemmitize?

how to modify Wordnet Lemmatizer to lemmitize specific words?

我正在将 wordNet lemmatizer 应用到我的语料库中,我需要为 lemmatizer 定义 pos 标注器:

stemmer = PorterStemmer()
def lemmitize(document):
    return stemmer.stem(WordNetLemmatizer().lemmatize(document, pos='v'))

def preprocess(document):
output = []
    for token in gensim.utils.simple_preprocess(document):
        if token not in gensim.parsing.preprocessing.STOPWORDS and len(token) > 3:
            print("lemmitize: ", lemmitize(token))
            output.append(lemmitize(token))
    return output

现在如您所见,我正在为动词定义 pos(并且我知道 wordNet 默认 pos 是一个名词),但是当我对文档进行词形还原时:

the left door closed at the night  

我正在退出:

output:  ['leav', 'door', 'close', 'night']

这不是我所期待的。在我上面的句子中,left 指向哪扇门(例如右门或左门)。如果我选择 pos ='n' 这个问题可能会解决,但它将作为 wornNet 默认值,并且不会对 taken 这样的词产生任何影响。

我在 here 中发现了类似的问题,我在 nltk_data/corpora/wordnet/verb.exc 中修改了例外列表,并将 left leave 更改为 left left 但我仍然得到相同的结果结果为 leav.
现在我想知道这个问题是否有任何解决方案,或者在最好的情况下,有什么方法可以添加一些单词的自定义词典(仅限于我的文档),wordNet 不会像这样对它们进行词形还原:

my_dict_list = [left, ...]

您可以为某些单词添加自定义词典,例如 pos_dict = {'breakfasted':'v', 'left':'a', 'taken':'v'}

通过将此自定义 pos_dicttoken 一起传递到 lemmitize 函数中,您可以为每个标记使用您指定的 POS 标记的词形还原器。

lemmatize(token, pos_dict.get(token, 'n')) 将传递 'n' 作为其第二个参数作为默认值,除非令牌在 pos_dict 键中。您可以将此默认值更改为您想要的任何值。

def lemmitize(document, pos_dict):
    return stemmer.stem(WordNetLemmatizer().lemmatize(document, pos_dict.get(document, 'n')))

def preprocess(document, pos_dict):
    output = []
    for token in gensim.utils.simple_preprocess(document):
        if token not in gensim.parsing.preprocessing.STOPWORDS and len(token) > 3:
            print("lemmitize: ", lemmitize(token, pos_dict))
            output.append(lemmitize(token, pos_dict))
    return output

你在词形还原和词干化之间犯了一个常见的错误。

词干提取

词干提取意味着将单词缩减为其前缀。与语法无关,与你自己的数据或使用的算法有关。

最常用的词干提取器,例如Porter Stemmer,去掉了"morphological and inflexional endings from words" (Porter Stemmer Website)

因此,诸如 cook、cooking、cooked 和 cookie 等词的 morphological/inflexional 词尾被移除,词尾全部变为 "Cook"。但是,请注意,您将一个名词、一个现在进行时的动词、一个过去时的动词和另一个名词捆绑在一起(例如,请注意 cookie,尽管它是一种熟食,但实际上并不用 "cook" 或 "to cook" 一词分享 "hierarchy"。

当你这样做时:

stemmer.stem(WordNetLemmatizer().lemmatize(document))

您正在使用 wordnet 进行词干提取 - 首先对词进行词根化,然后进行词干提取,删除 "morphological/inflexional" 词。事实上,如果你进行词干提取,你甚至不需要词形还原(它只会改变不规则动词的内容)。

词形还原

词形还原,另一方面,使用词汇信息将单词缩减为 "default" 非弯曲形式。为使它起作用,提供 te POS 非常重要(因为如您所见,leaves 是一个既表示动词又表示名词的词素)。

但是如何找到词性呢?

今天有一些技术,但最常用的一种是基于查找 table 和周围的词 - 这些被输入预训练的机器学习算法,returns 最可能的标签。阅读更多内容:https://medium.com/greyatom/learning-pos-tagging-chunking-in-nlp-85f7f811a8cb

使用名为 NLTK 的流行 Python NLP 包,您可以: (你必须先下载相关的包)

import nltk

sentence = "I want to tag these!"
token = nltk.word_tokenize(sentence)
nltk.pos_tag(token)

结果:

[('I', 'PRP'), ('want', 'VBP'), ('to', 'TO'), ('tag', 'VB'), ('these', 'DT'), ('!', '.')]

另一个流行的工具是 Spacy,如下所示: (您必须先下载带有机器学习训练模型的语言模型)

import spacy

import spacy
nlp = spacy.load('en')
doc = nlp('I want to tag these!')
print([(token.text, token.pos_) for token in doc])

结果:

[('I', 'PRON'), ('want', 'VERB'), ('to', 'PART'), ('tag', 'VERB'), ('these', 'DET'), ('!', 'PUNCT')]

您可以在此处阅读有关 Spacy 词性标记的更多信息:https://spacy.io/usage/linguistic-features/

然后我建议您坚持使用词形还原,因为这将为您提供更细粒度的选项。