我可以使用scikit-learn中的CountVectorizer来计算未被用于提取标记的文档的频率吗?

43

我一直在使用scikit-learn中的CountVectorizer类。

我明白,如果按照下面的方式使用它,最终的输出将包括一个数组,其中包含特征或标记的计数。

这些标记是从一组关键词中提取的,即:

tags = [
  "python, tools",
  "linux, tools, ubuntu",
  "distributed systems, linux, networking, tools",
]

下一步是:

from sklearn.feature_extraction.text import CountVectorizer
vec = CountVectorizer(tokenizer=tokenize)
data = vec.fit_transform(tags).toarray()
print data

我们从哪里得到

[[0 0 0 1 1 0]
 [0 1 0 0 1 1]
 [1 1 1 0 1 0]]

这很好,但我的情况略有不同。

我想以与上述相同的方式提取特征,但我不希望data中的行是从中提取特征的相同文档。

换句话说,我该如何获得另一组文档的计数,比如:

list_of_new_documents = [
  ["python, chicken"],
  ["linux, cow, ubuntu"],
  ["machine learning, bird, fish, pig"]
]

并获得:

[[0 0 0 1 0 0]
 [0 1 0 0 0 1]
 [0 0 0 0 0 0]]

我已阅读了 CountVectorizer 类的文档,并遇到了 vocabulary 参数,它是一个将术语映射为特征索引的映射。然而,我似乎无法利用此参数。

非常感谢任何建议。
PS:以上示例中使用的内容全部归功于Matthias Friedrich的博客

3个回答

55

你说得对,vocabulary 就是你想要的。它的使用方法如下:

>>> cv = sklearn.feature_extraction.text.CountVectorizer(vocabulary=['hot', 'cold', 'old'])
>>> cv.fit_transform(['pease porridge hot', 'pease porridge cold', 'pease porridge in the pot', 'nine days old']).toarray()
array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 0],
       [0, 0, 1]], dtype=int64)

你需要传递一个字典,以你所需的特征作为键。

如果你在一组文档上使用了 CountVectorizer ,然后想要使用这些文档的特征集合用于新的一组文档,则可以使用原始 CountVectorizer 的 vocabulary_ 属性,并将其传递给新的 CountVectorizer。因此,在你的示例中,你可以这样做:

newVec = CountVectorizer(vocabulary=vec.vocabulary_)

使用第一个分词器的词汇表创建一个新的分词器。


谢谢,这看起来很棒!对于第一种解决方案:词汇表始终应该是字典,而不是列表吗?如果我理解错了,请纠正我,但是计数(0、1、2)似乎无关紧要。你提到的第二种方法可能更清晰些。 - tumultous_rooster
1
@MattO'Brien:你说得对,它可以是一个列表,我误读了文档。我编辑了我的回答。然而,在第二种方法中,它是一个字典,因为拟合向量化器的vocabulary_方法就是这样的。 - BrenBarn
1
BrenBarn,你的回答节省了我很多时间。真的非常感谢你在这个网站上的存在。 - tumultous_rooster
10
也许我理解有误,但是与其使用原始的词汇表初始化一个新的CountVectorizer,不如直接在原始的向量化器上调用.transform()方法来处理新的文档集合。 - Fred
我有一个包含大量字符串(n > 10000)的列表,其中每个字符串包含100K到110K个单词。如何使此countVectorizer适用于这样的数据,并且是否可以使用所有核心来加速处理。 - Asis
对于任何遇到vocabulary参数问题的人,CountVectorizer()默认设置为lowercase=True,因此如果您的自定义词汇表是大写的,则必须将其设置为lowercase=False - NatalieL

9

您应该在原始词汇源上调用fit_transform或只是fit,以便向量化器学习词汇表。

然后,您可以通过transform()方法在任何新数据源上使用此fit向量化器。

您可以通过vectorizer.vocabulary_获得由拟合生成的词汇表(即单词到标记ID的映射),假设您将CountVectorizer命名为vectorizer


3
>>> tags = [
  "python, tools",
  "linux, tools, ubuntu",
  "distributed systems, linux, networking, tools",
]

>>> list_of_new_documents = [
  ["python, chicken"],
  ["linux, cow, ubuntu"],
  ["machine learning, bird, fish, pig"]

]

>>> from sklearn.feature_extraction.text import CountVectorizer
>>> vect = CountVectorizer()
>>> tags = vect.fit_transform(tags)

# vocabulary learned by CountVectorizer (vect)
>>> print(vect.vocabulary_)
{'python': 3, 'tools': 5, 'linux': 1, 'ubuntu': 6, 'distributed': 0, 'systems': 4, 'networking': 2}

# counts for tags
>>> tags.toarray()
array([[0, 0, 0, 1, 0, 1, 0],
       [0, 1, 0, 0, 0, 1, 1],
       [1, 1, 1, 0, 1, 1, 0]], dtype=int64)

# to use `transform`, `list_of_new_documents` should be a list of strings 
# `itertools.chain` flattens shallow lists more efficiently than list comprehensions

>>> from itertools import chain
>>> new_docs = list(chain.from_iterable(list_of_new_documents)
>>> new_docs = vect.transform(new_docs)

# finally, counts for new_docs!
>>> new_docs.toarray()
array([[0, 0, 0, 1, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 1],
       [0, 0, 0, 0, 0, 0, 0]])

为了验证CountVectorizer是否使用了从tags中学习到的词汇表来处理new_docs,请再次打印vect.vocabulary_或比较new_docs.toarray()tags.toarray()的输出结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接