Python Numpy:将矩阵的每一行添加到矩阵中(一次一行),然后找到每个新矩阵中每一行的最小值。希望加快代码速度吗

Python Numpy:将矩阵的每一行添加到矩阵中(一次一行),然后找到每个新矩阵中每一行的最小值。希望加快代码速度吗,python,performance,numpy,matrix,Python,Performance,Numpy,Matrix,我将矩阵中的每一行添加到矩阵中,然后计算新矩阵中每一行的最小值 我当前来自python的代码带有一个测试用例: # Compute distances to all other nodes using landmarks distToLM = np.array([[1,2,3],[4,5,6],[7,8,9]]) m = len(distToLM) count = 1 dist = np.zeros((m,m)) for i in range(m): findMin = distToL

我将矩阵中的每一行添加到矩阵中,然后计算新矩阵中每一行的最小值

我当前来自python的代码带有一个测试用例:

# Compute distances to all other nodes using landmarks 
distToLM = np.array([[1,2,3],[4,5,6],[7,8,9]])
m = len(distToLM)
count = 1
dist = np.zeros((m,m))
for i in range(m):
    findMin = distToLM[i,:] + distToLM.take(range(count,m),axis=0) 
    dist[i,count:]=np.min(findMin,axis = 1)
    count = count + 1
注意:我每次都在切片矩阵,因为我只需要矩阵的上三角值

因此,第一次迭代将[1,2,3]与[4,5,6]和[7,8,9]相加,形成一个矩阵:

[5,7,9]

[8,10,12]

从这里我想要每行的最小值,所以是5和8

下一次迭代我将取[4,5,6],并将其添加到它下面的所有行,即[7,8,9],然后取每行的最小值

这段代码相当慢,对于4000x4000矩阵大约3秒

我也尝试过Cython版本,速度没有太大的提高,这可能是因为调用numpy函数与在C中执行主代码相比有很大的依赖性:

DTYPE=np.int

ctypedef np.int_t DTYPE_t
@cython.boundscheck(False)
@cython.wraparound(False)
def findDist(np.ndarray[DTYPE_t,ndim=2] distToLM):
    cdef int m = distToLM.shape[0]
    count = 1
    cdef np.ndarray[DTYPE_t, ndim=2] dist = np.zeros((m,m),dtype=DTYPE)
    cdef np.ndarray[DTYPE_t, ndim=2] findMin
    for i in range(m):
        findMin = distToLM[i,:] + distToLM.take(range(count,m),axis=0) 
        dist[i,count:]=np.min(findMin,axis = 1)
        count = count + 1
    return dist
我想如果有什么方法可以矢量化的话,速度会快得多


我愿意接受任何建议。

稍微更改一下可以帮助我更好地形象化行动(我不太使用
take
):

事实上,双重迭代甚至很清楚:

distToLM = np.array([[1,2,3],[4,5,6],[7,8,9]])
m = distToLM.shape[0]
dist = np.zeros((m,m), distToLM.dtype)
for i in range(m):
    for j in range(i+1,m):
        dist[i,j] = np.min(distToLM[i,:] + distToLM[j,:])
这揭示了代码中模糊的二维对称性。它不会更快,但使用Cython MemoryView更容易实现

这种对称性还表明我可以对这些行执行“外部”求和:

In [512]: np.min(distToLM[:,None,:]+distToLM[None,:,:],axis=-1)
Out[512]: 
array([[ 2,  5,  8],
       [ 5,  8, 11],
       [ 8, 11, 14]])
上tri是所需的距离

In [518]: np.triu(_,k=1)
Out[518]: 
array([[ 0,  5,  8],
       [ 0,  0, 11],
       [ 0,  0,  0]])
这比迭代方法计算的值更多,但速度更快。不幸的是,对于您的大问题来说,中等大小(40004000)的阵列对于内存来说可能太大了

我可以选择
triu
索引,然后使用:

In [530]: I,J=np.triu_indices(3,1)
In [531]: I,J
Out[531]: (array([0, 0, 1], dtype=int32), array([1, 2, 2], dtype=int32))
In [532]: np.min(distToLM[I,:]+distToLM[J,:],axis=1)
Out[532]: array([ 5,  8, 11])
我对大型阵列的性能没有感觉

这提醒我,
scipy.spatical
有它所谓的
squareform
compact
成对距离表示


也许那里有些有用的东西

如果您提供了一个最小的测试
distToLM
,这会有所帮助。我试着测试一下你的代码,但还是放弃了。这不值得我花时间去猜测。明天早上我有机会的时候,我会举一个例子。谢谢你的建议。
In [530]: I,J=np.triu_indices(3,1)
In [531]: I,J
Out[531]: (array([0, 0, 1], dtype=int32), array([1, 2, 2], dtype=int32))
In [532]: np.min(distToLM[I,:]+distToLM[J,:],axis=1)
Out[532]: array([ 5,  8, 11])