基于GN算法(Girvan-Newman)实现社交网络中社区划分
1 背景
網絡中社區結構的研究是了解整個網絡結構和功能的重要途經。對于網絡中社區結構的研究是了解整個網絡結構和功能的重要途經。一般來說,社區結構是大規模網絡中普遍存在的基本結構。網絡中的頂點可以進行分組,組內頂點間的連接比較“稠密”,組間頂點的連接比較“稀疏”,比如下面這個網絡結構模型。
在信息網絡中,社區經常對應著功能相同,性質相近或者關系比較密切的結點集合,比如,社會關系網絡中的朋友圈。GN算法是Girvan和Newman 提出的一個比較經典的社區劃分算法。
2 算法思想
社區與社區之間的連接比較少,從一個社區到另一個社區至少要通過這些連接中的一條。如果找到這些重要通道并將他們移除則自然分出了社區。為了定量的描述邊的“重要”程度,提出了邊介數的概念。
邊介數:網絡中通過這條邊的最短路徑的數目。
一個網絡的社區的劃分可以有很多劃分方法,哪種劃分方法比較好呢?為了定量描述社區劃分的好壞,Girvan和Newman 提出了模塊度Q的概念,對社區進行模塊化描述。對于一個可以表示為n×n矩陣的無向網絡,模塊化Q函數如下:
? ? Q=?
其中,i代表的是第i個社區,eii表示社區i的邊占原始網絡所有邊的比例,ai表示所有連接了社區i中的頂點的邊占總邊數的比例。
模塊度的含義其實就是一個網絡在某種社區劃分下與隨機網絡的差異,因為隨機網絡不具備社區結構,對應的差距越大,說明社區的劃分結果越好。
查閱資料得知,Q值取值范圍:-0.5到1 。
3 算法步驟
1)計算每條邊的邊介數;
2)找出邊介數最大的邊,并移除;
3)計算所得社區結構的Q值,尋找Q值最大的情況;
4)重新計算網絡中剩余邊的邊介數,重復2、3兩步,直至網絡中所有邊都被移除 。
GN的過程對應著一顆自頂向下構建的層次樹,在層次樹中選擇一個合適的層次分割即可。例如,下圖這個層次樹,移除掉邊介數最大的一條邊,效果就像從紅線那一層分割,其他同理。
4 實驗復現
選取比較經典的美國一所大學空手道俱樂部成員間的人際關系的數據,使用python語言進行復現。
Python實現該社交網絡的社區劃分代碼(完整代碼以及實驗數據)如下:
#util.py文件 #coding=utf-8 import networkx as nx# 加載網絡 def load_graph(path):G = nx.Graph()with open(path) as text:for line in text:vertices = line.strip().split(" ")source = int(vertices[0])target = int(vertices[1])G.add_edge(source, target)return G# 克隆 def clone_graph(G):cloned_graph = nx.Graph()for edge in G.edges():cloned_graph.add_edge(edge[0], edge[1])return cloned_graph# 計算Q值 def cal_Q(partition, G):m = len(list(G.edges())) #邊的個數a = []e = []# 計算每個社區的a值for community in partition:t = 0for node in community:t += len(list(G.neighbors(node)))a.append(t / float(2 * m))# 計算每個社區的e值for community in partition:t = 0for i in range(len(community)):for j in range(len(community)):if i != j:if G.has_edge(community[i], community[j]):t += 1e.append(t / float(2 * m))# 計算Qq = 0for ei, ai in zip(e, a):q += (ei - ai ** 2)return q#GN.py文件 # coding=utf-8 # 首先導入包 import networkx as nx import matplotlib.pyplot as plt import utilclass GN(object):"""docstring for GN"""def __init__(self, G):self._G_cloned = util.clone_graph(G)self._G = Gself._partition = [[n for n in G.nodes()]]self._max_Q = 0.0# GN算法def execute(self):while len(self._G.edges()) > 0:# 1.計算所有邊的edge betweennessedge = max(nx.edge_betweenness(self._G).items(),key=lambda item: item[1])[0]# 2.移去edge betweenness最大的邊self._G.remove_edge(edge[0], edge[1])# 獲得移去邊后的子連通圖components = [list(c) for c in list(nx.connected_components(self._G))]if len(components) != len(self._partition):# 3.計算Q值cur_Q = util.cal_Q(components, self._G_cloned)# print(cur_Q)if cur_Q > self._max_Q:self._max_Q = cur_Qself._partition = componentsreturn self._partition# 可視化劃分結果 def showCommunity(G, partition, pos):# 劃分在同一個社區的用一個符號表示,不同社區之間的邊用黑色粗體cluster = {}labels = {}for index, item in enumerate(partition):for nodeID in item:labels[nodeID] = r'$' + str(nodeID) + '$' # 設置可視化labelcluster[nodeID] = index # 節點分區號# 可視化節點colors = ['r', 'g', 'b', 'y', 'm']shapes = ['v', 'D', 'o', '^', '<']for index, item in enumerate(partition):nx.draw_networkx_nodes(G, pos, nodelist=item,node_color=colors[index],node_shape=shapes[index],node_size=350,alpha=1)# 可視化邊edges = {len(partition): []}for link in G.edges():# cluster間的linkif cluster[link[0]] != cluster[link[1]]:edges[len(partition)].append(link)else:# cluster內的linkif cluster[link[0]] not in edges:edges[cluster[link[0]]] = [link]else:edges[cluster[link[0]]].append(link)for index, edgelist in enumerate(edges.values()):# cluster內if index < len(partition):nx.draw_networkx_edges(G, pos,edgelist=edgelist,width=1, alpha=0.8, edge_color=colors[index])else:# cluster間nx.draw_networkx_edges(G, pos,edgelist=edgelist,width=3, alpha=0.8, edge_color=colors[index])# 可視化labelnx.draw_networkx_labels(G, pos, labels, font_size=12)plt.axis('off')plt.show()if __name__ == '__main__':# 加載網絡數據并可視化G = util.load_graph("network/data.txt")pos = nx.spring_layout(G)nx.draw(G, pos, with_labels=True, font_weight='bold')plt.show()# GN算法algo = GN(G)partition = algo.execute()print(partition)# 可視化結果showCommunity(algo._G_cloned, partition, pos)##數據文件data.txt如下 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1 11 1 12 1 13 1 14 1 18 1 20 1 22 1 32 2 3 2 4 2 8 2 14 2 18 2 20 2 22 2 31 3 4 3 8 3 9 3 10 3 14 3 28 3 29 3 33 4 8 4 13 4 14 5 7 5 11 6 7 6 11 6 17 7 17 9 31 9 33 9 34 10 34 14 34 15 33 15 34 16 33 16 34 19 33 19 34 20 34 21 33 21 34 23 33 23 34 24 26 24 28 24 30 24 33 24 34 25 26 25 28 25 32 26 32 27 30 27 34 28 34 29 32 29 34 30 33 30 34 31 33 31 34 32 33 32 34 33 34復現結果如下:
該空手道俱樂部初始社交網絡結構:
進行社區劃分之后的效果:
劃分成了五個子社區,這與論文里面的實驗結果也是相一致的。
5 算法優缺點
?優點:計算簡潔、易于程序實現; ?缺點:復雜度高(由于需要不斷地通過求解最短路徑來求解邊介數,復雜度比較高);總結
以上是生活随笔為你收集整理的基于GN算法(Girvan-Newman)实现社交网络中社区划分的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机网络的局限性的表现,计算机网络系统
- 下一篇: 理性和感性哪个对做产品更重要