将特征稀疏矩阵与sklearn混合的正确方法是什么?

时间:2015-08-29 00:38:03

标签: python numpy pandas scikit-learn

前几天我正在处理需要提取几种类型的特征矩阵的机器学习任务。我将此特征矩阵保存为磁盘中的numpy数组,以便稍后在某个估算器中使用它们(这是一个分类任务)。毕竟,当我想使用所有功能时,我只是连接矩阵以便有一个很大的特征矩阵。当我获得这个大特征矩阵时,我将它呈现给估算器。

我不知道这是否是使用具有大量模式(计数)的特征矩阵的正确方法。 我应该使用哪些其他方法来正确混合多种类型的功能?。但是,查看文档,我发现FeatureUnion似乎正在执行此任务。

例如,假设我想创建一个包含3个矢量化方法的大特征矩阵TfidfVectorizerCountVectorizerHashingVectorizer这就是我在documentation example之后尝试的方法:

#Read the .csv file
import pandas as pd
df = pd.read_csv('file.csv',
                     header=0, sep=',', names=['id', 'text', 'labels'])

#vectorizer 1
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf_vect = TfidfVectorizer(use_idf=True, smooth_idf=True,
                             sublinear_tf=False, ngram_range=(2,2))
#vectorizer 2
from sklearn.feature_extraction.text import CountVectorizer
bow = CountVectorizer(ngram_range=(2,2))

#vectorizer 3
from sklearn.feature_extraction.text import HashingVectorizer
hash_vect = HashingVectorizer(ngram_range=(2,2))


#Combine the above vectorizers in one single feature matrix:

from sklearn.pipeline import  FeatureUnion
combined_features = FeatureUnion([("tfidf_vect", tfidf_vect),
                                  ("bow", bow),
                                  ("hash",hash_vect)])

X_combined_features = combined_features.fit_transform(df['text'].values)
y = df['labels'].values

#Check the matrix
print X_combined_features.toarray()

然后:

[[ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]
 ..., 
 [ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]]

拆分数据:

from sklearn import cross_validation
X_train, X_test, y_train, y_test = cross_validation.train_test_split(X_combined_features,y, test_size=0.33)

所以我有几个问题: 这是混合多个特征提取器以产生大特征矩阵的正确方法吗?假设我创建自己的“矢量化器”并返回稀疏矩阵,我怎样才能正确使用FeatureUnion界面将它们与上述3个功能混合在一起?

更新

假设我有一个这样的矩阵:

矩阵A((152, 33)

[[ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]
 ..., 
 [ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  0.]]

然后使用返回numpy array的矢量化器,我得到了这个特征矩阵:

矩阵B((152, 10)

[[4210  228   25 ...,    0    0    0]
 [4490  180   96 ...,   10    4    6]
 [4795  139    8 ...,    0    0    1]
 ..., 
 [1475   58    3 ...,    0    0    0]
 [4668  256   25 ...,    0    0    0]
 [1955  111   10 ...,    0    0    0]]

Matrix C((152, 46)

[[ 0  0  0 ...,  0  0  0]
 [ 0  0  0 ...,  0  0 17]
 [ 0  0  0 ...,  0  0  0]
 ..., 
 [ 0  0  0 ...,  0  0  0]
 [ 0  0  0 ...,  0  0  0]
 [ 0  0  0 ...,  0  0  0]]

如何正确地将A,B和C与numpy.hstackscipy.sparse.hstackFeatureUnion合并? 。您是否认为这是任何机器学习任务的正确管道方法?

1 个答案:

答案 0 :(得分:4)

  

这是混合多个特征提取器以产生大特征矩阵的正确方法吗?

就结果的正确性而言,您的方法是正确的,因为FeatureUnion在输入数据上运行每个单独的变换器并水平连接结果矩阵。但是,这不是唯一的方法,哪种方式在效率方面更好将取决于您的使用案例(稍后将详细介绍)。

  

假设我创建了自己的“矢量化器”并返回稀疏矩阵,我如何正确使用FeatureUnion接口将它们与上述3个特征混合使用?

使用FeatureUnion,您只需将新的变压器附加到变换器列表:

custom_vect = YourCustomVectorizer()
combined_features = FeatureUnion([("tfidf_vect", tfidf_vect),
                                  ("bow", bow),
                                  ("hash", hash_vect),
                                  ("custom", custom_vect])

但是,如果您的输入数据和大多数变压器是固定的(例如,当您尝试包含新的变压器时),上述方法将导致许多重新计算。在这种情况下,另一种方法是预先计算存储变换器(矩阵或稀疏矩阵)的中间结果,并在需要时使用numpy.hstackscipy.sparse.hstack手动连接它们。

如果您的输入数据始终在变化,但变换器列表已修复,FeatureUnion可提供更多便利。它的另一个优点是它可以选择n_jobs,它可以帮助您并行化拟合过程。

旁注:将散列矢量化器与其他矢量化器混合似乎有点奇怪,因为当您无法使用精确版本时,通常会使用散列矢量化器。