首页 文章

Networkx从未完成计算2 mil节点的中介中心性

提问于
浏览
8

我有一个简单的Twitter用户图,有大约200万个节点和500万个边 . 我正试图玩Centrality . 但是,计算需要很长时间(超过一小时) . 我不认为我的图表超大,所以我猜我的代码可能有问题 .

这是我的代码 .

%matplotlib inline
import pymongo
import networkx as nx
import time
import itertools

from multiprocessing import Pool
from pymongo import MongoClient

from sweepy.get_config import get_config

config = get_config()

MONGO_URL = config.get('MONGO_URL')
MONGO_PORT = config.get('MONGO_PORT')
MONGO_USERNAME = config.get('MONGO_USERNAME')
MONGO_PASSWORD = config.get('MONGO_PASSWORD')

client = MongoClient(MONGO_URL, int(MONGO_PORT))

db = client.tweets
db.authenticate(MONGO_USERNAME, MONGO_PASSWORD)

users = db.users
graph  = nx.DiGraph()


for user in users.find():
    graph.add_node(user['id_str'])
    for friend_id in user['friends_ids']:
        if not friend_id in graph:
            graph.add_node(friend_id)
        graph.add_edge(user['id_str'], friend_id)

数据在MongoDB中 . 这是数据样本 .

{
    "_id" : ObjectId("55e1e425dd232e5962bdfbdf"),
    "id_str" : "246483486",
    ...
    "friends_ids" : [ 
         // a bunch of ids
    ]
}

我尝试使用中间性中心性并行加速,但它仍然超级慢 . https://networkx.github.io/documentation/latest/examples/advanced/parallel_betweenness.html

"""
Example of parallel implementation of betweenness centrality using the
multiprocessing module from Python Standard Library.

The function betweenness centrality accepts a bunch of nodes and computes
the contribution of those nodes to the betweenness centrality of the whole
network. Here we divide the network in chunks of nodes and we compute their
contribution to the betweenness centrality of the whole network.
"""
def chunks(l, n):
    """Divide a list of nodes `l` in `n` chunks"""
    l_c = iter(l)
    while 1:
        x = tuple(itertools.islice(l_c, n))
        if not x:
            return
        yield x


def _betmap(G_normalized_weight_sources_tuple):
    """Pool for multiprocess only accepts functions with one argument.
    This function uses a tuple as its only argument. We use a named tuple for
    python 3 compatibility, and then unpack it when we send it to
    `betweenness_centrality_source`
    """
    return nx.betweenness_centrality_source(*G_normalized_weight_sources_tuple)


def betweenness_centrality_parallel(G, processes=None):
    """Parallel betweenness centrality  function"""
    p = Pool(processes=processes)
    node_divisor = len(p._pool)*4
    node_chunks = list(chunks(G.nodes(), int(G.order()/node_divisor)))
    num_chunks = len(node_chunks)
    bt_sc = p.map(_betmap,
                  zip([G]*num_chunks,
                      [True]*num_chunks,
                      [None]*num_chunks,
                      node_chunks))

    # Reduce the partial solutions
    bt_c = bt_sc[0]
    for bt in bt_sc[1:]:
        for n in bt:
            bt_c[n] += bt[n]
    return bt_c



print("Computing betweenness centrality for:")
print(nx.info(graph))
start = time.time()
bt = betweenness_centrality_parallel(graph, 2)
print("\t\tTime: %.4F" % (time.time()-start))
print("\t\tBetweenness centrality for node 0: %.5f" % (bt[0]))

从Mongodb到networkx的导入过程相对较快,不到一分钟 .

1 回答

  • 18

    TL / DR:中介中心性是一个非常缓慢的计算,因此您可能希望通过考虑 myk 节点的子集来使用近似度量,其中 myk 的某个数字远小于网络中的节点数,但大到足以在统计上有意义的(NetworkX有一个选项: betweenness_centrality(G, k=myk) .


    我需要很长时间 . 中介中心性是一个缓慢的计算 . networkx使用的算法是 O(VE) ,其中 V 是顶点数, E 是边数 . 在你的情况下 VE = 10^13 . 我希望导入图表需要 O(V+E) 时间,所以如果花费的时间足够长,你可以告诉它不是瞬时的,那么_518110将会很痛苦 .

    如果具有1%节点和1%边缘的减少网络(因此20,000个节点和50,000个边缘)将花费时间X,那么您需要的计算需要10000X . 如果X是一秒,那么新计算接近3小时,我认为这是非常乐观的(参见下面的测试) . 因此,在您确定代码出现问题之前,请先在较小的网络上运行,然后估算网络的运行时间 .

    一个很好的选择是使用近似测量 . 标准中介度量度量考虑每对节点以及它们之间的路径 . Networkx提供了一种替代方案,它使用只有 k 节点的随机样本,然后找到这些节点与网络中所有其他节点之间的最短路径 . 我认为这应该会在 O(kE) 时间内提供加速

    所以你要用的是

    betweenness_centrality(G, k=k)
    

    如果你想对你的结果有多精确的界限,你可以用少量的 k 进行多次调用,确保它们相对接近,然后取平均值 .


    这是我对运行时间的一些快速测试,随机图(V,E)=(20,50); (200500);和(2000,5000)

    import time
    for n in [20,200,2000]:
        G=nx.fast_gnp_random_graph(n, 5./n)
        current_time = time.time()
        a=nx.betweenness_centrality(G)
        print time.time()-current_time
    
    >0.00247192382812
    >0.133368968964
    >15.5196769238
    

    所以在我的电脑上处理一个比你大0.1%的网络需要15秒 . Build 与您相同大小的网络大约需要1500万秒 . 这是1.5 * 10 ^ 7秒,这是pi * 10 ^ 7秒的一半 . 由于pi * 10 ^ 7秒是一年中非常接近的秒数,这将花费我的电脑大约6个月 .

    因此,您需要使用近似算法运行 .

相关问题