Python - scipy 稀疏矩阵的高效函数
Python - Efficient Function with scipy sparse Matrices
对于一个项目,我需要 python 中的高效函数来解决以下任务:
给定一个非常大的长稀疏向量列表 X(=> 大稀疏矩阵)和另一个包含单个向量 y 的矩阵 Y,我想要一个 "distances" 列表,y 必须包含每个元素X的。特此"distance"定义如下:
比较两个Vector的每一个Element,总是取小的然后相加。
示例:
X = [[0,0,2],
[1,0,0],
[3,1,0]]
Y = [[1,0,2]]
函数应该return dist = [2,1,1]
在我的项目中,X 和 Y 都包含很多零,并作为以下实例出现:
<class 'scipy.sparse.csr.csr_matrix'>
到目前为止一切顺利,我设法编写了一个函数来解决这个任务,但速度非常慢且效率低下。我需要一些关于如何提高 process/iterate 稀疏矩阵效率的技巧。
这是我的功能:
def get_distances(X, Y):
Ret=[]
rows, cols = X.shape
for i in range(0,rows):
dist = 0
sample = X.getrow(i).todense()
test = Y.getrow(0).todense()
rows_s, cols_s = sample.shape
rows_t, cols_t = test.shape
for s,t in zip(range(0, cols_s), range(0, cols_t)):
dist += min(sample[0,s], test[0,t])
X_ret.append([dist])
return ret
为了进行运算,我将稀疏矩阵转换为密集矩阵,这当然很糟糕,但我不知道如何做得更好。你知道如何改进我的代码并使功能更快吗?
非常感谢!
我修改了你的函数,运行它在
import numpy as np
from scipy import sparse
def get_distances(X, Y):
ret=[]
for row in X:
sample = row.A
test = Y.getrow(0).A
dist = np.minimum(sample[0,:], test[0,:]).sum()
ret.append(dist)
return ret
X = [[0,0,2],
[1,0,0],
[3,1,0]]
Y = [[1,0,2]]
XM = sparse.csr_matrix(X)
YM = sparse.csr_matrix(Y)
print( get_distances(XM,YM))
print (np.minimum(XM.A, YM.A).sum(axis=1))
生产
1255:~/mypy$ python3 stack37056258.py
[2, 1, 1]
[2 1 1]
np.minimum
采用两个数组(可能是 2d)的元素明智的最小值,所以我不需要迭代列。我也不需要使用索引。
minimum
也适用于稀疏矩阵,但是当我尝试将它应用于 X
(3 行)和 Y
(1 ).如果它们的大小相同,则此方法有效:
Ys = sparse.vstack((YM,YM,YM))
print(Ys.shape)
print (XM.minimum(Ys).sum(axis=1))
将单行矩阵转换为数组也可以解决错误 - 因为它最终使用密集版本,np.minimum(XM.todense(), YM.A)
。
print (XM.minimum(YM.A).sum(axis=1))
当我尝试对这 2 个矩阵进行其他逐个元素的操作时,我得到 ValueError: inconsistent shapes
,例如XM+YM
,或 XM<YM
。看起来稀疏不像 numpy
数组那样实现广播。
=======================
多次复制1行稀疏矩阵的方式比较
In [271]: A=sparse.csr_matrix([0,1,0,0,1])
In [272]: timeit sparse.vstack([A]*3000).A
10 loops, best of 3: 32.3 ms per loop
In [273]: timeit sparse.kron(A,np.ones((3000,1),int)).A
1000 loops, best of 3: 1.27 ms per loop
很多时候,kron
比vstack
好。
=======================
问题与
有重叠
试试下面的稀疏矩阵代码:
from scipy.sparse import csr_matrix, vstack
X = csr_matrix([[0,0,2],[1,0,0],[3,1,0]])
Y = csr_matrix([[1,0,2]])
def matrix_dist(x,y):
y=vstack([y]*x.shape[1])
return (((x+y)-(x-y).multiply((x-y).sign())).sum(1)/2).A.ravel()
对于一个项目,我需要 python 中的高效函数来解决以下任务:
给定一个非常大的长稀疏向量列表 X(=> 大稀疏矩阵)和另一个包含单个向量 y 的矩阵 Y,我想要一个 "distances" 列表,y 必须包含每个元素X的。特此"distance"定义如下:
比较两个Vector的每一个Element,总是取小的然后相加。
示例:
X = [[0,0,2],
[1,0,0],
[3,1,0]]
Y = [[1,0,2]]
函数应该return dist = [2,1,1]
在我的项目中,X 和 Y 都包含很多零,并作为以下实例出现:
<class 'scipy.sparse.csr.csr_matrix'>
到目前为止一切顺利,我设法编写了一个函数来解决这个任务,但速度非常慢且效率低下。我需要一些关于如何提高 process/iterate 稀疏矩阵效率的技巧。 这是我的功能:
def get_distances(X, Y):
Ret=[]
rows, cols = X.shape
for i in range(0,rows):
dist = 0
sample = X.getrow(i).todense()
test = Y.getrow(0).todense()
rows_s, cols_s = sample.shape
rows_t, cols_t = test.shape
for s,t in zip(range(0, cols_s), range(0, cols_t)):
dist += min(sample[0,s], test[0,t])
X_ret.append([dist])
return ret
为了进行运算,我将稀疏矩阵转换为密集矩阵,这当然很糟糕,但我不知道如何做得更好。你知道如何改进我的代码并使功能更快吗?
非常感谢!
我修改了你的函数,运行它在
import numpy as np
from scipy import sparse
def get_distances(X, Y):
ret=[]
for row in X:
sample = row.A
test = Y.getrow(0).A
dist = np.minimum(sample[0,:], test[0,:]).sum()
ret.append(dist)
return ret
X = [[0,0,2],
[1,0,0],
[3,1,0]]
Y = [[1,0,2]]
XM = sparse.csr_matrix(X)
YM = sparse.csr_matrix(Y)
print( get_distances(XM,YM))
print (np.minimum(XM.A, YM.A).sum(axis=1))
生产
1255:~/mypy$ python3 stack37056258.py
[2, 1, 1]
[2 1 1]
np.minimum
采用两个数组(可能是 2d)的元素明智的最小值,所以我不需要迭代列。我也不需要使用索引。
minimum
也适用于稀疏矩阵,但是当我尝试将它应用于 X
(3 行)和 Y
(1 ).如果它们的大小相同,则此方法有效:
Ys = sparse.vstack((YM,YM,YM))
print(Ys.shape)
print (XM.minimum(Ys).sum(axis=1))
将单行矩阵转换为数组也可以解决错误 - 因为它最终使用密集版本,np.minimum(XM.todense(), YM.A)
。
print (XM.minimum(YM.A).sum(axis=1))
当我尝试对这 2 个矩阵进行其他逐个元素的操作时,我得到 ValueError: inconsistent shapes
,例如XM+YM
,或 XM<YM
。看起来稀疏不像 numpy
数组那样实现广播。
=======================
多次复制1行稀疏矩阵的方式比较
In [271]: A=sparse.csr_matrix([0,1,0,0,1])
In [272]: timeit sparse.vstack([A]*3000).A
10 loops, best of 3: 32.3 ms per loop
In [273]: timeit sparse.kron(A,np.ones((3000,1),int)).A
1000 loops, best of 3: 1.27 ms per loop
很多时候,kron
比vstack
好。
=======================
问题与
试试下面的稀疏矩阵代码:
from scipy.sparse import csr_matrix, vstack
X = csr_matrix([[0,0,2],[1,0,0],[3,1,0]])
Y = csr_matrix([[1,0,2]])
def matrix_dist(x,y):
y=vstack([y]*x.shape[1])
return (((x+y)-(x-y).multiply((x-y).sign())).sum(1)/2).A.ravel()