scipy.sparse 矩阵:将行均值减去非零元素
scipy.sparse matrix: subtract row mean to nonzero elements
我有一个 csr_matrix 格式的稀疏矩阵。对于每一行,我需要从非零元素中减去行均值。必须根据行的非零元素数(而不是行的长度)计算均值。
我找到了一种使用以下代码快速计算行均值的方法:
# M is a csr_matrix
sums = np.squeeze(np.asarray(M.sum(1))) # sum of the nonzero elements, for each row
counts = np.diff(M.tocsr().indptr) # count of the nonzero elements, for each row
# for the i-th row the mean is just sums[i] / float(counts[i])
问题出在更新部分。我需要一种快速的方法来做到这一点。
实际上我正在做的是将 M 转换为 lil_matrix 并以这种方式执行更新:
M = M.tolil()
for i in xrange(len(sums)):
for j in M.getrow(i).nonzero()[1]:
M[i, j] -= sums[i] / float(counts[i])
这很慢。对更快的解决方案有什么建议吗?
这个很棘手。我想我有。基本思想是我们尝试得到一个均值在对角线上的对角矩阵,以及一个类似于 M 的矩阵,但在 M 中的非零数据位置有一个矩阵。然后我们将它们相乘并从 M 中减去乘积。这里去...
>>> import numpy as np
>>> import scipy.sparse as sp
>>> a = sp.csr_matrix([[1., 0., 2.], [1.,2.,3.]])
>>> a.todense()
matrix([[ 1., 0., 2.],
[ 1., 2., 3.]])
>>> tot = np.array(a.sum(axis=1).squeeze())[0]
>>> tot
array([ 3., 6.])
>>> cts = np.diff(a.indptr)
>>> cts
array([2, 3], dtype=int32)
>>> mu = tot/cts
>>> mu
array([ 1.5, 2. ])
>>> d = sp.diags(mu, 0)
>>> d.todense()
matrix([[ 1.5, 0. ],
[ 0. , 2. ]])
>>> b = a.copy()
>>> b.data = np.ones_like(b.data)
>>> b.todense()
matrix([[ 1., 0., 1.],
[ 1., 1., 1.]])
>>> (d * b).todense()
matrix([[ 1.5, 0. , 1.5],
[ 2. , 2. , 2. ]])
>>> (a - d*b).todense()
matrix([[-0.5, 0. , 0.5],
[-1. , 0. , 1. ]])
祝你好运!希望对您有所帮助。
从 @Dthal's
样本开始:
In [92]: a = sparse.csr_matrix([[1.,0,2],[1,2,3]])
In [93]: a.A
Out[93]:
array([[ 1., 0., 2.],
[ 1., 2., 3.]])
In [94]: sums=np.squeeze(a.sum(1).A)
# sums=a.sum(1).A1 # shortcut
In [95]: counts=np.diff(a.tocsr().indptr)
In [96]: means=sums/counts
In [97]: sums
Out[97]: array([ 3., 6.])
In [98]: counts
Out[98]: array([2, 3], dtype=int32)
In [99]: means
Out[99]: array([ 1.5, 2. ])
repeat
让我们复制 means
,生成一个大小与矩阵 data
匹配的数组。
In [100]: mc = np.repeat(means, counts)
In [101]: mc
Out[101]: array([ 1.5, 1.5, 2. , 2. , 2. ])
此mc
与@Dthal's
相同(b*d).data
。
现在只需从 data
中减去即可。
In [102]: a.data -= mc
In [103]: a.A
Out[103]:
array([[-0.5, 0. , 0.5],
[-1. , 0. , 1. ]])
我有一个 csr_matrix 格式的稀疏矩阵。对于每一行,我需要从非零元素中减去行均值。必须根据行的非零元素数(而不是行的长度)计算均值。 我找到了一种使用以下代码快速计算行均值的方法:
# M is a csr_matrix
sums = np.squeeze(np.asarray(M.sum(1))) # sum of the nonzero elements, for each row
counts = np.diff(M.tocsr().indptr) # count of the nonzero elements, for each row
# for the i-th row the mean is just sums[i] / float(counts[i])
问题出在更新部分。我需要一种快速的方法来做到这一点。 实际上我正在做的是将 M 转换为 lil_matrix 并以这种方式执行更新:
M = M.tolil()
for i in xrange(len(sums)):
for j in M.getrow(i).nonzero()[1]:
M[i, j] -= sums[i] / float(counts[i])
这很慢。对更快的解决方案有什么建议吗?
这个很棘手。我想我有。基本思想是我们尝试得到一个均值在对角线上的对角矩阵,以及一个类似于 M 的矩阵,但在 M 中的非零数据位置有一个矩阵。然后我们将它们相乘并从 M 中减去乘积。这里去...
>>> import numpy as np
>>> import scipy.sparse as sp
>>> a = sp.csr_matrix([[1., 0., 2.], [1.,2.,3.]])
>>> a.todense()
matrix([[ 1., 0., 2.],
[ 1., 2., 3.]])
>>> tot = np.array(a.sum(axis=1).squeeze())[0]
>>> tot
array([ 3., 6.])
>>> cts = np.diff(a.indptr)
>>> cts
array([2, 3], dtype=int32)
>>> mu = tot/cts
>>> mu
array([ 1.5, 2. ])
>>> d = sp.diags(mu, 0)
>>> d.todense()
matrix([[ 1.5, 0. ],
[ 0. , 2. ]])
>>> b = a.copy()
>>> b.data = np.ones_like(b.data)
>>> b.todense()
matrix([[ 1., 0., 1.],
[ 1., 1., 1.]])
>>> (d * b).todense()
matrix([[ 1.5, 0. , 1.5],
[ 2. , 2. , 2. ]])
>>> (a - d*b).todense()
matrix([[-0.5, 0. , 0.5],
[-1. , 0. , 1. ]])
祝你好运!希望对您有所帮助。
从 @Dthal's
样本开始:
In [92]: a = sparse.csr_matrix([[1.,0,2],[1,2,3]])
In [93]: a.A
Out[93]:
array([[ 1., 0., 2.],
[ 1., 2., 3.]])
In [94]: sums=np.squeeze(a.sum(1).A)
# sums=a.sum(1).A1 # shortcut
In [95]: counts=np.diff(a.tocsr().indptr)
In [96]: means=sums/counts
In [97]: sums
Out[97]: array([ 3., 6.])
In [98]: counts
Out[98]: array([2, 3], dtype=int32)
In [99]: means
Out[99]: array([ 1.5, 2. ])
repeat
让我们复制 means
,生成一个大小与矩阵 data
匹配的数组。
In [100]: mc = np.repeat(means, counts)
In [101]: mc
Out[101]: array([ 1.5, 1.5, 2. , 2. , 2. ])
此mc
与@Dthal's
相同(b*d).data
。
现在只需从 data
中减去即可。
In [102]: a.data -= mc
In [103]: a.A
Out[103]:
array([[-0.5, 0. , 0.5],
[-1. , 0. , 1. ]])