所以,我正在使用非常稀疏的numpy数组进行一些Kmeans分类 - 很多很多零。我想我会使用scipy的'稀疏'软件包来减少存储开销,但我对如何创建数组而不是矩阵感到有些困惑。
我已经完成了关于如何创建稀疏矩阵的教程: http://www.scipy.org/SciPy_Tutorial#head-c60163f2fd2bab79edd94be43682414f18b90df7
为了模仿一个数组,我只是创建一个1xN矩阵,但正如你猜测的那样,Asp.dot(Bsp)不能正常工作,因为你不能将两个1xN矩阵相乘。我必须将每个数组转换为Nx1,这非常蹩脚,因为我会为每个点积计算做这个。
接下来,我尝试创建一个NxN矩阵,其中第1列==第1行(这样您可以将两个矩阵相乘,只需将左上角作为点积),但结果证明效率非常低
我喜欢使用scipy的稀疏包作为numpy的数组()的神奇替代品,但到目前为止,我还不确定该怎么做。
有什么建议吗?
答案 0 :(得分:34)
使用基于行或列的scipy.sparse
格式:csc_matrix
和csr_matrix
。
这些使用高效的C实现(包括乘法),并且转置是无操作(特别是如果你调用transpose(copy=False)
),就像使用numpy数组一样。
编辑:通过ipython的一些时间安排:
import numpy, scipy.sparse
n = 100000
x = (numpy.random.rand(n) * 2).astype(int).astype(float) # 50% sparse vector
x_csr = scipy.sparse.csr_matrix(x)
x_dok = scipy.sparse.dok_matrix(x.reshape(x_csr.shape))
现在x_csr
和x_dok
稀疏50%:
print repr(x_csr)
<1x100000 sparse matrix of type '<type 'numpy.float64'>'
with 49757 stored elements in Compressed Sparse Row format>
时间安排:
timeit numpy.dot(x, x)
10000 loops, best of 3: 123 us per loop
timeit x_dok * x_dok.T
1 loops, best of 3: 1.73 s per loop
timeit x_csr.multiply(x_csr).sum()
1000 loops, best of 3: 1.64 ms per loop
timeit x_csr * x_csr.T
100 loops, best of 3: 3.62 ms per loop
所以看起来我说谎了。换位 非常便宜,但没有csr * csc的高效C实现(在最新的scipy 0.9.0中)。每次调用都会构造一个新的csr对象: - (
作为一个黑客(虽然现在scipy相对稳定),你可以直接在稀疏数据上做点积:
timeit numpy.dot(x_csr.data, x_csr.data)
10000 loops, best of 3: 62.9 us per loop
注意这最后一种方法再次进行了numpy密集乘法。稀疏度为50%,因此实际上比dot(x, x)
快2倍。
答案 1 :(得分:1)
您可以创建现有2d稀疏数组之一的子类
from scipy.sparse import dok_matrix
class sparse1d(dok_matrix):
def __init__(self, v):
dok_matrix.__init__(self, (v,))
def dot(self, other):
return dok_matrix.dot(self, other.transpose())[0,0]
a=sparse1d((1,2,3))
b=sparse1d((4,5,6))
print a.dot(b)
答案 2 :(得分:1)
我不确定它真的好多了或者更快,但你可以这样做以避免使用转置:
Asp.multiply(Bsp).sum()
这只是采用两个矩阵的逐元素乘积并对产品求和。您可以创建一个子类,使用上面使用上述语句作为点积的矩阵格式。
然而,转换它们可能更容易:
Asp*Bsp.T
这似乎不是很多,但你也可以创建一个子类并修改 mul ()方法。