Sklearn:将 lemmatizer 添加到 CountVectorizer

Posted

技术标签:

【中文标题】Sklearn:将 lemmatizer 添加到 CountVectorizer【英文标题】:Sklearn: adding lemmatizer to CountVectorizer 【发布时间】:2018-05-05 13:14:23 【问题描述】:

如Sklearn page 中所述,我在计数向量器中添加了词形还原。

from nltk import word_tokenize          
from nltk.stem import WordNetLemmatizer 
class LemmaTokenizer(object):
    def __init__(self):
        self.wnl = WordNetLemmatizer()
    def __call__(self, articles):
        return [self.wnl.lemmatize(t) for t in word_tokenize(articles)]

tf_vectorizer = CountVectorizer(tokenizer=LemmaTokenizer,
                       strip_accents = 'unicode',
                       stop_words = 'english',
                       lowercase = True,
                       token_pattern = r'\b[a-zA-Z]3,\b', # keeps words of 3 or more characters
                       max_df = 0.5,
                       min_df = 10)

但是,当使用fit_transform 创建 dtm 时,我收到以下错误(我无法理解)。在将词形还原添加到我的矢量化器之前,dtm 代码始终有效。我深入手册,用代码尝试了一些东西,但找不到任何解决方案。

dtm_tf = tf_vectorizer.fit_transform(articles)

更新:

在遵循@MaxU 下面的建议后,代码运行没有错误,但是我的输出中没有省略数字和标点符号。我运行单独的测试以查看LemmaTokenizer() 之后的哪些其他功能可以工作和不工作。结果如下:

strip_accents = 'unicode', # works
stop_words = 'english', # works
lowercase = True, # works
token_pattern = r'\b[a-zA-Z]3,\b', # does not work
max_df = 0.5, # works
min_df = 10 # works

显然,只是 token_pattern 变得不活跃。这是没有token_pattern 的更新和工作代码(我只需要先安装“punkt”和“wordnet”包):

from nltk import word_tokenize          
from nltk.stem import WordNetLemmatizer 
class LemmaTokenizer(object):
    def __init__(self):
        self.wnl = WordNetLemmatizer()
    def __call__(self, articles):
        return [self.wnl.lemmatize(t) for t in word_tokenize(articles)]

tf_vectorizer = CountVectorizer(tokenizer=LemmaTokenizer(),
                                strip_accents = 'unicode', # works 
                                stop_words = 'english', # works
                                lowercase = True, # works
                                max_df = 0.5, # works
                                min_df = 10) # works

对于那些想要删除少于 3 个字符的数字、标点符号和单词(但不知道如何)的人,这是使用 Pandas 数据框工作时为我完成的一种方法

# when working from Pandas dataframe

df['TEXT'] = df['TEXT'].str.replace('\d+', '') # for digits
df['TEXT'] = df['TEXT'].str.replace(r'(\b\w1,2\b)', '') # for words
df['TEXT'] = df['TEXT'].str.replace('[^\w\s]', '') # for punctuation 

【问题讨论】:

我不知道这个问题的答案。但是,来自 sklearn 的例子似乎很草率。 lemmatizer 需要一个词性标签才能正常工作。这通常是在标记化之前使用 pos_tag nltk 函数推断出来的。 【参考方案1】:

应该是:

tf_vectorizer = CountVectorizer(tokenizer=LemmaTokenizer(),
# NOTE:                        ---------------------->  ^^

代替:

tf_vectorizer = CountVectorizer(tokenizer=LemmaTokenizer,

【讨论】:

感谢您的建议,代码运行确实没有错误。但是,LemmaTokenizer() 之后的功能不再起作用。最重要的是,token_pattern = r'\b[a-zA-Z]3,\b' 变得不活跃(所以我的主题充满了数字和标点符号)。是否可以一步集成所有内容?还是我要把两者分开? (并事先删除数字和标点符号)。 @Rens,请打开一个新问题并提供一个小的(3-5 行)可重现的样本数据集和您的代码【参考方案2】:

感谢您的代码,它对我有帮助。 这是处理非活动token_pattern 的另一种方法:

import re
class LemmaTokenizer:
    def __init__(self):
        self.wnl = WordNetLemmatizer()
    def __call__(self, doc):
        regex_num_ponctuation = '(\d+)|([^\w\s])'
        regex_little_words = r'(\b\w1,2\b)'
        return [self.wnl.lemmatize(t) for t in word_tokenize(doc) 
                if not re.search(regex_num_ponctuation, t) and not re.search(regex_little_words, t)]

将 Regex 加入到 LemmaTokenizer 类中。

【讨论】:

这是一个不错的附加选项,当然也是首选方式!那谢谢啦。顺便说一句:对于我的主题模型,我终于停止使用词形还原器,因为它产生的结果不太好。另见:mimno.infosci.cornell.edu/papers/schofield_tacl_2016.pdf

以上是关于Sklearn:将 lemmatizer 添加到 CountVectorizer的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Stemmer或Lemmatizer来阻止特定的单词

将 scikit-learn (sklearn) 预测添加到 pandas 数据帧

自然语言19.1_Lemmatizing with NLTK

NLP入门词形还原(Lemmatization)

向 Sklearn 分类器添加功能

将前 k 个结果添加到 sklearn 管道?