NetworkX 是 Python 上最常用的圖分析包,GraphScoep 兼容 NetworkX 接口。本文中我們將分享如何用 GraphScope 像 NetworkX 一樣在(大)圖上進行分析。
NetworkX 是什么NetworkX 是一個用 Python 語言開發的圖論與復雜網絡建模工具,它內置了常用的圖與復雜網絡分析算法,提供了一套簡單易用的圖分析接口,可以方便地進行復雜網絡數據分析、仿真建模等工作。NetworkX 的接口設計十分簡潔,對于作為剛進入圖算法領域的小白來說,NetworkX 的接口可以幫助使用者快速建立起對圖數據的感知,并且對于中小型數據集,NetworkX 的接口也是非常好上手的。 但由于 NetworkX 是基于 Python 語言開發,算法的性能并不是它的強項,而且也無法有效地處理工業級別的大規模圖數據?;谶@一背景,GraphScope 提供了一套兼容 NetworkX 的圖分析接口,在能使用像 NetworkX 這樣簡單易用的接口的同時,也能提供高性能的圖分析算法以支持超大規模圖數據的處理。 我們通過一個小例子來簡單介紹一下 NetworkX 的圖分析過程。 # NetworkX 的圖分析過程從圖的構建開始 import networkx
# 初始化一個空的無向圖 G = networkx.Graph()
# 通過 add_edges_from 接口添加邊列表 # 此處添加了兩條邊(1, 2)和(1, 3) G.add_edges_from([(1, 2), (1, 3)])
# 通過 add_node 添加點4 G.add_node(4)
# 接著查看一些圖的信息 # 使用 G.number_of_nodes 查詢圖G目前點的數目 G.number_of_nodes() # 4
# 類似地,G.number_of_edges 可以查詢圖G中 # 邊的數量 G.number_of_edges() # 2
# 通過 G.degree 來查看圖G中每個點的度數 sorted(d for n, d in G.degree()) # [0, 1, 1, 2]
# 最后調用 NetworkX 內置的算法對對圖進行分析 # 調用 connected_components 算法分析圖G的 # 聯通分量 list(networkx.connected_components(G)) # [{1, 2, 3}, {4},]
# 調用 clustering 算法分析圖G的聚類情況 networkx.clustering(G) # {1: 0, 2: 0, 3: 0, 4: 0}
上述例子只是對 NetworkX 做圖分析的一個簡單的介紹,更多 NetworkX 的接口介紹以及詳細的使用說明,內置的算法等可以參考 NetworkX 官方文檔[1]。 用 GraphScope 像 NetworkX 一樣做圖分析NetworkX 官方的 NetworkX tutorial[2] 是一個 NetworkX 接口使用以及圖的入門教程。為了演示 GraphScope 對 NetworkX 的兼容性以及如何使用 GraphScope 的 NetworkX 接口進行圖分析,下面我們使用 GraphScope 來執行教程中的例子。 使用 GraphScope 的 NetworkX 兼容接口,我們只需要簡單地將教程中的import netwokx as nx 替換為import graphscope.nx as nx 即可, 當然這里只是依照 NetworkX 的慣例使用nx 作為別名, 你也可以其他自定義的別名,例如 import graphscope.nx as gs_nx 。 圖的構建GraphScope 支持與 NetworkX 完全相同的載圖語法,示例里我們使用nx.Graph() 來建立一個空的無向圖。 import graphscope.nx as nx
# 我們可以建立一個空的無向圖 G = nx.Graph()
增加節點和邊GraphScope 的圖操作接口也保持了與 NetworkX 的兼容,用戶可以通過add_node 和add_nodes_from 來添加節點,通過add_edge 和add_edges_from 來添加邊。 # 通過 add_node 一次添加一個節點 G.add_node(1)
# 或從任何 iterable 容器中添加節點,如列表 G.add_nodes_from([2, 3])
# 如果容器中是元組的形式,還可以在添加節點的同時, # 添加節點屬性 G.add_nodes_from([(4, {"color": "red"}), (5, {"color": "green"})])
# 對于邊,可以通過 add_edge 的一次添加一條邊 G.add_edge(1, 2) e = (2, 3) G.add_edge(*e)
# 通過 add_edges_from 添加邊列表 G.add_edges_from([(1, 2), (1, 3)])
# 或者通過邊元組的方式,在添加邊的同時, # 添加邊的屬性 G.add_edges_from([(1, 2), (2, 3, {'weight': 3.1415})])
查詢圖的元素GraphScope 支持兼容 NetworkX 的圖查詢接口。用戶可以通過number_of_nodes 和number_of_edges 來獲取圖點和邊的數量,通過nodes , edges ,adj 和degree 等接口來獲取圖當前的點和邊,以及點的鄰居和度數等信息。 # 查詢目前圖中點和邊的數目 G.number_of_nodes() # 5 G.number_of_edges() # 3
# 列出目前圖中的點和邊 list(G.nodes) # [1, 2, 3, 4, 5] list(G.edges) # [(1, 2), (1, 3), (2, 3)]
# 查詢某個點的鄰居 list(G.adj[1]) # [2, 3]
# 查詢某個點的度 G.degree(1) # 2
從圖中刪除元素像 NetworkX 一樣, GraphScope 也可以使用與添加元素相類似的方式從圖中刪除點和邊,對圖進行修改。例如可以通過remove_node 和remove_nodes_from 來刪除圖中的節點,通過remove_edge 和remove_edges_from 來刪除圖中的邊。 # 通過 remove_node 刪除一個點 G.remove_node(5)
# 查看圖 G 現有的點,發現點5已經被刪除了 list(G.nodes) # [1, 2, 3, 4]
# 通過 remove_nodes_from 刪除多個點 G.remove_nodes_from([4, 5])
# 再查看圖 G 現有的點,點4也已經被刪除了 list(G.nodes) # [1, 2, 3]
# 通過 remove_edge 刪除一條邊 G.remove_edge(1, 2)
# 查看圖 G 現有的邊,(1, 2) 這條邊在G中 # 已經被刪除 list(G.edges) # [(1, 3), (2, 3)]
# 通過 remove_edges_from 刪除多條邊 G.remove_edges_from([(1, 3), (2, 3)])
# 查看圖 G 現有的邊,(1, 3), (2, 3) 這兩條邊 # 在 G 中已經不存在了 list(G.edges) # []
# 我們再來看一下現在的點和邊的數目 G.number_of_nodes() # 3
G.number_of_edges() # 0
圖分析GraphScope 可以通過兼容 NetworkX 的接口來對圖進行各種算法的分析,示例里我們構建了一個簡單圖,然后分別使用connected_components 分析圖的聯通分量,使用clustering 來得到圖中每個點的聚類系數,以及使用all_pairs_shortest_path 來獲取節點兩兩之間的最短路徑。 # 首先構建圖 G = nx.Graph() G.add_edges_from([(1, 2), (1, 3)]) G.add_node(4)
# 通過 connected_components 算法找出 # 圖中的聯通分量 list(nx.connected_components(G)) # [{4}, {1, 2, 3},]
# 通過 clustering 算法計算每個點的聚類系數 nx.clustering(G) # {4: 0.0, 1: 0.0, 2: 0.0, 3: 0.0}
# 計算圖中節點兩兩之間的最短路徑 sp = dict(nx.all_pairs_shortest_path(G))
# 查看節點3與其他節點的最短路徑 sp[3] # {3: [3], 1: [3, 1], 2: [3, 1, 2]}
圖的簡單繪制同 NetworkX 一樣,GraphScope 支持通過draw 將圖進行簡單地繪制出來。 (依賴matplotlib 的繪圖功能,如果未安裝,需要先通過 pip install atplotlib 安裝) import graphscope.nx as nx # 創建一個5個點的 star graph G = nx.star_graph(5) # 使用 nx.draw 繪制圖 nx.draw(G, with_labels=True)
 通過一些簡單的例子,我們展示了 GraphScope 對于 NetworkX 接口的兼容性和一些圖操作/分析接口的使用。更詳細的使用可以參考 GraphScope 文檔[3]。 GraphScope 相比 NetworkX 算法性能有著數量級的提升GraphScope 支持了部分 NetworkX 內置的圖算法,我們可以通過 NetworkX 的調用算法的方式來調用這些算法。下面我們通過一個簡單的實驗來看一下 GraphScope 對比 NetworkX 在算法性能上到底提升多少。 這個實驗使用來自 SNAP 的 twitter[4] 圖數據,測試算法是 NetworkX 內置的 Clustering[5] 算法。實驗所用的機器配置為8核CPU, 16G內存。 我們首先準備下數據,使用 wget 將數據集下載到本地 wget https://raw./GraphScope/gstest/master/twitter.e ${HOME}/twitter.e
