python - 从 scipy CSR 矩阵索引到 numpy 数组的最有效方法?

标签 python numpy scipy scikit-learn nearest-neighbor

我有一个 numpy ndarray X有形状(4000, 3) ,其中 X 中的每个样本是 3D 坐标 (x,y,z)。

我有一个 scipy csr 矩阵 nn_rad_csr形状(4000, 4000) ,这是从 sklearn.neighbors.radius_neighbors_graph(X, 0.01, include_self=True) 生成的最近邻图.

nn_rad_csr.toarray()[i]是一个形状 (4000,) 稀疏向量,具有与节点 X[i] 的最近邻居图中的边相关联的二进制权重(0 或 1) 。

例如,如果 nn_rad_csr.toarray()[i][j] == 1然后X[j]位于 X[i] 的最近邻半径内,而值为 0意味着它不是邻居。

我想做的是有一个函数 radius_graph_conv(X, rad)它返回一个数组 Y这是 X ,由其邻居的值取平均值。我不确定如何利用 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 属性);此外,diffing .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

关于python - 从 scipy CSR 矩阵索引到 numpy 数组的最有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48390268/

相关文章:

python - 将行和列插入 numpy 数组

python - Pandas : select row where column A does not begin with column B

python - 将名称之间的制表符替换为空格

python - 如何计算 50x20 矩阵的类内散布

python - numpy/pylab 最小值,最大值

python - 当向其传递两组相同的数据时,自制的 pearson 相关实现返回 0.999...2

python - 多行正则表达式

python - 在 matplotlib 中使用 log2 比例制作方轴图

python - 索引错误 : too many indices for np. 数组

python - 具有三个输出的 Matlab polyval 函数在 Python/Numpy 中等效