如何取消 Python 中的词干?

How to un-stem a word in Python?

我想知道我是否可以将它们解压缩为正常形式?

问题是我有数千个不同形式的单词,例如吃、吃、吃、吃等等,我需要计算每个词的出现频率。所有这些 - 吃、吃、吃、吃等都将计入吃,因此,我使用了词干提取。

但是问题的下一部分要求我在数据中找到相似的单词,我正在使用 nltk 的同义词集来计算单词之间的 Wu-Palmer 相似度。问题是 nltk 的同义词集不会对词干词起作用,或者至少在这段代码中它们不会。 check if two words are related to each other

我应该怎么做?有没有办法取消词干?

不,没有。使用词干提取,您会丢失信息,不仅是关于单词形式的信息(如 eat 与 eats 或 eaten),而且还有关于单词本身的信息(如 tradition 与 traditional)。除非您打算使用预测方法来尝试根据单词的上下文预测此信息,否则无法将其取回。

我怀疑你所说的 stem 的真正意思是 "tense"。正如您希望每个单词的不同时态都计入动词的 "base form"。

查看 pattern

pip install pattern

然后使用 en.lemma 函数 return 动词的基本形式。

import pattern.en as en
base_form = en.lemma('ate') # base_form == "eat"

从理论上讲,取消词干的唯一方法是,如果在词干提取之前,您保留了一个术语词典或任何类型的映射,并将此映射继续到您的其余计算中。此映射应该以某种方式捕获未提取词干的令牌的位置,并且当需要提取令牌时,如果您知道已提取词干的令牌的原始位置,您将能够使用映射追溯并恢复原始未提取词干的表示形式。

对于 Bag of Words 表示,这似乎是计算密集型的,并且在某种程度上违背了 BoW 方法的统计性质的目的。

但从理论上讲,我再次相信它可以工作。我还没有在任何实现中看到这一点。

我认为一个不错的方法就像 中所说的那样。

一个可能的实现可能是这样的:

import re
import string
import nltk
import pandas as pd
stemmer = nltk.stem.porter.PorterStemmer()

要使用的词干分析器。这里要使用的文本:

complete_text = ''' cats catlike catty cat 
stemmer stemming stemmed stem 
fishing fished fisher fish 
argue argued argues arguing argus argu 
argument arguments argument '''

用不同的词创建一个列表:

my_list = []
#for i in complete_text.decode().split():
try: 
    aux = complete_text.decode().split()
except:
    aux = complete_text.split()
for i in aux:
    if i not in my_list:
        my_list.append(i.lower())
my_list

输出:

['cats',
 'catlike',
 'catty',
 'cat',
 'stemmer',
 'stemming',
 'stemmed',
 'stem',
 'fishing',
 'fished',
 'fisher',
 'fish',
 'argue',
 'argued',
 'argues',
 'arguing',
 'argus',
 'argu',
 'argument',
 'arguments']

现在创建字典:

aux = pd.DataFrame(my_list, columns =['word'] )
aux['word_stemmed'] = aux['word'].apply(lambda x : stemmer.stem(x))
aux = aux.groupby('word_stemmed').transform(lambda x: ', '.join(x))
aux['word_stemmed'] = aux['word'].apply(lambda x : stemmer.stem(x.split(',')[0]))
aux.index = aux['word_stemmed']
del aux['word_stemmed']
my_dict = aux.to_dict('dict')['word']
my_dict

哪个输出是:

{'argu': 'argue, argued, argues, arguing, argus, argu',
 'argument': 'argument, arguments',
 'cat': 'cats, cat',
 'catlik': 'catlike',
 'catti': 'catty',
 'fish': 'fishing, fished, fish',
 'fisher': 'fisher',
 'stem': 'stemming, stemmed, stem',
 'stemmer': 'stemmer'}

配套笔记本here.

tl;dr:您可以使用任何您想要的词干提取器(例如:Snowball),并在对每个词干词进行词干分析之前通过计算出现次数来跟踪最流行的词。

您可能会喜欢这个使用词干提取并包含执行反向词干提取算法的开源项目:

this page of the project 上有关于如何进行反向词干提取的说明。总而言之,它的工作原理如下。

首先,您将对一些文档进行词干处理,例如,这里是删除了停用词的短(法语)字符串: ['sup chat march trottoir', 'sup chat aiment ronron', 'chat ronron', 'sup chien aboi', 'deux sup chien', 'combien chien train aboi']

那么诀窍就是保留最流行的原始单词的数量以及每个词干单词的数量: {'aboi': {'aboie': 1, 'aboyer': 1}, 'aiment': {'aiment': 1}, 'chat': {'chat': 1, 'chats': 2}, 'chien': {'chien': 1, 'chiens': 2}, 'combien': {'Combien': 1}, 'deux': {'Deux': 1}, 'march': {'marche': 1}, 'ronron': {'ronronner': 1, 'ronrons': 1}, 'sup': {'super': 4}, 'train': {'train': 1}, 'trottoir': {'trottoir': 1}}

最后,您现在可以猜到如何自己实现了。只需在给定一个词干词的情况下,获取计数最多的原始词。您可以参考以下实现,它作为 Multilingual-Latent-Dirichlet-Allocation-LDA 项目的一部分在 MIT 许可证下可用:

可以通过放弃非顶级反向词(例如通过使用堆)来进行改进,这最终只会产生一个字典而不是一个字典的字典。