2013-11-23 173 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,你會經常找到比默認做更好的方法。