1. 程式人生 > 其它 >用 GraphScope 像 NetworkX 一樣做圖分析

用 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_nodeadd_nodes_from來新增節點,通過add_edgeadd_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_nodesnumber_of_edges來獲取圖點和邊的數量,通過nodesedges,adjdegree等介面來獲取圖當前的點和邊,以及點的鄰居和度數等資訊。

# 查詢目前圖中點和邊的數目
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_noderemove_nodes_from來刪除圖中的節點,通過remove_edgeremove_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