用 GraphScope 像 NetworkX 一樣做圖分析
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.githubusercontent.com/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://networkx.org/documentation/stable/index.html
[2]NetworkX tutorial: https://networkx.org/documentation/stable/tutorial.html
[3]GraphScope 文件: https://graphscope.io/docs/reference/networkx/index.html
[4]Snap-twitter: https://snap.stanford.edu/data/ego-Twitter.html
[5]Clustering 演算法: https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.cluster.clustering.html#networkx.algorithms.cluster.clustering