几个月前,数学家Andrew Beveridge和Jie Shan在Math Horizon杂志上发表了权利的游戏的网络,其中,他们分析了小说“冰雨的风暴”,火爆的“冰与火之歌”(权利的游戏电视剧的基础)的第三卷中的角色互动网络。在他们的论文中,他们详细介绍了如何通过使用文本分析和实体抽取,来发现文本中提到的角色,从而构建角色互动网络。然后,他们应用社交网络分析算法到该网络中,以找到该网络中最重要的角色,并且应用社区检测算法来找到角色集群。
分析和可视化是通过使用Gephi,这一流行的图形分析工具,来完成的。近期也有很多作者使用Neo4j来复制结果。我们也可以使用igraph工具包来分析一下权利的有效网络。
import csv
edges = []
firstline = True
with open('stormofswords.csv', 'rb') as f:
for row in csv.reader(f.read().splitlines()):
if firstline == True:
firstline = False
continue
u, v, weight = [i for i in row]
edges.append((u, v, int(weight)))
from igraph import Graph as IGraph
g = IGraph.TupleList(edges, directed=True, vertex_name_attr='name', edge_attrs=None, weights=True)
分析网络
# 角色数
g.vcount()
# 网络直径: 一个网络的直径(或者测地线)被定义为网络中的最长最短路径。
print g.diameter()
names = g.vs["name"]
print g.get_diameter()
[names[x] for x in g.get_diameter()]
最短路径
print g.shortest_paths("Jon","Margaery")
print "---------------------"
print [names[x] for x in g.get_shortest_paths("Jon","Margaery")[0]]
print "---------------------"
paths = g.get_all_shortest_paths("Jon")
for p in paths:
print [names[x] for x in p]
中心性度量
# 度中心性(Degree Centrality)
# 度中心性仅是一个节点在网络中的连接数。在权利的游戏的图的上下文中,一个角色的度中心性是该角色交互的其他角色数。
print g.maxdegree()
print "---------------------"
for p in g.vs:
if p.degree() > 15:
print p["name"],p.degree()
# 加权度中心性
for p in g.vs:
weightedDegree = sum([x.degree() for x in p.neighbors()])
if weightedDegree > 250:
print p["name"],weightedDegree
# 邻居平均度
for p in zip(g.vs,g.knn()[0]):
if p[1] > 20:
print p[0]["name"],p[1]
# 介数中心性(Betweenness Centrality)
# 一个网络中的一个节点的中介中心性(Betweenness Centrality) 是,网络中所有的节点对之间通过该节点的最短路径数。
# 中介中心性是一项重要的指标,因为它可以用于识别网络中的“信息代理”,或者那些连接不同集群的节点。
btvs = []
for p in zip(g.vs, g.betweenness()):
btvs.append({"name": p[0]["name"], "bt": p[1]})
# print pgvs
sorted(btvs, key=lambda k: k['bt'], reverse=True)[:10]
# 接近中心性(Closeness centrality)
# 接近中心性(Closeness centrality)是到网络中所有其他角色的平均距离的倒数。
# 具有高接近中心性的节点通常在图中的集群之间被高度连接,但在集群外部不一定是高度连接的。
ccvs = []
for p in zip(g.vs, g.closeness()):
ccvs.append({"name": p[0]["name"], "cc": p[1]})
# print pgvs
sorted(ccvs, key=lambda k: k['cc'], reverse=True)[:10]
PageRank算法
PageRank是一种最初由Google用来对网页重要性进行排序的算法。
pg = g.pagerank()
# pg = g.pagerank(vertices=None, directed=True, damping=0.85,
# weights=weights, arpack_options=None,
# implementation='prpack',
# niter=1000, eps=0.001)
pgvs = []
for p in zip(g.vs, pg):
pgvs.append({"name": p[0]["name"], "pg": p[1]})
# print pgvs
sorted(pgvs, key=lambda k: k['pg'], reverse=True)[:10]
社区检测
社区检测算法用以查找图中的集群。我们将使用igraph中实现的walktrap社区检测方法,来找到那些在社区之中频繁交互,但在社区之外不存在太多互动的角色的社区。
clusters = IGraph.community_walktrap(g, weights="weight").as_clustering()
# community_walktrap: Community detection algorithm of Latapy & Pons, based on random walks.
# Pascal Pons, Matthieu Latapy: Computing communities in large networks using random walks,
# http://arxiv.org/abs/physics/0512106.
nodes = [{"name": node["name"]} for node in g.vs]
community = {}
for node in nodes:
idx = g.vs.find(name=node["name"]).index
node["community"] = clusters.membership[idx]
if node["community"] not in community:
community[node["community"]] = [node["name"]]
else:
community[node["community"]].append(node["name"])
for c,l in community.iteritems():
print "Community ", c, ": ", l
由于篇幅太长,这里进展示社区检测代码运行结果,其他代码请自行下载,自行运行
Community 0 : ['Aemon', 'Grenn', 'Samwell', 'Alliser', 'Mance', 'Jon', 'Craster', 'Karl', 'Eddison', 'Gilly', 'Janos', 'Bowen', 'Dalla', 'Orell', 'Qhorin', 'Rattleshirt', 'Styr', 'Val', 'Ygritte']
Community 1 : ['Aerys', 'Jaime', 'Robert', 'Tyrion', 'Tywin', 'Amory', 'Oberyn', 'Cersei', 'Gregor', 'Joffrey', 'Balon', 'Loras', 'Brienne', 'Bronn', 'Podrick', 'Lysa', 'Petyr', 'Sansa', 'Elia', 'Ilyn', 'Meryn', 'Pycelle', 'Shae', 'Varys', 'Qyburn', 'Renly', 'Tommen', 'Kevan', 'Margaery', 'Myrcella', 'Jon Arryn', 'Olenna', 'Marillion', 'Robert Arryn', 'Ellaria', 'Mace', 'Chataya', 'Doran', 'Walton']
Community 2 : ['Arya', 'Anguy', 'Beric', 'Gendry', 'Sandor', 'Thoros', 'Eddard']
Community 3 : ['Bran', 'Rickon', 'Hodor', 'Jojen', 'Luwin', 'Meera', 'Nan', 'Theon']
Community 4 : ['Brynden', 'Roose', 'Lothar', 'Walder', 'Catelyn', 'Edmure', 'Hoster', 'Jeyne', 'Robb', 'Roslin', 'Rickard', 'Ramsay']
Community 5 : ['Belwas', 'Barristan', 'Illyrio', 'Daario', 'Drogo', 'Irri', 'Daenerys', 'Aegon', 'Jorah', 'Kraznys', 'Missandei', 'Rakharo', 'Rhaegar', 'Viserys', 'Worm']
Community 6 : ['Stannis', 'Davos', 'Cressen', 'Salladhor', 'Melisandre', 'Shireen']
Community 7 : ['Lancel']
微信公众号首发,关注公众号,第一时间了解最新机器学习笔记,可进相关群,一起讨论,互相进步