2013-11-23 101 views
5

我有我使用Sklearn的TfidfVectorizer对象获得一个稀疏矩阵的规范:获取numpy的稀疏矩阵行

vect = TfidfVectorizer(sublinear_tf=True, max_df=0.5, analyzer='word', vocabulary=my_vocab, stop_words='english') 
tfidf = vect.fit_transform([my_docs]) 

稀疏矩阵(取出用于一般性的数字):

<sparse matrix of type '<type 'numpy.float64'>' 
with stored elements in Compressed Sparse Row format>] 

我想获得每行的数值来告诉我文档有多高,我正在寻找的术语。我并不在乎它包含哪些词,我只想知道它包含了多少。所以我想要得到每行或每行的规范* row.T。然而,我很难与numpy合作来获得这个。

我的第一种方法是只简单地做:

tfidf[i] * numpy.transpose(tfidf[i]) 

然而,numpy的将显然不会少于一名维转置的数组,这样只会方形矢量。于是,我就这样做:

tfidf[i] * numpy.transpose(numpy.atleast_2d(tfidf[0])) 

但numpy.transpose(numpy.atleast_2d(TFIDF [0]))还是不会转行。

我继续试图获得行的标准(反正这种方法可能更好)。我最初的方法是使用numpy.linalg。

numpy.linalg.norm(tfidf[0]) 

但是,这给了我一个“尺寸不匹配”的错误。所以我试图手动计算标准。我一开始就只设置一个变量等于稀疏矩阵的numpy的阵列版本,并打印出第一行的LEN:

my_array = numpy.array(tfidf) 
print my_array 
print len(my_array[0]) 

它打印出my_array正确的,但是当我尝试访问LEN它告诉我:

IndexError: 0-d arrays can't be indexed 

我只是想获得由fit_transform返回的稀疏矩阵中的每一行的数值。获得规范将是最好的。这里的任何帮助非常感谢。

+0

它是什么类型的稀疏矩阵? – askewchan

+0

嗨,谢谢你的回应。我编辑了我的答案以显示类型。 – Sterling

+0

我可以解释最后一个错误:调用'np.array(tfidf)'将整个矩阵的1个元素和0个d数组作为一个对象。为了使它成为一个普通的数组,使用'tfidf.toarray()'或获得一个矩阵,使用'tfidf.todense()'。 – askewchan

回答

7

一些简单的假数据:

a = np.arange(9.).reshape(3,3) 
s = sparse.csr_matrix(a) 

要想从稀疏的每一行的常态,你可以使用:

np.sqrt(s.multiply(s).sum(1)) 

而重新归一化s

s.multiply(1/np.sqrt(s.multiply(s).sum(1))) 

或在重新正常化之前保持稀疏:

s.multiply(sparse.csr_matrix(1/np.sqrt(s.multiply(s).sum(1)))) 

从它那里得到普通的矩阵或阵列,使用方法:

m = s.todense() 
a = s.toarray() 

如果您有茂密的版本足够的内存,你可以得到每一行的范数:

n = np.sqrt(np.einsum('ij,ij->i',a,a)) 

n = np.apply_along_axis(np.linalg.norm, 1, a) 

校准,你可以做

an = a/n[:, None] 

,或者归一化,以代替原始阵列:

a /= n[:, None] 

[:, None]事情基本上调换n是一个垂直阵列。

5

scipy.sparse是一款出色的软件包,每次发布时它都会越来越好,但很多东西仍然只有一半,而且如果你自己实现一些算法,你可以获得很大的性能提升。例如,7倍的改善了@ askewchan的实现使用SciPy的功能:

In [18]: a = sps.rand(1000, 1000, format='csr') 

In [19]: a 
Out[19]: 
<1000x1000 sparse matrix of type '<type 'numpy.float64'>' 
    with 10000 stored elements in Compressed Sparse Row format> 

In [20]: %timeit a.multiply(a).sum(1) 
1000 loops, best of 3: 288 us per loop 

In [21]: %timeit np.add.reduceat(a.data * a.data, a.indptr[:-1]) 
10000 loops, best of 3: 36.8 us per loop 

In [24]: np.allclose(a.multiply(a).sum(1).ravel(), 
    ...:    np.add.reduceat(a.data * a.data, a.indptr[:-1])) 
Out[24]: True 

可以代替阵列同样正常化执行以下操作:

norm_rows = np.sqrt(np.add.reduceat(a.data * a.data, a.indptr[:-1])) 
nnz_per_row = np.diff(a.indptr) 
a.data /= np.repeat(norm_rows, nnz_per_row) 

如果你要经常用到稀疏矩阵,阅读the wikipedia page on compressed sparse formats,你会经常找到比默认做更好的方法。