我正在使用scikit-学习构建一个分类器,它工作(有点大)文本文件。我现在需要一个简单的词包特征,所以我尝试使用TfidfVectorizer/HashingVectorizer/CountVectorizer来获得特征向量。
但是,一次处理整个列车数据以获得特征向量会导致numpy/scipy中的内存错误(取决于我使用的向量器)。
当从原始文本中提取文本特性时:如果我将数据以块的形式匹配到向量器中,这是否与一次性拟合整个数据相同?
要用代码来说明这一点,如下所示:
vectoriser = CountVectorizer() # or TfidfVectorizer/HashingVectorizer
train_vectors = vectoriser.fit_transform(train_data)与以下各点不同:
vectoriser = CountVectorizer() # or TfidfVectorizer/HashingVectorizer
start = 0
while start < len(train_data):
vectoriser.fit(train_data[start:(start+500)])
start += 500
train_vectors = vectoriser.transform(train_data)发布于 2015-08-04 09:38:15
这取决于您使用的向量器。
CountVectorizer统计文档中单词的出现情况。它为每个文档输出一个(n_words, 1)向量,其中包含每个单词出现在文档中的次数。n_words是文档中单词的总数(也就是词汇表的大小)。
它也适合一个词汇表,这样你就可以对模型进行反思(看看哪个词是重要的,等等)。您可以使用vectorizer.get_feature_names()查看它。
当你把它放在你的前500个文档中时,词汇表将只由500个文档中的单词组成。假设其中有30k,fit_transform输出一个500x30k稀疏矩阵。
现在,您再次使用500个下一个文档,但是它们只包含29k个单词,因此您可以得到一个fit_transform矩阵.
现在,如何使矩阵对齐以确保所有文档都有一致的表示?
我现在想不出一种简单的办法来做这件事。
对于TfidfVectorizer,您还有另一个问题,即反向文档频率:要能够计算文档频率,您需要同时查看所有文档。
但是,TfidfVectorizer只是一个CountVectorizer,后面是一个TfIdfTransformer,所以如果您能够正确地获得CountVectorizer的输出,那么您就可以对数据应用TfIdfTransformer。
使用HashingVectorizer,事情就不同了:这里没有词汇表。
In [51]: hvect = HashingVectorizer()
In [52]: hvect.fit_transform(X[:1000])
<1000x1048576 sparse matrix of type '<class 'numpy.float64'>'
with 156733 stored elements in Compressed Sparse Row format> 在前1000个文档中没有1M+不同的单词,但是我们得到的矩阵有1M+列。
HashingVectorizer不将单词存储在内存中。这使得它的内存效率更高,并确保它返回的矩阵总是有相同数量的列。所以这里的CountVectorizer没有相同的问题。
这可能是您描述的批处理的最佳解决方案。有几个缺点,即你不能得到以色列国防军的权重,而且你不知道单词和你的特征之间的映射。
HashingVectorizer文档引用了一个执行文本数据的核外分类的示例。它可能有点凌乱,但它能做你想做的事。
希望这能有所帮助。
编辑:如果您有太多的数据,HashingVectorizer就是最好的选择。如果您仍然想使用CountVectorizer,一个可能的解决方法是自己安装词汇表,并将它传递给您的向量程序,这样您只需要调用tranform。
下面是一个您可以适应的例子:
import re
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
news = fetch_20newsgroups()
X, y = news.data, news.target现在,不起作用的方法:
# Fitting directly:
vect = CountVectorizer()
vect.fit_transform(X[:1000])
<1000x27953 sparse matrix of type '<class 'numpy.int64'>'
with 156751 stored elements in Compressed Sparse Row format>注意我们得到的矩阵的大小。
将词汇表“手动”贴合:
def tokenizer(doc):
# Using default pattern from CountVectorizer
token_pattern = re.compile('(?u)\\b\\w\\w+\\b')
return [t for t in token_pattern.findall(doc)]
stop_words = set() # Whatever you want to have as stop words.
vocabulary = set([word for doc in X for word in tokenizer(doc) if word not in stop_words])
vectorizer = CountVectorizer(vocabulary=vocabulary)
X_counts = vectorizer.transform(X[:1000])
# Now X_counts is:
# <1000x155448 sparse matrix of type '<class 'numpy.int64'>'
# with 149624 stored elements in Compressed Sparse Row format>
#
X_tfidf = tfidf.transform(X_counts)在您的示例中,在应用转换之前,您需要首先构建整个矩阵X_counts (用于所有文档)。
发布于 2015-08-03 10:26:08
我不是文本特征提取专家,但基于文档和其他分类器库经验:
如果我对大量的训练数据做了几次拟合,这是否与一次拟合整个数据相同呢?
您不能直接合并提取的特征,因为您将得到不同的重要性,即从中的不同块获取相同的令牌/单词的weights与块中的其他单词的不同比例,后者用不同的键表示。
你可以使用任何特征提取方法,我认为结果的有用性取决于任务。
但是,如果可以使用不同块的,不同的特性可以对相同的数据进行分类。一旦您通过获得了几个不同的输出--相同的特征提取方法(或者您也可以使用不同的提取方法)--您就可以将它们用作bagging、boosting等“合并”机制的输入。实际上,在大多数情况下,在整个过程之后,您将得到一个更好的最终输出,而不是一个“全功能”的完整文件,甚至是一个简单的分类器。
https://stackoverflow.com/questions/31784011
复制相似问题