簡體   English   中英

從Scipy CSR矩陣索引到numpy數組的最有效方法?

[英]Most efficient way to index into a numpy array from a scipy CSR matrix?

我有一個形狀為(4000, 3) 4000,3)的numpy ndarray X ,其中X中的每個樣本都是3D坐標(x,y,z)。

我有一個形狀為(4000, 4000)的sscipy csr矩陣nn_rad_csr ,它是從sklearn.neighbors.radius_neighbors_graph(X, 0.01, include_self=True)生成的最近鄰居圖。

nn_rad_csr.toarray()[i]是形狀(4000,)的稀疏矢量,其二進制權重(0或1)與節點X[i]的最近鄰居圖中的邊關聯。

例如,如果nn_rad_csr.toarray()[i][j] == 1X[j]X[i]的最近鄰居半徑內,而值0表示它不是鄰居。

我想做的是有一個函數radius_graph_conv(X, rad) ,該函數返回一個數組Y ,該數組YX ,按其鄰居的值平均。 我不確定如何利用CSR矩陣的稀疏性來有效地執行radius_graph_conv 我在下面有兩個簡單的圖轉換的實現。

import numpy as np
from sklearn.neighbors import radius_neighbors_graph, KDTree

def radius_graph_conv(X, rad):
    nn_rad_csr = radius_neighbors_graph(X, rad, include_self=True)
    csr_indices = nn_rad_csr.indices
    csr_indptr  = nn_rad_csr.indptr
    Y = np.copy(X)
    for i in range(X.shape[0]):
        j, k = csr_indptr[i], csr_indptr[i+1]
        neighbor_idx = csr_indices[j:k]
        rad_neighborhood = X[neighbor_idx] # ndim always 2
        Y[i] = np.mean(rad_neighborhood, axis=0)
    return Y

def radius_graph_conv_matmul(X, rad):
    nn_rad_arr = radius_neighbors_graph(X, rad, include_self=True).toarray()
    # np.sum(nn_rad_arr, axis=-1) is basically a count of neighbors

    return np.matmul(nn_rad_arr / np.sum(nn_rad_arr, axis=-1), X)

有一個更好的方法嗎? 使用knn圖,它的功能非常簡單,因為鄰居的數目是固定的,您可以索引到X,但是對於基於半徑或密度的最近鄰居圖,則必須使用CSR(或數組)數組(如果您使用的是kd樹)。

這是利用csr格式的直接方法。 您的matmul解決方案可能在后台執行類似的操作。 但是我們還利用它是一個鄰接矩陣來保存一個查找(來自.data屬性)。 同樣, diff .indptr應該比求和相等的數量更有效。

>>> import numpy as np
>>> from scipy import sparse
>>> 
# create mock data
>>> A = np.random.random((100, 100)) < 0.1
>>> A = (A | A.T).view(np.uint8)
>>> AS = sparse.csr_matrix(A)
>>> X = np.random.random((100, 3))
>>> 
# dense solution for reference
>>> Xa = A @ X / A.sum(axis=-1, keepdims=True)
# sparse solution
>>> XaS = np.add.reduceat(X[AS.indices], AS.indptr[:-1], axis=0) / np.diff(AS.indptr)[:, None]
>>> 
# check they are the same
>>> np.allclose(Xa, XaS)
True

暫無
暫無

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

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