neo4j python 算法_图论与图学习(二):图算法
選自towardsdatascience
作者:Ma?l Fabien機器之心編譯參與:熊貓圖(graph)近來正逐漸變成機器學習的一大核心領域,比如你可以通過預測潛在的連接來理解社交網絡的結構、檢測欺詐、理解汽車租賃服務的消費者行為或進行實時推薦。近日,數據科學家 Ma?l Fabien 在其博客上發布了涉及圖論、圖算法和圖學習的系列文章《圖論與圖學習》。
本文是其中第二篇,介紹了圖算法。更多文章和對應代碼可訪問:https://github.com/maelfabien/Machine_Learning_Tutorials本文涵蓋以下主題:主要的圖算法
示意圖和用例
Python 示例
import?random
import?networkx?as?nx
from?IPython.display?import?Image
import?matplotlib.pyplot?as?plt后文會使用 networkx 最新的 2.0 版本。networkx 是一個用于復雜網絡的結構、動態和功能的創建、操作和研究的 Python 軟件包。我會盡量以實用為目標,努力闡釋每個概念。前一篇文章介紹了圖的主要種類以及描述一個圖的基本特性。現在我們更加詳細地介紹圖分析/算法以及分析圖的不同方式。為了理解上下文,這里給出一些圖算法的用例:
實時欺詐檢測
實時推薦
精簡法規遵從性
復雜網絡的管理和監控
身份和訪問管理
社交應用/功能
…
Pathfinding(尋路):根據可用性和質量等條件確定最優路徑。我們也將搜索算法包含在這一類別中。這可用于確定最快路由或流量路由。
Centrality(中心性):確定網絡中節點的重要性。這可用于識別社交網絡中有影響力的人或識別網絡中潛在的攻擊目標。
Community detection(社群檢測):評估群體聚類的方式。這可用于劃分客戶或檢測欺詐等。
尋路算法是通過最小化跳(hop)的數量來尋找兩個節點之間的最短路徑。
搜索算法不是給出最短路徑,而是根據圖的相鄰情況或深度來探索圖。這可用于信息檢索。
寬度優先搜索(BFS):首先探索每個節點的相鄰節點,然后探索相鄰節點的相鄰節點……
深度優先搜索(DFS):會嘗試盡可能地深入一條路徑,如有可能便訪問新的相鄰節點。
將圖中所有節點標記為未訪問。創建一個所有未訪問節點的集合,稱為未訪問集。
為每個節點分配一個暫定的距離值:將我們的初始節點的該值設置為零,將其它所有節點的該值設置為無窮。將初始起始節點設置為當前節點。
對于當前節點,考察其所有未被訪問過的相鄰節點并計算通過當前節點的暫定距離。比較新計算出的暫定距離與當前分配的值,配之以其中更小的值。舉個例子,如果當前節點 A 標記的距離為 6,將其與相鄰節點 B 連接的邊的長度為 2,則通過 A 到達 B 的距離為 6+2=8。如果 B 之前被標記的距離大于 8,則將其改為 8。否則,保持其當前的值。
當我們考察完當前節點的所有未訪問節點時,將當前節點標記為已訪問,并將其移出未訪問集。已訪問節點不會再次進行檢查。
如果目標節點已被標記為已訪問(當規劃兩個特定節點之間的路由時)或未訪問集中節點之間的最小暫定距離為無窮時(當規劃一次完整的遍歷時;當初始節點與剩余的未訪問節點之間沒有連接時才會出現這種情況),那么就停止操作。算法結束。
否則,選擇標記有最小暫定距離的未訪問節點,將其設置為新的「當前節點」,然后回到步驟 3。
nx.shortest_path(G_karate)這會返回圖中每個節點之間的最小路徑的列表:{0:?{0:?[0],
????1:?[0,?1],
????2:?[0,?2],
????...b. 單源最短路徑單源最短路徑(Single Source Shortest Path/SSSP)是找到給定節點與圖中其它所有節點之間的最短路徑。這常用于 IP 網絡的路由協議。c. 所有配對最短路徑所有配對最短路徑(All Pairs Shortest Path / APSP)算法是找到所有節點對之間的最短路徑。盡管能夠提供相近的結果,但這比為每個節點對調用單源最短路徑算法更快。該算法通常可用于確定交通網格的不同分區的流量負載。#?Returns?shortest?path?length?between?each?node
list(nx.all_pairs_shortest_path_length(G_karate))這會返回:[(0,
????{0:?0,
????1:?1,
????2:?1,
????3:?1,
????4:?1,
????...d. 最小權重生成樹最小權重生成樹(minimum spanning tree)是圖(一個樹)的一個子圖,其用權重和最小的邊連接了圖中的所有節點。最小生成樹應該用于無向圖。from?networkx.algorithms?import?tree
mst?=?tree.minimum_spanning_edges(G_karate,?algorithm='prim',?data=False)
edgelist?=?list(mst)
sorted(edgelist)這會返回:[(0,?1),
(0,?2),
(0,?3),
(0,?4),
(0,?5),
(0,?6),
...二 社群檢測社群檢測是根據給定的質量指標將節點劃分為多個分組。這通常可用于識別社交社群、客戶行為或網頁主題。社區是指一組相連節點的集合。但是,目前關于社群還沒有廣泛公認的定義,只是社群內的節點應該要密集地相連。社群Girvan Newman 算法是一個用于發現社群的常用算法。其通過逐步移除網絡內的邊來定義社區。我們將居間性稱為「邊居間性(edge betweenness)」。這是一個正比于穿過該邊的節點對之間最短路徑的數量的值。該算法的步驟如下:
計算網絡中所有已有邊的居間性。
移除居間性最高的邊。
移除該邊后,重新計算所有邊的居間性。
重復步驟 2 和 3,直到不再剩余邊。
comp?=?community.girvan_newman(G_karate)for?communities?in?itertools.islice(comp,?k):
????print(tuple(sorted(c)?for?c?in?communities))這會得到一個屬于每個社群的節點的列表(k=1 的意思是我們期望得到 2 個社群):([0,?1,?3,?4,?5,?6,?7,?10,?11,?12,?13,?16,?17,?19,?21],?[2,?8,?9,?14,?15,?18,?20,?22,?23,?24,?25,?26,?27,?28,?29,?30,?31,?32,?33])如上給出的那樣,這個方法實在沒法擴展。由于這個原因,Louvain 等方法已被開發出來。但是,如果要運行大規模的圖,這些方法需要很長的時間。3. Louvain 模塊性在定義 Louvain 方法之前,需要介紹一下模塊性(modularity)的概念。模塊性是一個度量,衡量的是分組被劃分為聚類的程度:模塊性Louvain 方法的偽代碼如下:
首先為每個節點分配一個社群
交替執行接下來的兩個步驟,直到收斂
創建一個帶有相鄰節點的新社群,以最大化模塊性
創建一個新的加權的圖。之前步驟的社群變成圖的節點。
partition?=?community.best_partition(G_karate)pos?=?nx.spring_layout(G_karate)
plt.figure(figsize=(8,?8))
plt.axis('off')
nx.draw_networkx_nodes(G_karate,?pos,?node_size=600,?cmap=plt.cm.RdYlBu,?node_color=list(partition.values()))
nx.draw_networkx_edges(G_karate,?pos,?alpha=0.3)
plt.show(G_karate)使用 Louvain 對空手道圖執行的最佳劃分4. 強互連的組分強互連的組分(Strongly Connected Components /SCC)算法能找到有向圖中的互連節點的分組。注意,在同一個分組中,每個節點都必須從任意其它節點從兩個方向都到達。這通常用在圖分析過程的早期階段,能讓我們了解圖構建的方式。舉個例子,這能讓我們探索財務報表數據,了解誰擁有什么公司的股份。5. 弱互連的組分(并查集)弱互連的組分(Weakly Connected Components),也稱為并查集(Union Find)算法,能找到有向圖中的互連節點的集合,在同一個集合中,每個節點都可從任意其它節點到達。這只需要節點對之間在一個方向上存在一條路徑即可,而 SCC 則需要兩個方向都存在路徑。和 SCC 一樣,并查集通常用在分析的早期階段,以理解圖的結構。并查集是一個預處理步驟,為了理解圖的結構,在任何算法之前都是必需的。我們可以使用下面的方法測試相連的有向圖:nx.is_weakly_connected(G)
nx.is_strongly_connected(G)或使用下面的方法測試無向圖:nx.is_connected(G_karate)這會返回一個布爾值。一定要看看 networkx 文檔中有關連接性實現的問題:https://networkx.github.io/documentation/stable/reference/algorithms/component.html6. 分層聚類在分層聚類(hierarchical clustering)中,我們構建聚類的層次結構。我們用樹狀圖的形式表示聚類。樹狀圖其思想是以不同的規模分析社群結構。我們通常自下而上構建樹狀圖。我們從每個節點一個聚類開始,然后合并兩個「最近」的節點。但我們如何衡量聚類是否相近呢?我們使用相似度距離。令 d(i,j) 為 i 和 j 之間的最短路徑的長度。相似度距離要得到最大連接,在每個步驟,被最短距離分開的兩個聚類被組合到一起。相似度距離可用以下示意圖闡釋:連接方式回到我們的空手道示例。在應用分層聚類之前,我們需要定義每個節點之間的距離矩陣。pcc_longueurs=list(nx.all_pairs_shortest_path_length(G_karate))
distances=np.zeros((n,n))#?distances[i,?j]?is?the?length?of?the?shortest?path?between?i?and?j
for?i?in?range(n):
????for?j?in?range(n):
????????distances[i,?j]?=?pcc_longueurs[i][1][j]現在,我們將使用 sklearn 的 AgglomerativeClustering 函數來確定分層聚類。from?sklearn.cluster?import?AgglomerativeClusteringclustering?=?AgglomerativeClustering(n_clusters=2,linkage='average',affinity='precomputed').fit_predict(distances)最后,根據聚類結果,用不同顏色繪出所得到的圖:nx.draw(G_karate,??node_color?=?clustering)分層聚類7. 聚類系數聚類系數衡量的是兩個節點傾向于聚類到一起的程度。局部聚類系數是以節點 i 為中心的三角形的數量與以節點 i 為中心的三節點的數量的比。某種程度而言,這衡量的是節點 i 與其相鄰節點接近完備圖(complete graph)的程度。聚類系數我通過以下圖演示了聚類系數的計算:聚類系數全局聚類系數衡量的是圖中三角形(局部聚類)的密度:全局聚類系數上面的圖的全局聚類系數為:對于 Erdos-Rényi 隨機圖,E[Clustering Coefficient]=E[Ci]=p,其中 p 是前一篇文章中定義的概率。對于 Baràbasi-Albert 隨機圖,全局聚類系數根據節點的數量遵循冪律。度為 k 的節點的平均聚類系數正比于 k 的倒數:度較低的節點連接的是它們社群中的其它節點。度較高的節點連接的是其它社群的節點。對于一個給定的圖,在 networkx 中,聚類系數很容易算出。首先,我們來計算局部聚類系數:#?List?of?local?clustering?coefficients
list(nx.clustering(G_barabasi).values())這會得到類似下面的結果:0.13636363636363635,
0.2,
0.07602339181286549,
0.04843304843304843,
0.09,
0.055384615384615386,
0.07017543859649122,
...然后平均這些結果,得到該圖的全局聚類稀疏:#?Global?clustering?coefficient
np.mean(list(nx.clustering(G_barabasi).values()))這會得到:0.0965577637155059三 中心度算法中心度(Centrality)衡量的是節點的重要程度。這并非一個明晰的定義,但如果我們想要確定重要的網頁、交通網絡中的瓶頸……,那這就會很有用。游走(walk)是可以多次經過同一個節點的路徑。根據所考慮的游走類型和統計它們的方式,中心度度量也會各有不同。1. PageRank 算法PageRank 是根據所連接的相鄰節點,然后再根據它們各自的相鄰節點估計當前節點的重要性。盡管是谷歌讓這種算法流行起來的,但這種方法能夠用于檢測任何網絡中的高影響力節點。比如可用在社交網絡上進行推薦。PageRank 要么是通過在相鄰節點上迭代地分配節點的秩(原本是基于度)來計算,要么是通過隨機遍歷圖并統計每次游走期間到達每個節點的頻率來計算。Neo4J 對 PageRank 算法的總結PageRank 通常是在有向圖上計算,但也可通過將有向圖中的每條邊轉換成兩條邊而在無向圖上執行。舉個例子,空手道圖的 PageRank 可以這樣獲得:nx.pagerank(G_karate,?alpha=0.9)其中 alpha 是阻尼參數(默認為 0.85)。這應該能返回一個排名列表:{0:?0.09923208031303203,
?1:?0.0543403155825792,
?2:?0.05919704684187155,
?3:?0.036612460562853694,
...2. 度中心度度中心度(Degree Centrality)統計的是終止于節點 i 的長度為 1 的游走的數量。這能夠衡量傳入和傳出關系。這能通過 C(Xi)=di 給出。度中心度可用于識別社交網絡中最有影響力的人。c_degree?=?nx.degree_centrality(G_karate)
c_degree?=?list(c_degree.values())3. 特征向量中心度特征向量中心度(Eigenvector Centrality)是終止于節點 i 的長度為無窮的游走的數量。這能讓有很好連接相鄰節點的節點有更高的重要度。特征向量中心度c_eigenvector?=?nx.eigenvector_centrality(G_karate)
c_eigenvector?=?list(c_eigenvector.values())4. 接近度中心度接近度中心度(Closeness Centrality)檢測的是可以在圖中有效傳播信息的節點。這可用于識別假新聞賬戶或恐怖分子,以便隔離能向圖中其它部分傳播信息的個體。接近度中心度反比于到其它節點的最短路徑長度的總和。c_closeness?=?nx.closeness_centrality(G_karate)
c_closeness?=?list(c_closeness.values())5. 居間性中心度居間性中心度(Betweenness Centrality)檢測的是節點在圖中的信息流上所具有的影響量。這通常可用于發現用作從圖的一部分到另一部分的橋的節點,比如用在電信網絡的數據包傳遞處理器或假新聞傳播分析中。其中:
σ_jk 是 j 和 k 之間的最短路徑的數量
σ_jk(i) 是 j 和 k 之間的經過 i 的最短路徑的數量
c_betweenness?=?list(c_betweenness.values())Python 中實現依賴于 networkx 的內置函數:#?Plot?the?centrality?of?the?nodes
plt.figure(figsize=(18,?12))#?Degree?Centrality
f,?axarr?=?plt.subplots(2,?2,?num=1)
plt.sca(axarr[0,0])
nx.draw(G_karate,?cmap?=?plt.get_cmap('inferno'),?node_color?=?c_degree,?node_size=300,?pos=pos,?with_labels=True)
axarr[0,0].set_title('Degree?Centrality',?size=16)#?Eigenvalue?Centrality
plt.sca(axarr[0,1])
nx.draw(G_karate,?cmap?=?plt.get_cmap('inferno'),?node_color?=?c_eigenvector,?node_size=300,?pos=pos,?with_labels=True)
axarr[0,1].set_title('Eigenvalue?Centrality',?size=16)#?Proximity?Centrality
plt.sca(axarr[1,0])
nx.draw(G_karate,?cmap?=?plt.get_cmap('inferno'),?node_color?=?c_closeness,?node_size=300,?pos=pos,?with_labels=True)
axarr[1,0].set_title('Proximity?Centrality',?size=16)#?Betweenness?Centrality
plt.sca(axarr[1,1])
nx.draw(G_karate,?cmap?=?plt.get_cmap('inferno'),?node_color?=?c_betweenness,?node_size=300,?pos=pos,?with_labels=True)
axarr[1,1].set_title('Betweenness?Centrality',?size=16)不同的中心度度量可以觀察到,不同的中心度度量關注的節點也不同。比如,居間性中心度得到的結果與其它方法的結果非常不同,因為它們衡量的不是同一個指標。四 總結現在我們已經介紹了圖的基礎知識、圖的主要類型、不同的圖算法和它們使用 networkx 的 Python 實現。下一篇文章我們將介紹圖學習,這能提供預測圖中節點和邊的方法,從而處理缺失值或預測新的關系。擴展閱讀:
Neo4j 的圖算法全面指南,Mark Needham & Amy E. Hodler:https://go.neo4j.com/rs/710-RRC-335/images/Comprehensive-Guide-to-Graph-Algorithms-in-Neo4j-ebook-EN-US.pdf
Networkx 文檔:https://networkx.github.io/documentation/stable/
原文鏈接:https://towardsdatascience.com/graph-algorithms-part-2-dce0b2734a1d
本文為機器之心編譯,轉載請聯系本公眾號獲得授權。
?------------------------------------------------
加入機器之心(全職記者 / 實習生):hr@jiqizhixin.com
投稿或尋求報道:content@jiqizhixin.com
廣告 & 商務合作:bd@jiqizhixin.com
總結
以上是生活随笔為你收集整理的neo4j python 算法_图论与图学习(二):图算法的全部內容,希望文章能夠幫你解決所遇到的問題。