⑴ 基於社區發現演算法和圖分析Neo4j解讀《權力的游戲》下篇
其中的分析和可視化是用Gephi做的,Gephi是非常流行的圖分析工具。但作者覺得使用Neo4j來實現更有趣。
節點中心度
節點中心度給出網路中節點的重要性的相對度量。有許多不同的方式來度量中心度,每種方式都代表不同類型的「重要性」。
度中心性(Degree Centrality)
度中心性是最簡單度量,即為某個節點在網路中的聯結數。在《權力的游戲》的圖中,某個角色的度中心性是指該角色接觸的其他角色數。作者使用Cypher計算度中心性:
MATCH (c:Character)-[:INTERACTS]- RETURN c.name AS character, count(*) AS degree ORDER BY degree DESC
character
degree
Tyrion
36
Jon
26
Sansa
26
Robb
25
Jaime
24
Tywin
22
Cersei
20
Arya
19
Joffrey
18
Robert
18
從上面可以發現,在《權力的游戲》網路中提利昂·蘭尼斯特(Tyrion)和最多的角色有接觸。鑒於他的心計,我們覺得這是有道理的。
加權度中心性(Weighted Degree Centrality)
作者存儲一對角色接觸的次數作為 INTERACTS 關系的 weight 屬性。對該角色的 INTERACTS 關系的所有 weight 相加得到加權度中心性。作者使用Cypher計算所有角色的這個度量:
MATCH (c:Character)-[r:INTERACTS]- RETURN c.name AS character, sum(r.weight) AS weightedDegree ORDER BY weightedDegree DESC
character
weightedDegree
Tyrion
551
Jon
442
Sansa
383
Jaime
372
Bran
344
Robb
342
Samwell
282
Arya
269
Joffrey
255
Daenerys
232
介數中心性(Betweenness Centrality)
介數中心性:在網路中,一個節點的介數中心性是指其它兩個節點的所有最短路徑都經過這個節點,則這些所有最短路徑數即為此節點的介數中心性。介數中心性是一種重要的度量,因為它可以鑒別出網路中的「信息中間人」或者網路聚類後的聯結點。
圖6中紅色節點是具有高的介數中心性,網路聚類的聯結點。
為了計算介數中心性,作者使用Neo4j 3.x或者apoc庫。安裝apoc後能用Cypher調用其170+的程序:
MATCH (c:Character) WITH collect(c) AS charactersCALL apoc.algo.betweenness(['INTERACTS'], characters, 'BOTH') YIELD node, scoreSET node.betweenness = scoreRETURN node.name AS name, score ORDER BY score DESC
name
score
Jon
1279.7533534055322
Robert
1165.6025171231624
Tyrion
1101.3849724234349
Daenerys
874.8372110508583
Robb
706.5572832464792
Sansa
705.1985623519137
Stannis
571.5247305125714
Jaime
556.1852522889822
Arya
443.01358430043337
Tywin
364.7212195528086
緊度中心性(Closeness centrality)
緊度中心性是指到網路中所有其他角色的平均距離的倒數。在圖中,具有高緊度中心性的節點在聚類社區之間被高度聯結,但在社區之外不一定是高度聯結的。
圖7 :網路中具有高緊度中心性的節點被其它節點高度聯結
MATCH (c:Character) WITH collect(c) AS charactersCALL apoc.algo.closeness(['INTERACTS'], characters, 'BOTH') YIELD node, scoreRETURN node.name AS name, score ORDER BY score DESC
name
score
Tyrion
0.004830917874396135
Sansa
0.004807692307692308
Robert
0.0047169811320754715
Robb
0.004608294930875576
Arya
0.0045871559633027525
Jaime
0.004524886877828055
Stannis
0.004524886877828055
Jon
0.004524886877828055
Tywin
0.004424778761061947
Eddard
0.004347826086956522
使用python-igraph
Neo4j與其它工具(比如,R和Python數據科學工具)完美結合。我們繼續使用apoc運行 PageRank和社區發現(community detection)演算法。這里接著使用python-igraph計算分析。Python-igraph移植自R的igraph圖形分析庫。 使用 pip install python-igraph 安裝它。
從Neo4j構建一個igraph實例
為了在《權力的游戲》的數據的圖分析中使用igraph,首先需要從Neo4j拉取數據,用Python建立igraph實例。作者使用 Neo4j 的Python驅動庫py2neo。我們能直接傳入Py2neo查詢結果對象到igraph的 TupleList 構造器,創建igraph實例:
from py2neo import Graphfrom igraph import Graph as IGraph graph = Graph query = ''' MATCH (c1:Character)-[r:INTERACTS]->(c2:Character) RETURN c1.name, c2.name, r.weight AS weight '''ig = IGraph.TupleList(graph.run(query), weights=True)
現在有了igraph對象,可以運行igraph實現的各種圖演算法來。
PageRank
作者使用igraph運行的第一個演算法是PageRank。PageRank演算法源自Google的網頁排名。它是一種特徵向量中心性(eigenvector centrality)演算法。
在igraph實例中運行PageRank演算法,然後把結果寫回Neo4j,在角色節點創建一個pagerank屬性存儲igraph計算的值:
pg = ig.pagerank pgvs = for p in zip(ig.vs, pg): print(p) pgvs.append({"name": p[0]["name"], "pg": p[1]}) pgvs write_clusters_query = ''' UNWIND {nodes} AS n MATCH (c:Character) WHERE c.name = n.name SET c.pagerank = n.pg '''graph.run(write_clusters_query, nodes=pgvs)
現在可以在Neo4j的圖中查詢最高PageRank值的節點:
MATCH (n:Character) RETURN n.name AS name, n.pagerank AS pagerank ORDER BY pagerank DESC LIMIT 10
name
pagerank
Tyrion
0.042884981999963316
Jon
0.03582869669163558
Robb
0.03017114665594764
Sansa
0.030009716660108578
Daenerys
0.02881425425830273
Jaime
0.028727587587471206
Tywin
0.02570016262642541
Robert
0.022292016521362864
Cersei
0.022287327589773507
Arya
0.022050209663844467
社區發現(Community detection)
圖8
社區發現演算法用來找出圖中的社區聚類。作者使用igraph實現的隨機遊走演算法( walktrap)來找到在社區中頻繁有接觸的角色社區,在社區之外角色不怎麼接觸。
在igraph中運行隨機遊走的社區發現演算法,然後把社區發現的結果導入Neo4j,其中每個角色所屬的社區用一個整數來表示:
clusters = IGraph.community_walktrap(ig, weights="weight").as_clustering nodes = [{"name": node["name"]} for node in ig.vs]for node in nodes: idx = ig.vs.find(name=node["name"]).index node["community"] = clusters.membership[idx] write_clusters_query = ''' UNWIND {nodes} AS n MATCH (c:Character) WHERE c.name = n.name SET c.community = toInt(n.community) '''graph.run(write_clusters_query, nodes=nodes)
我們能在Neo4j中查詢有多少個社區以及每個社區的成員數:
MATCH (c:Character) WITH c.community AS cluster, collect(c.name) AS members RETURN cluster, members ORDER BY cluster ASC
cluster
members
0
[Aemon, Alliser, Craster, Eddison, Gilly, Janos, Jon, Mance, Rattleshirt, Samwell, Val, Ygritte, Grenn, Karl, Bowen, Dalla, Orell, Qhorin, Styr]
1
[Aerys, Amory, Balon, Brienne, Bronn, Cersei, Gregor, Jaime, Joffrey, Jon Arryn, Kevan, Loras, Lysa, Meryn, Myrcella, Oberyn, Podrick, Renly, Robert, Robert Arryn, Sansa, Shae, Tommen, Tyrion, Tywin, Varys, Walton, Petyr, Elia, Ilyn, Pycelle, Qyburn, Margaery, Olenna, Marillion, Ellaria, Mace, Chataya, Doran]
2
[Arya, Beric, Eddard, Gendry, Sandor, Anguy, Thoros]
3
[Brynden, Catelyn, Edmure, Hoster, Lothar, Rickard, Robb, Roose, Walder, Jeyne, Roslin, Ramsay]
4
[Bran, Hodor, Jojen, Luwin, Meera, Rickon, Nan, Theon]
5
[Belwas, Daario, Daenerys, Irri, Jorah, Missandei, Rhaegar, Viserys, Barristan, Illyrio, Drogo, Aegon, Kraznys, Rakharo, Worm]
6
[Davos, Melisandre, Shireen, Stannis, Cressen, Salladhor]
7
[Lancel]
角色「大合影」
《權力的游戲》的權力圖。節點的大小正比於介數中心性,顏色表示社區(由隨機遊走演算法獲得),邊的厚度正比於兩節點接觸的次數。現在已經計算好這些圖的分析數據,讓我們對其進行可視化,讓數據看起來更有意義。
Neo4j自帶瀏覽器可以對Cypher查詢的結果進行很好的可視化,但如果我們想把可視化好的圖嵌入到其它應用中,可以使用Javascript可視化庫Vis.js。從Neo4j拉取數據,用Vis.js的neovis.js構建可視化圖。Neovis.js提供簡單的API配置,例如:
var config = { container_id: "viz", server_url: "localhost", labels: { "Character": "name" }, label_size: { "Character": "betweenness" }, relationships: { "INTERACTS": }, relationship_thickness: { "INTERACTS": "weight" }, cluster_labels: { "Character": "community" } }; var viz = new NeoVis(config); viz.render;
其中:
節點帶有標簽Character,屬性name;
節點的大小正比於betweenness屬性;
可視化中包括INTERACTS關系;
關系的厚度正比於weight屬性;
節點的顏色是根據網路中社區community屬性決定;
從本地伺服器localhost拉取Neo4j的數據;
在一個id為viz的DOM元素中展示可視化。
⑵ PageRank:隨機遊走模型(一)
PageRank是一種廣泛應用於圖結構場景的排序方法,如社交網路、推薦系統、交通、電網等。常見應用還包括文本中的關鍵詞提取。它幾乎原封不動地被應用到新場景中,卻表現出強大的能力。主要通過計算節點的PageRank值對節點進行排序,以此表示節點的「重要性」。擁有較高PageRank值的網頁在搜索引擎中會被給予更靠前的排名。
本文系列包含四篇,以隨機遊走模型介紹PageRank基本概念為第一篇,通過馬爾科夫鏈深入PageRank理論為第二篇,接著第三篇探討基於PageRank的變體演算法,如TrustRank、ItemRank和TextRank,第四篇介紹用於計算PageRank和PageRank變體演算法的統一框架,該框架在代碼整理完畢後將開源。
樸素的隨機遊走模型中,使用圖結構來描述網路(如Web),圖中的節點表示網頁,邊表示網頁間的超鏈接。假設存在一個上網者(Surfer)在網頁間隨機遊走,選擇繼續瀏覽或輸入新網址。當遊走次數足夠多時,每個網頁被訪問的頻率趨於穩定,這些頻率即為網頁的PageRank值。
修正後的模型考慮了Dangling頁面和內部鏈接問題,通過添加指向所有頁面的鏈接來解決Dangling頁面問題,忽略內部鏈接以避免頁面自我循環。模型進一步描述了Surfer選擇行為的概率,以及如何通過隨機遊走計算PageRank值。
概率的隨機遊走模型中,定義了Surfer在任意時刻處於不同節點的概率,並通過分析Surfer通過不同行為訪問特定節點的概率,得出節點在任意時刻被訪問的概率,即PageRank值。
PageRank的理論分析涉及到概率收斂問題,下一文將詳細討論。討論PageRank的一般性問題包括其被操控性、隨機策略的合理性以及其在實際應用中的局限性。在特定領域如排序相關場景和圖相關場景中,PageRank變體演算法(如ItemRank和TextRank)的使用更為普遍。
推薦閱讀文獻,深入了解PageRank及其應用,如Gleich D F.《PageRank beyond the Web》中探討了PageRank在非網頁場景中的應用。
⑶ 隨機遊走演算法是什麼
這個……設置一個1到4的隨機數(假定遊走的空間是二維的),如果隨機數結果為1,就向上走一個單位,如果為2,向左走一個單位,如果為3,向下走一個單位,如果為4,向右走一個單位,每走一個單位,重復一遍上面的過程。