首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >scikit-学习:将数据整合到块中,而不是一次将其全部拟合起来。

scikit-学习:将数据整合到块中,而不是一次将其全部拟合起来。
EN

Stack Overflow用户
提问于 2015-08-03 09:36:33
回答 2查看 4.9K关注 0票数 9

我正在使用scikit-学习构建一个分类器,它工作(有点大)文本文件。我现在需要一个简单的词包特征,所以我尝试使用TfidfVectorizer/HashingVectorizer/CountVectorizer来获得特征向量。

但是,一次处理整个列车数据以获得特征向量会导致numpy/scipy中的内存错误(取决于我使用的向量器)。

当从原始文本中提取文本特性时:如果我将数据以块的形式匹配到向量器中,这是否与一次性拟合整个数据相同?

要用代码来说明这一点,如下所示:

代码语言:javascript
复制
vectoriser = CountVectorizer() # or TfidfVectorizer/HashingVectorizer
train_vectors = vectoriser.fit_transform(train_data)

与以下各点不同:

代码语言:javascript
复制
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)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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,事情就不同了:这里没有词汇表。

代码语言:javascript
复制
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

下面是一个您可以适应的例子:

代码语言:javascript
复制
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

现在,不起作用的方法:

代码语言:javascript
复制
# 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>

注意我们得到的矩阵的大小。

将词汇表“手动”贴合:

代码语言:javascript
复制
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 (用于所有文档)。

票数 6
EN

Stack Overflow用户

发布于 2015-08-03 10:26:08

我不是文本特征提取专家,但基于文档和其他分类器库经验:

如果我对大量的训练数据做了几次拟合,这是否与一次拟合整个数据相同呢?

您不能直接合并提取的特征,因为您将得到不同的重要性,即从中的不同块获取相同的令牌/单词的weights与块中的其他单词的不同比例,后者用不同的键表示。

你可以使用任何特征提取方法,我认为结果的有用性取决于任务。

但是,如果可以使用不同块的,不同的特性可以对相同的数据进行分类。一旦您通过获得了几个不同的输出--相同的特征提取方法(或者您也可以使用不同的提取方法)--您就可以将它们用作baggingboosting等“合并”机制的输入。实际上,在大多数情况下,在整个过程之后,您将得到一个更好的最终输出,而不是一个“全功能”的完整文件,甚至是一个简单的分类器。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31784011

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档