Actualización Implementé una biblioteca networkx_addon. SimRank está incluido en la biblioteca. Consulte: https://github.com/hhchen1105/networkx_addon para más detalles.
Uso de la muestra:
>>> 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)
Usted puede obtener la puntuación de similitud entre dos nodos (por ejemplo, nodo 'a' y el nodo 'b') por
>>> print s['a']['b']
SimRank es una medida de similitud de vértice. Calcula la similitud entre dos nodos en un gráfico basado en la topología, es decir, los nodos y los enlaces del gráfico. Para ilustrar SimRank, consideremos el siguiente gráfico, en el que un, b, c se conectan entre sí, y d está conectado a d. ¿Cómo un nodo un es similar a un nodo d, se basa en la forma de un 's nodos vecinos, b y c , similar a d' s vecinos, c.
+-------+
| |
a---b---c---d
Como se ve, esta es una definición recursiva. Por lo tanto, SimRank se calcula recursivamente hasta que converjan los valores de similitud. Tenga en cuenta que SimRank introduce una constante r para representar la importancia relativa entre vecinos directos y vecinos directos. La ecuación formal de SimRank se puede encontrar here.
La siguiente función toma un NetworkX gráfico $ G $ y el parámetro imporance relativa r como entrada, y devuelve el valor de similitud simrank sim entre dos nodos en G. El valor de retorno sim es un diccionario del diccionario de flotación. Para acceder a la similitud entre el nodo a y el nodo b en el gráfico G, se puede acceder simplemente a 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
Para calcular los valores de similitud entre los nodos en el gráfico anterior, puede intentarlo.
>> G = networkx.Graph()
>> G.add_edges_from([('a','b'), ('b', 'c'), ('c','a'), ('c','d')])
>> simrank(G)
Usted obtendrá
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})})
Vamos a verificar el resultado mediante el cálculo de similitud entre, por ejemplo, el nodo un y el nodo b, denotado por 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,
que es lo mismo que nuestro calculado S (a, b) anterior.
Para más detalles, es posible que quieres descargar el siguiente documento:
G. y J. Jeh Widom. SimRank: una medida de similitud de contexto estructural. En KDD'02 páginas 538-543. ACM Press, 2002.
Esta implementación no es precisa. El algoritmo SimRank se ejecuta en gráficos dirigidos y solo considera los bordes de los nodos predecesores. – yuval
Creo que un gráfico no dirigido puede considerarse como un gráfico "bidireccional". :) – user1036719
@ user1036719 por favor, podría explicar su comentario más. Creo que el punto es que SimRank debe ejecutarse en gráficos dirigidos y, como está implementado, no. No creo que pueda convertir un gráfico dirigido a un gráfico no dirigido y ejecutar el algoritmo correctamente. – Andrew