簡體   English   中英

使用numpy數組加速通過索引獲取邊緣矩陣

[英]Speed up getting edge matrix by index with numpy array

我想在原始矩陣中剪裁邊緣,不知道有沒有更快的方法。 由於我需要在相同的positions和positions_u中多次運行selectEdge函數,這意味着對於很多圖形來說索引不會改變嗎? 是否有可能生成一個可以解決所有問題的映射矩陣?

非常感謝你

def selectEdge(positions, positions_u, originalMat, selectedMat):
    """ select Edge by neighbors of all points
    many to many
    m positions
    n positions
    would have m*n edges
    update selectedMat
    """
    for ele in positions:
        for ele_u in positions_u:            
            selectedMat[ele][ele_u] += originalMat[ele][ele_u]
            selectedMat[ele_u][ele] += originalMat[ele_u][ele]
    return selectedMat

我只需要上三角矩陣,因為它是對稱的

def test_selectEdge(self):
        positions, positions_u = np.array([0,1,5,7]), np.array([2,3,4,6])
        originalMat, selectedMat = np.array([[1.0]*8]*8), np.array([[0.0]*8]*8)
        selectedMat = selectEdge(positions, positions_u, originalMat, selectedMat)
        print 'position, positions_u'
        print positions, positions_u
        print 'originalMat', originalMat
        print 'selectedMat', selectedMat

這是我的測試結果

position, positions_u
[0 1 5 7] [2 3 4 6]
originalMat 
[[ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.]]
selectedMat 
[[ 0.  0.  1.  1.  1.  0.  1.  0.]
 [ 0.  0.  1.  1.  1.  0.  1.  0.]
 [ 1.  1.  0.  0.  0.  1.  0.  1.]
 [ 1.  1.  0.  0.  0.  1.  0.  1.]
 [ 1.  1.  0.  0.  0.  1.  0.  1.]
 [ 0.  0.  1.  1.  1.  0.  1.  0.]
 [ 1.  1.  0.  0.  0.  1.  0.  1.]
 [ 0.  0.  1.  1.  1.  0.  1.  0.]]

對於后面的選擇相鄰邊的實現,它甚至會更慢

def selectNeighborEdges(originalMat, selectedMat, relation):
    """ select Edge by neighbors of all points
    one to many
    Args:
        relation: dict, {node1:[node i, node j,...], node2:[node i, node j, ...]}

    update selectedMat
    """
    for key in relation:
        selectedMat = selectEdge([key], relation[key], originalMat, selectedMat)
    return selectedMat

您可以使用“高級整數索引”消除double for-loop

X, Y = positions[:,None], positions_u[None,:]
selectedMat[X, Y] += originalMat[X, Y]
selectedMat[Y, X] += originalMat[Y, X]

例如,

import numpy as np

def selectEdge(positions, positions_u, originalMat, selectedMat):
    for ele in positions:
        for ele_u in positions_u:
            selectedMat[ele][ele_u] += originalMat[ele][ele_u]
            selectedMat[ele_u][ele] += originalMat[ele_u][ele]
    return selectedMat

def alt_selectEdge(positions, positions_u, originalMat, selectedMat):
    X, Y = positions[:,None], positions_u[None,:]
    selectedMat[X, Y] += originalMat[X, Y]
    selectedMat[Y, X] += originalMat[Y, X]
    return selectedMat


N, M = 100, 50
positions = np.random.choice(np.arange(N), M, replace=False)
positions_u = np.random.choice(np.arange(N), M, replace=False)
originalMat = np.random.random((N, N))
selectedMat = np.zeros_like(originalMat)

首先檢查selectEdgealt_selectEdge返回相同的結果:

expected = selectEdge(positions, positions_u, originalMat, selectedMat)
result = alt_selectEdge(positions, positions_u, originalMat, selectedMat)
assert np.allclose(expected, result)

這是一個timeit基准測試(使用IPython):

In [89]: %timeit selectEdge(positions, positions_u, originalMat, selectedMat)
100 loops, best of 3: 4.44 ms per loop

In [90]: %timeit alt_selectEdge(positions, positions_u, originalMat, selectedMat)
10000 loops, best of 3: 104 µs per loop

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM