从networkX中的随机漫步中获取节点列表

时间:2016-05-18 23:27:20

标签: python graph machine-learning statistics networkx

我是networkX的新手。我创建了如下图表:

G = nx.read_edgelist(filename,
                     nodetype=int,
                     delimiter=',',
                     data=(('weight', float),))

其中边缘为正,但不总和为1。

是否有内置方法从某个节点随机遍历k步并返回节点列表?如果没有,最简单的方法是什么(节点可以重复)?

伪代码:

node = random
res = [node]
for i in range(0, k)
    read edge weights from this node
    an edge from this node has probability weight / sum_weights
    node = pick an edge from this node 
    res.append(node)

5 个答案:

答案 0 :(得分:2)

最有效的方法是使用 CSR 稀疏格式的图的转换矩阵,当然,有一个很好的包:csrgraph (pip install csrgraph)。您可以这样做:

import csrgraph as cg
import numpy as np

G = cg.csrgraph(G, threads=12) 
node_names = G.names
walks = G.random_walks(walklen=10, # length of the walks
                epochs=100, # how many times to start a walk from each node
                start_nodes=None, # the starting node. It is either a list (e.g., [2,3]) or None. If None it does it on all nodes and returns epochs*G.number_of_nodes() walks
                return_weight=1.,
                neighbor_weight=1.)

结果是一个大小为 (epochs*number_of_nodes, walklen) 的数组。有关该函数及其参数的更多信息,请参见 here

在包含 2,130 个节点和 36,560 条边的图形上,我用了 0.5 秒生成了 213,000 条长度为 20 的路径,上面的代码片段:

>>> array([[   0,    4, 1678, ...,   48,  728,   30],
       [   1,   57,  102, ...,  947,  456,  240],
       [   2,  156,  177, ...,  175, 1363,  539],
       ...,
       [2127, 1655, 1656, ..., 1655, 1656, 2127],
       [2128,    4, 1432, ...,  111,   32,  162],
       [2129,    4,  521, ..., 1280,  180,  608]], dtype=uint32)

walks.shape
>>> (213000, 20)

可以使用以下代码段或其他类似方法将节点名称映射回其原始格式:

walks = np.vectorize(lambda x: node_names[x])(walks) # map to original node names

注意:这个包不仅仅是随机游走,你可能想查看他们的 GitHub 存储库 here

答案 1 :(得分:1)

免责声明:我是以下软件包的作者。

我很惊讶地发现没有任何库可以有效地做到这一点,因此我专门为此构建并开源了一个 python 包。它是用 C++ 编写的,并使用并行化以获得最大速度。它可以在几秒钟内生成数百万次随机游走。

import walker

walks = walker.random_walks(G, n_walks=15, walk_len=10)

这将为图形 G 中的每个节点创建 15 次步行,长度为 10。

如果您只想从单个节点开始创建一个随机游走:

node = 42
walks = walker.random_walks(G, n_walks=1, walk_len=10, start_node=[node])

您还可以通过指定 pq 参数来创建偏向 node2vec 的随机游走。

安装需要 pybind11 以允许 C++ 绑定:

pip install pybind11
pip install graph-walker

答案 2 :(得分:0)

您可以使用邻接矩阵。然后,您可以对其进行标准化,使行的总和等于1,每行是跳转到另一个节点的节点的概率分布。 如果助行器跳转到随机节点,您也可以有跳跃概率。

M = nx.adjacency_matrix(g) #obtain the adj. matrix for the graph
#normalise the adjacency matrix
for i in range(M.shape[1]):
    if (np.sum(M[i]) > 0):
    M[i] = M[i]/np.sum(M[i])
p = generate a random number between 0 and 1
if p < restart_prob:
    #do restart
else:
    #choose next node

然后你可以随机选择一个节点,然后用概率 1-restart_prob 选择下一个节点,或者以概率 restart_prob 重新启动walker。

为了更好地理解算法,您可以了解PageRank的工作原理。

答案 3 :(得分:0)

最简单的方法是使用转移矩阵 T 然后使用普通马尔可夫随机游走(简而言之,图形可以被视为有限状态马尔可夫链)。 / p>

A D 分别是图 G 的邻接度和度矩阵。转换矩阵 T 定义为 T = D ^( - 1) A
p ^(0)为状态向量(简而言之, i -th组件表示在节点 i 处的概率)在步行开始时,第一步(步行)可以评估为 p ^(1)= T p ^(0)。
迭代地, k - 随机游走步骤可以评估为 p ^(k)= T p ^ (K-1)。

以简单的Networkx术语......

import networkx
import numpy
# let's generate a graph G
G = networkx.gnp_random_graph(5, 0.5)
# let networkx return the adjacency matrix A
A = networkx.adj_matrix(G)
A = A.todense()
A = numpy.array(A, dtype = numpy.float64)
# let's evaluate the degree matrix D
D = numpy.diag(numpy.sum(A, axis=0))
# ...and the transition matrix T
T = numpy.dot(numpy.linalg.inv(D),A)
# let's define the random walk length, say 10
walkLength = 10
# define the starting node, say the 0-th
p = numpy.array([1, 0, 0, 0, 0]).reshape(-1,1)
visited = list()
for k in range(walkLength):
    # evaluate the next state vector
    p = numpy.dot(T,p)
    # choose the node with higher probability as the visited node
    visited.append(numpy.argmax(p))

答案 4 :(得分:0)

扩展@AlessioX的答案

让A是一个邻接矩阵,即如果顶点i和j之间有边,则A_ij为1.0,否则为0.0。 (不过请注意,以下内容甚至适用于加权邻接矩阵。)

>>> A
array([[1, 0, 1],
       [1, 1, 1],
       [0, 0, 1]])

然后我们可以通过简单地将每一行除以总和来找到转换矩阵T:

>>> A / A.sum(axis=1, keepdims=True)
array([[0.5       , 0.        , 0.5       ],
       [0.33333333, 0.33333333, 0.33333333],
       [0.        , 0.        , 1.        ]])