本文通过Python 3.7实现了标签传播算法的两个代码(1.自己写的,2.调包实现),并通过空手道俱乐部的例子进行可视化显示。

标签传播是一种半监督机器学习算法,它将标签分配给以前未标记的数据点。在算法开始时,数据点的子集(通常只占很小一部分)有标签(或分类)。在整个算法过程中,这些标签会传播到未标记的点。

在复杂的网络中,真实的网络往往具有社区结构。标签传播是寻找社区的一种算法。 与其他算法相比,标签传播在运行时间和关于网络结构所需的先验信息量方面具有优势(不需要预先知道参数)。缺点是它不会产生唯一的解决方案,而是产生许多解决方案的集合。

注意:该算法是概率性的,并且发现的社区可能因执行的不同而不同

算法的思想:
在用一个唯一的标签初始化每个节点之后,该算法会重复地将一个节点的标签设置为该节点的相邻节点中出现频率最高的标签。当每个节点的标签在其相邻节点中出现得最频繁时,算法就会停止。该算法是异步的,因为每个节点都会在不等待其余节点更新的情况下进行更新。

该过程有5个步骤:

  1. 初始化网络中所有节点的标签。对于给定的节点x,Cx (0) = x。
  2. 设置t = 1。
  3. 以随机顺序排列网络中的节点,并将其设置为x
  4. 对于以特定顺序选择的每个x ∈ X,让Cx(t) = f(Cxi1(t),…、Cxim(t)、Cxi(m+1)(t1)。…,Cxik(t1))。f这里返回相邻标签中出现频率最高的标签。如果有多个最高频率标签,就随机选择一个标签。
  5. 如果每个节点都有其邻居节点中数量最多的标签,则停止算法。否则,设置t = t + 1并转到(3)。

python实现LPA代码如下:

import random
import networkx as nx
import matplotlib.pyplot as plt

'''
本文实现标签传播算法 2007年
author:xiao黄
time:2020.09.27
blog:
'''
# 应该封装成类的形式

def lpa(G):
    '''
    异步更新方式
    G:图
    return: None
    通过改变节点的标签,最后通过标签来划分社区
    算法终止条件:迭代次数超过设定值
    '''
    max_iter_num = 0 # 迭代次数

    while max_iter_num < 10:
        max_iter_num += 1
        print('迭代次数',max_iter_num)
    
        for node in G:
            count = {} # 记录邻居节点及其标签
            for nbr in G.neighbors(node): # node的邻居节点
                label = G.node[nbr]['labels'] 
                count[label] = count.setdefault(label,0) + 1
            
            # 找到出现次数最多的标签
            count_items = sorted(count.items(),key=lambda x:-x[-1])
            best_labels = [k for k,v in count_items if v == count_items[0][1]]
            # 当多个标签最大技术值相同时随机选取一个标签
            label = random.sample(best_labels,1)[0] # 返回的是列表,所以需要[0]
            G.node[node]['labels'] = label # 更新标签


def draw_picture(G):
    # 画图
    node_color = [float(G.node[v]['labels']) for v in G]
    pos = nx.spring_layout(G) # 节点的布局为spring型
    plt.figure(figsize = (8,6)) # 图片大小
    nx.draw_networkx(G,pos=pos,node_color=node_color)
    plt.show()

if __name__ == "__main__":
    G = nx.karate_club_graph() # 空手道

    # 给节点添加标签
    for node in G:
        G.add_node(node, labels = node) # 用labels的状态

    lpa(G)

    com = set([G.node[node]['labels'] for node in G])
    print('社区数量',len(com))

    draw_picture(G)

算法运行结果:

标签传播算法python源码 标签传播算法社区发现_复杂网络


调包实现LPA代码如下:

import matplotlib.pyplot as plt
import networkx as nx
from networkx.algorithms.community import asyn_lpa_communities as lpa

G = nx.karate_club_graph() # 空手道俱乐部
com = list(lpa(G))
print('社区数量',len(com))

# 下面是画图
pos = nx.spring_layout(G) # 节点的布局为spring型

NodeId = list(G.nodes())
node_size = [G.degree(i)**1.2*90 for i in NodeId] # 节点大小

plt.figure(figsize = (8,6)) # 图片大小
nx.draw(G,pos, with_labels=True, node_size =node_size, node_color='w', node_shape = '.')
'''
node_size表示节点大小
node_color表示节点颜色
with_labels=True表示节点是否带标签
'''
color_list = ['pink','orange','r','g','b','y','m','gray','black','c','brown']

for i in range(len(com)):
    nx.draw_networkx_nodes(G, pos, nodelist=com[i], node_color=color_list[i],  with_labels=True)

plt.show()

参考文献:
Raghavan、Usha Nandini、R_ka Albert和Soundar Kumara。”大型网络中检测社区结构的近线性时间算法〉,《物理评论》E 76.3(2007):036106。

U.N.Raghavan – R. Albert – S. Kumara “Near linear time algorithm to detect community structures in large-scale networks”, 2007.