You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Networkx处理超14万节点二分图投影时内存不足求解决方案

大规模二分图投影内存溢出的解决办法

我尝试使用NetworkX的projected_graph方法对一个包含14万+节点的二分图(B)进行投影,但受内存限制,程序持续崩溃。我曾尝试通过稀疏矩阵乘法计算邻接矩阵,但由于矩阵稀疏度不足,该方法也未能奏效。恳请各位提供解决方案。

原始代码:

import networkx as nx
from networkx.algorithms import bipartite

B.add_nodes_from(inmates_list, bipartite=0)
B.add_nodes_from(cells_list, bipartite=1)

inmates = set(n for n,d in B.nodes(data=True) if d['bipartite']==0)
cells = set(B) - inmates
G = bipartite.projected_graph(B, inmates)

方案1:迭代式构建投影图(最低内存开销)

不用一次性生成完整投影图,而是遍历每个cell,把共享该cell的inmates两两连边。这种方式不需要存储大矩阵,边遍历边构建,内存占用大幅降低。

代码示例:

import networkx as nx

# 初始化投影图,先加入所有inmates节点
G = nx.Graph()
G.add_nodes_from(inmates_list)

# 遍历每个cell,处理关联的inmates
for cell in cells_list:
    connected_inmates = list(B.neighbors(cell))
    # 生成两两组合并添加边
    for i in range(len(connected_inmates)):
        for j in range(i+1, len(connected_inmates)):
            u, v = connected_inmates[i], connected_inmates[j]
            # 若需要统计共同cell数,可累加权重
            if G.has_edge(u, v):
                G[u][v]['shared_cells'] = G[u][v].get('shared_cells', 0) + 1
            else:
                G.add_edge(u, v, shared_cells=1)

方案2:优化NetworkX原生投影

NetworkX的projected_graph默认会加载整个图到内存,可先清理节点冗余属性,减少内存占用后再执行投影:

# 清理节点无关属性,只保留二分标记
for node in B.nodes:
    for key in list(B.nodes[node].keys()):
        if key != 'bipartite':
            del B.nodes[node][key]

# 直接投影,避免重复计算节点集合
inmates = set(inmates_list)
G = bipartite.projected_graph(B, inmates)

方案3:换用更高效的图处理库

如果NetworkX的内存效率仍不满足需求,试试专门针对大规模图优化的库:

  • igraph:内存占用远低于NetworkX,投影速度更快
    示例代码:
    import igraph as ig
    
    # 构建二分图映射:先将节点转成索引
    inmate_idx = {n: i for i, n in enumerate(inmates_list)}
    cell_idx = {n: i + len(inmates_list) for i, n in enumerate(cells_list)}
    
    # 创建igraph对象,标记二分类型
    g = ig.Graph()
    g.add_vertices(len(inmate_idx) + len(cell_idx))
    g.vs['type'] = [0]*len(inmate_idx) + [1]*len(cell_idx)
    
    # 添加所有边
    edges = [(inmate_idx[u], cell_idx[v]) for u, v in B.edges()]
    g.add_edges(edges)
    
    # 投影到inmates节点(type=0)
    projected_graph, _ = g.bipartite_projection(types=g.vs['type'])
    
  • graph-tool:内存效率更高,但安装门槛略高,适合超大规模图处理

方案4:分块处理投影

如果整个图还是太大,可将cells分批次处理,分别投影后合并结果:

from itertools import islice

# 定义分块工具函数
def split_in_chunks(iterable, chunk_size):
    iterator = iter(iterable)
    while chunk := list(islice(iterator, chunk_size)):
        yield chunk

# 初始化总投影图
G = nx.Graph()
G.add_nodes_from(inmates_list)

# 按每1000个cell为一块处理
for cell_chunk in split_in_chunks(cells_list, 1000):
    # 构建当前块的子二分图
    sub_bipartite = nx.Graph()
    sub_bipartite.add_nodes_from(cell_chunk, bipartite=1)
    # 添加该块cell对应的所有边
    for cell in cell_chunk:
        sub_bipartite.add_edges_from((cell, n) for n in B.neighbors(cell))
    # 生成子投影图
    sub_proj = bipartite.projected_graph(sub_bipartite, inmates & set(sub_bipartite.nodes()))
    # 合并到总图,累加共享cell数
    for u, v in sub_proj.edges():
        if G.has_edge(u, v):
            G[u][v]['shared_cells'] += 1
        else:
            G.add_edge(u, v, shared_cells=1)

内容的提问来源于stack exchange,提问作者user2146697

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:48:27