稀疏矩阵的逐元素划分 python

Element-wise division on sparse matrix python

我有一个大小为 (n x m):

的稀疏矩阵
sparse_dtm = dok_matrix((num_documents, vocabulary_size), dtype=np.float32)
        for doc_index, document in enumerate(data):
            document_counter = Counter(document)
            for word in set(document):
                sparse_dtm[doc_index, word_to_index[word]] = document_counter[word]

其中:

此外,我有一个长度为 n:

的列表

sums = sparse_dtm.sum(1).tolist()

现在,我想进行逐元素除法,其中 sparse_dtmrow_i 的每个单元格除以 sums[i]

一种天真的方法,使用传统 Python 元素划分:

sparse_dtm / sums

导致以下错误:

TypeError: unsupported operand type(s) for /: 'csr_matrix' and 'list'

我如何执行这种按元素划分?

如果我没理解错的话,你需要将每一行除以行的总和,对吗?

在这种情况下,您需要重塑总和

sparse_dtm / sparse_dtm.sum(1).reshape(-1, 1)

你也可以使用 pandas DataFrame,例如

row_num = 10
col_num = 5
sparse_dtm = np.ndarray((row_num, col_num), dtype=np.float32)
for row in range(row_num):
    for col in range(col_num):
        value = (row+1) * (col+2)
        sparse_dtm[row, col] = value
df = pd.DataFrame(sparse_dtm)
print(df)

给予

      0     1     2     3     4
0   2.0   3.0   4.0   5.0   6.0
1   4.0   6.0   8.0  10.0  12.0
2   6.0   9.0  12.0  15.0  18.0
3   8.0  12.0  16.0  20.0  24.0
4  10.0  15.0  20.0  25.0  30.0
5  12.0  18.0  24.0  30.0  36.0
6  14.0  21.0  28.0  35.0  42.0
7  16.0  24.0  32.0  40.0  48.0
8  18.0  27.0  36.0  45.0  54.0
9  20.0  30.0  40.0  50.0  60.0

然后将每一行除以行

的总和
df / df.sum(axis=1).values.reshape(-1, 1)

这给

     0     1    2     3    4
0  0.1  0.15  0.2  0.25  0.3
1  0.1  0.15  0.2  0.25  0.3
2  0.1  0.15  0.2  0.25  0.3
3  0.1  0.15  0.2  0.25  0.3
4  0.1  0.15  0.2  0.25  0.3
5  0.1  0.15  0.2  0.25  0.3
6  0.1  0.15  0.2  0.25  0.3
7  0.1  0.15  0.2  0.25  0.3
8  0.1  0.15  0.2  0.25  0.3
9  0.1  0.15  0.2  0.25  0.3
In [189]: M = sparse.dok_matrix([[0,1,3,0],[0,0,2,0],[1,0,0,0]])
In [190]: M
Out[190]: 
<3x4 sparse matrix of type '<class 'numpy.int64'>'
    with 4 stored elements in Dictionary Of Keys format>
In [191]: M.A
Out[191]: 
array([[0, 1, 3, 0],
       [0, 0, 2, 0],
       [1, 0, 0, 0]])

sum(1)产生一个(3,1)np.matrix,可以直接在除法中使用:

In [192]: M.sum(1)
Out[192]: 
matrix([[4],
        [2],
        [1]])
In [193]: M/M.sum(1)
Out[193]: 
matrix([[0.  , 0.25, 0.75, 0.  ],
        [0.  , 0.  , 1.  , 0.  ],
        [1.  , 0.  , 0.  , 0.  ]])

请注意,结果是密集的 np.matrix,而不是稀疏的。

如果行总和为 0,这可能会产生问题,但对于您的构造,这可能是不可能的。

我们可以通过先将和转换为稀疏来保留稀疏结果。我正在使用逆运算,因为没有稀疏的元素划分(关于所有这些 0):

In [205]: D=sparse.csr_matrix(1/M.sum(1))
In [206]: D
Out[206]: 
<3x1 sparse matrix of type '<class 'numpy.float64'>'
    with 3 stored elements in Compressed Sparse Row format>
In [207]: D.A
Out[207]: 
array([[0.25],
       [0.5 ],
       [1.  ]])
In [208]: D.multiply(M)
Out[208]: 
<3x4 sparse matrix of type '<class 'numpy.float64'>'
    with 4 stored elements in Compressed Sparse Row format>
In [209]: _.A
Out[209]: 
array([[0.  , 0.25, 0.75, 0.  ],
       [0.  , 0.  , 1.  , 0.  ],
       [1.  , 0.  , 0.  , 0.  ]])

sklearn 还添加了一些稀疏矩阵实用程序

In [210]: from sklearn import preprocessing
In [211]: preprocessing.normalize(M, norm='l1', axis=1)
Out[211]: 
<3x4 sparse matrix of type '<class 'numpy.float64'>'
    with 4 stored elements in Compressed Sparse Row format>
In [212]: _.A
Out[212]: 
array([[0.  , 0.25, 0.75, 0.  ],
       [0.  , 0.  , 1.  , 0.  ],
       [1.  , 0.  , 0.  , 0.  ]])