如何使用 Scikit Learn CountVectorizer 在语料库中获取词频?

Posted

技术标签:

【中文标题】如何使用 Scikit Learn CountVectorizer 在语料库中获取词频?【英文标题】:How do I get word frequency in a corpus using Scikit Learn CountVectorizer? 【发布时间】:2015-02-13 19:24:42 【问题描述】:

我正在尝试使用 scikit-learn 的 CountVectorizer 计算一个简单的词频。

import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer

texts=["dog cat fish","dog cat cat","fish bird","bird"]
cv = CountVectorizer()
cv_fit=cv.fit_transform(texts)

print cv.vocabulary_
u'bird': 0, u'cat': 1, u'dog': 2, u'fish': 3

我期待它返回u'bird': 2, u'cat': 3, u'dog': 2, u'fish': 2

【问题讨论】:

CountVectorizer 创建“术语到特征索引的映射” - 如果您只想要频率,为什么不使用collections.Counter 【参考方案1】:

cv.vocabulary_ 在这种情况下是一个字典,其中键是您找到的单词(特征),值是索引,这就是为什么它们是 0, 1, 2, 3。它看起来和你的计数相似只是运气不好:)

您需要使用 cv_fit 对象来获取计数

from sklearn.feature_extraction.text import CountVectorizer

texts=["dog cat fish","dog cat cat","fish bird", 'bird']
cv = CountVectorizer()
cv_fit=cv.fit_transform(texts)

print(cv.get_feature_names())
print(cv_fit.toarray())
#['bird', 'cat', 'dog', 'fish']
#[[0 1 1 1]
# [0 2 1 0]
# [1 0 0 1]
# [1 0 0 0]]

数组中的每一行都是您的原始文档(字符串)之一,每一列是一个特征(单词),元素是该特定单词和文档的计数。你可以看到,如果你对每一列求和,你会得到正确的数字

print(cv_fit.toarray().sum(axis=0))
#[2 3 2 2]

老实说,我建议使用collections.Counter 或来自 NLTK 的东西,除非你有特定的理由使用 scikit-learn,因为它会更简单。

【讨论】:

【参考方案2】:

cv_fit.toarray().sum(axis=0) 肯定给出了正确的结果,但是对稀疏矩阵求和然后转换为数组会快得多:

np.asarray(cv_fit.sum(axis=0))

【讨论】:

【参考方案3】:

我们将使用 zip 方法从单词列表及其计数列表中生成 dict

import pandas as pd
import numpy as np    
from sklearn.feature_extraction.text import CountVectorizer

texts=["dog cat fish","dog cat cat","fish bird","bird"]    

cv = CountVectorizer()   
cv_fit=cv.fit_transform(texts)    
word_list = cv.get_feature_names();    
count_list = cv_fit.toarray().sum(axis=0)    

print word_list ['鸟', '猫', '狗', '鱼']print count_list [2 3 2 2]print dict(zip(word_list,count_list)) '鱼':2,'狗':2,'鸟':2,'猫':3

【讨论】:

cv_fit.toarray().sum(axis=0) 使 RAM 爆炸,因为它需要加密稀疏矩阵。查看@pieterbons 的答案以获得更好的方法。【参考方案4】:

结合其他人的观点和我自己的一些观点:) 这是我为你准备的东西

from collections import Counter
from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize

text='''Note that if you use RegexpTokenizer option, you lose 
natural language features special to word_tokenize 
like splitting apart contractions. You can naively 
split on the regex \w+ without any need for the NLTK.
'''

# tokenize
raw = ' '.join(word_tokenize(text.lower()))

tokenizer = RegexpTokenizer(r'[A-Za-z]2,')
words = tokenizer.tokenize(raw)

# remove stopwords
stop_words = set(stopwords.words('english'))
words = [word for word in words if word not in stop_words]

# count word frequency, sort and return just 20
counter = Counter()
counter.update(words)
most_common = counter.most_common(20)
most_common

#输出 (全部)

[('注', 1), ('使用', 1), ('regexptokenizer', 1), ('选项1), ('输', 1), ('自然', 1), ('语言', 1), ('特征', 1), ('特殊', 1), ('字', 1), ('tokenize', 1), ('喜欢', 1), ('分裂', 1), ('分开', 1), (“宫缩”,1), ('天真', 1), ('分裂', 1), ('正则表达式', 1), ('没有', 1), ('需要', 1)]

在效率方面可以做得比这更好,但如果你不是太担心的话,这个代码是最好的。

【讨论】:

旧版本的代码抛出以下导入错误:“NameError: name 'word_tokenize' is not defined”,刚刚将导入添加到第 4 行。干得好,很好的解决方案@Pradeep-Singh。 【参考方案5】:

结合@YASH-GUPTA 的答案以获得可读结果和@pieterbons 的RAM效率,但需要进行调整并添加几个括号。 工作代码:

import numpy as np    
from sklearn.feature_extraction.text import CountVectorizer

texts = ["dog cat fish", "dog cat cat", "fish bird", "bird"]    

cv = CountVectorizer()   
cv_fit = cv.fit_transform(texts)    
word_list = cv.get_feature_names()

# Added [0] here to get a 1d-array for iteration by the zip function. 
count_list = np.asarray(cv_fit.sum(axis=0))[0]

print(dict(zip(word_list, count_list)))
# Output: 'bird': 2, 'cat': 3, 'dog': 2, 'fish': 2

【讨论】:

以上是关于如何使用 Scikit Learn CountVectorizer 在语料库中获取词频?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 scikit-learn 创建我自己的数据集?

如何使用 scikit.learn 将字符串列表用作 svm 的训练数据?

如何使用 scikit-learn 进行高斯/多项式回归?

如何在 scikit-learn(用于计算机视觉)中使用我自己的数据集?

如何使用 Python (scikit-learn) 计算 FactorAnalysis 分数?

如何使用 scikit-learn 执行非正则化逻辑回归?