我是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)
答案 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])
您还可以通过指定 p 和 q 参数来创建偏向 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. ]])