Using networkx to calculate eigenvector centrality
Asked Answered
H

1

10

I'm trying to use networkx to calculate the eigenvector centrality of my graph:

import networkx as nx
import pandas as pd
import numpy as np

a = nx.eigenvector_centrality(my_graph)

But I get the error:

NetworkXError: eigenvector_centrality():
power iteration failed to converge in %d iterations."%(i+1))

What is the problem with my graph?

graph visualization

Henrieta answered 4/4, 2017 at 13:31 Comment(1)
Maybe your graph is empty which indicates no edge and vertex has been created. Check the input of the graph to see if it follows the right format or if it is empy.Adenoidectomy
M
25

TL/DR: try nx.eigenvector_centrality_numpy.


Here's what's going on: nx.eigenvector_centrality relies on power iteration. The actions it takes are equivalent to repeatedly multiplying a vector by the same matrix (and then normalizing the result). This usually converges to the largest eigenvector. However, it fails when there are multiple eigenvalues with the same (largest) magnitude.

Your graph is a star graph. There are multiple "largest" eigenvalues for a star graph. In the case of a star with just two "peripheral nodes" you can easily check that sqrt(2) and -sqrt(2) are both eigenvalues. More generally sqrt(N) and -sqrt(N) are both eigenvalues, and the other eigenvalues have smaller magnitude. I believe that for any bipartite network, this will happen and the standard algorithm will fail.

The mathematical reason is that after n rounds of iteration, the solution looks like the sum of c_i lambda_i^n v_i/K_n where c_i is a constant that depends on the initial guess, lambda_i is the i-th eigenvalue, v_i is its eigenvector and K is a normalization factor (applied to all terms in the sum). When there is a dominant eigenvalue, lambda_i^n/K_n goes to a nonzero constant for the dominant eigenvalue and 0 for the others.

However in your case, you have two equally large eigenvalues, one is positive (lambda_1) and the other is negative (lambda_2=-lambda_1). The contribution of the smaller eigenvalues still goes to zero. But you're left with (c_1 lambda_1^n v_1 + c_2 lambda_2^n v_2)/K_n. Using lambda_2=-lambda_1 you are left with lambda_1^n(c_1 v_1+(-1)^n c_2v_2)/K_n. Then K_n-> lambda_1^n and this "converges" to c_1 v_1 + (-1)^n c_2 v_2. However, each time you iterate, you go from adding some multiple of v_2 to subtracting that multiple, so it doesn't really converge.

So the simple eigenvalue_centrality that networkx uses won't work. You can instead use nx.eigenvector_centrality_numpy so that numpy is used. That will get you v_1.


Note: With a quick look at the documentation, I'm not 100% positive that the numpy algorithm is guaranteed to be the largest (positive) eigenvalue. It uses a numpy algorithm to find an eigenvector, but I don't see in the documentation of that a guarantee that it is the dominant eigenvector. Most algorithms for finding a single eigenvector will result in the dominant eigenvector, so you're probably alright.

We can add a check to it:

  • as long as nx.eigenvector_centrality_numpy returns all positive values, the Perron-Frobenius theorem guarantees that this corresponds to the largest eigenvalue.
  • If some are zero, it gets a bit more tricky to be sure,
  • and if some are negative than it is not the dominant eigenvector.
Maw answered 5/4, 2017 at 18:15 Comment(3)
3 years later... I've had weird experiences with eigenvector_centrality_numpy. In a small example I have, it returns some values around 1E-11 and one negative value, whereas eigenvector_centrality returns more sensible centrality values (based on my expectations) and all are positive (the minimum is around 1E-3).Corbeil
If you can post the example in a new question, I may be able to look at it (my time is incredibly limited at the moment since my job is studying infectious disease control). It sounds like it's not finding the right eigenvalue (if some values are negative).Maw
Thanks! Here it is.Corbeil

© 2022 - 2024 — McMap. All rights reserved.