Dja*_*cks 7 python networkx graph-algorithm
我想知道如何使用python模块networkX实现SimRank来比较2个节点的相似性?据我所知,它networkX提供了查看邻居的方法,以及链接分析算法,如PageRank和HITS,但有一个用于SimRank吗?
示例,教程也受到欢迎!
use*_*719 13
更新 我实现了networkx_addon库.SimRank包含在库中.有关详细信息,请访问:https://github.com/hhchen1105/networkx_addon.
样品用法:
>>> import networkx
>>> import networkx_addon
>>> G = networkx.Graph()
>>> G.add_edges_from([('a','b'), ('b','c'), ('a','c'), ('c','d')])
>>> s = networkx_addon.similarity.simrank(G)
Run Code Online (Sandbox Code Playgroud)
您可以通过获得两个节点(例如,节点"a"和节点"b")之间的相似性得分
>>> print s['a']['b']
Run Code Online (Sandbox Code Playgroud)
SimRank是一种顶点相似性度量.它基于拓扑(即,图的节点和链接)计算图上两个节点之间的相似性.为了说明SimRank,让我们考虑下面的图,其中,一个,b,c ^彼此连接,并且d被连接到d.一个节点如何一个类似于节点d,是基于怎样一个的邻居节点,b和c ^,类似d的邻国,Ç.
+-------+
| |
a---b---c---d
Run Code Online (Sandbox Code Playgroud)
如图所示,这是一个递归定义.因此,递归地计算SimRank直到相似度值收敛.请注意,SimRank引入了一个常量r来表示直接邻居和直接邻居之间的相对重要性.可以在这里找到SimRank的形式方程.
以下函数将networkx图$ G $和相对imporance参数r作为输入,并返回G中任意两个节点之间的simrank相似值sim.返回值sim是float字典的字典.为了访问图G中节点a和节点b之间的相似性,可以简单地访问sim [a] [b].
def simrank(G, r=0.9, max_iter=100):
# init. vars
sim_old = defaultdict(list)
sim = defaultdict(list)
for n in G.nodes():
sim[n] = defaultdict(int)
sim[n][n] = 1
sim_old[n] = defaultdict(int)
sim_old[n][n] = 0
# recursively calculate simrank
for iter_ctr in range(max_iter):
if _is_converge(sim, sim_old):
break
sim_old = copy.deepcopy(sim)
for u in G.nodes():
for v in G.nodes():
if u == v:
continue
s_uv = 0.0
for n_u in G.neighbors(u):
for n_v in G.neighbors(v):
s_uv += sim_old[n_u][n_v]
sim[u][v] = (r * s_uv / (len(G.neighbors(u)) * len(G.neighbors(v))))
return sim
def _is_converge(s1, s2, eps=1e-4):
for i in s1.keys():
for j in s1[i].keys():
if abs(s1[i][j] - s2[i][j]) >= eps:
return False
return True
Run Code Online (Sandbox Code Playgroud)
要计算上图中节点之间的相似度值,您可以尝试这样做.
>> G = networkx.Graph()
>> G.add_edges_from([('a','b'), ('b', 'c'), ('c','a'), ('c','d')])
>> simrank(G)
Run Code Online (Sandbox Code Playgroud)
你会得到
defaultdict(<type 'list'>, {'a': defaultdict(<type 'int'>, {'a': 0, 'c': 0.62607626807407868, 'b': 0.65379221101693585, 'd': 0.7317028881451203}), 'c': defaultdict(<type 'int'>, {'a': 0.62607626807407868, 'c': 0, 'b': 0.62607626807407868, 'd': 0.53653543888775579}), 'b': defaultdict(<type 'int'>, {'a': 0.65379221101693585, 'c': 0.62607626807407868, 'b': 0, 'd': 0.73170288814512019}), 'd': defaultdict(<type 'int'>, {'a': 0.73170288814512019, 'c': 0.53653543888775579, 'b': 0.73170288814512019, 'd': 0})})
Run Code Online (Sandbox Code Playgroud)
让我们通过计算节点a和节点b之间的相似性来验证结果,用S(a,b)表示.
S(a,b)= r*(S(b,a)+ S(b,c)+ S(c,a)+ S(c,c))/(2*2)= 0.9*(0.6538+ 0.6261 + 0.6261 + 1)/ 4 = 0.6538,
这与我们上面计算的S(a,b)相同.
有关详细信息,您可能需要查看以下文章:
G. Jeh和J. Widom.SimRank:结构 - 背景相似性的度量.在KDD'02第538-543页.ACM出版社,2002年.
不,simrank没有在networkx中实现.
如果要将其添加到networkx,可以使用和缩短user1036719给出的代码:numpyitertools
def simrank(G, r=0.8, max_iter=100, eps=1e-4):
nodes = G.nodes()
nodes_i = {k: v for(k, v) in [(nodes[i], i) for i in range(0, len(nodes))]}
sim_prev = numpy.zeros(len(nodes))
sim = numpy.identity(len(nodes))
for i in range(max_iter):
if numpy.allclose(sim, sim_prev, atol=eps):
break
sim_prev = numpy.copy(sim)
for u, v in itertools.product(nodes, nodes):
if u is v:
continue
u_ns, v_ns = G.predecessors(u), G.predecessors(v)
# evaluating the similarity of current iteration nodes pair
if len(u_ns) == 0 or len(v_ns) == 0:
# if a node has no predecessors then setting similarity to zero
sim[nodes_i[u]][nodes_i[v]] = 0
else:
s_uv = sum([sim_prev[nodes_i[u_n]][nodes_i[v_n]] for u_n, v_n in itertools.product(u_ns, v_ns)])
sim[nodes_i[u]][nodes_i[v]] = (r * s_uv) / (len(u_ns) * len(v_ns))
return sim
Run Code Online (Sandbox Code Playgroud)
然后,从SimRank论文(大学图)中取出玩具示例,再现纸张结果:
G = networkx.DiGraph()
G.add_edges_from([('1','2'), ('1', '4'), ('2','3'), ('3','1'), ('4', '5'), ('5', '4')])
pprint(simrank(G).round(3))
Run Code Online (Sandbox Code Playgroud)
哪个输出:
array([[ 1. , 0. , 0. , 0.034, 0.132],
[ 0. , 1. , 0. , 0.331, 0.042],
[ 0. , 0. , 1. , 0.106, 0.414],
[ 0.034, 0.331, 0.106, 1. , 0.088],
[ 0.132, 0.042, 0.414, 0.088, 1. ]])
Run Code Online (Sandbox Code Playgroud)