接著我們分別使用 GraphScope 和 NetworkX 載入 snap-twitter 數據 import os import graphscope.nx as gs_nx import networkx as nx
# 使用 NetworkX 載入 snap-twitter 圖數據 g1 = nx.read_edgelist( os.path.expandvars('$HOME/twitter.e'), nodetype=int, data=False, create_using=nx.Graph ) type(g1) # networkx.classes.graph.Graph
# 使用 GraphScope 載入 snap-twitter 圖數據 g2 = gs_nx.read_edgelist( os.path.expandvars('$HOME/twitter.e'), nodetype=int, data=False, create_using=gs_nx.Graph ) type(g2) # graphscope.nx.classes.graph.Graph
我們使用 Clustering 算法來對圖進行聚類分析,來看一下 GraphScope 對比 NetworkX 在算法性能上有多少提升 %%time # 使用 GraphScope 計算圖中每個點的聚類系數 ret_gs = gs_nx.clustering(g2) # CPU times: user 213 ms, sys: 163 ms, total: 376 ms # Wall time: 2.9 s
%%time # 使用 NetworkX 計算圖中每個點的聚類系數 ret_nx = nx.clustering(g1) # CPU times: user 54.8 s, sys: 0 ns, total: 54.8 s # Wall time: 54.8 s
# 對比下兩者的結果是否一致 ret_gs == ret_nx # True
從實驗結果我們可以看到,GraphScope 在兼容 NetworkX 接口的同時,內置的算法對比 NetworkX 可以達到幾個數量級的性能提升。GraphScope 在提供兼容 NetworkX 簡單易用的接口的同時,也能提供非常高效的算法分析。 結語本文介紹了如何讓 GraphScope 使用 NetworkX 風格的方式對圖數據進行操作和分析,同時,本文也通過在snap-twitter 圖數據上聚類算法分析的對比來展示了 GraphScope 在兼容 NetworkX 接口的同時,提供了高效的算法分析能力。 在后續的文章中,我們將會通過 benchmark 的方式更細致地對比 GraphScope 與 NetworkX 在圖操作,圖查詢和圖分析上的一些性能比較,以及使用 GraphScope 來執行一些 github 社區中基于 NetworkX 的有趣的數據分析項目。 本文中涉及的代碼都已經在 GraphScope Playground 中,感興趣的讀者可以直接點擊下方的 閱讀原文,進入 Playground 試用這些代碼。
參考資料[1]NetworkX 官方文檔: https:///documentation/stable/index.html [2]NetworkX tutorial: https:///documentation/stable/tutorial.html [3]GraphScope 文檔: https:///docs/reference/networkx/index.html [4]Snap-twitter: https://snap./data/ego-Twitter.html [5]Clustering 算法: https:///documentation/stable/reference/algorithms/generated/networkx.algorithms.cluster.clustering.html#networkx.algorithms.cluster.clustering
|