LPA简介
什么是LPA
标签传播算法(Label Propagation Algorithm,LPA),是一种基于标签传播的局部社区划分算法。LPA将Grpah中的每个节点打上唯一的标签,通过随机选择一个node作为起始节点,根据其相连节点的标签改变自己的标签,以此来对整个图进行遍历,每一次迭代,图局部标签进行更新,从而达到整个Graph的标签确定。
优点
1、逻辑简单,整个计算过程几乎为线性计算,迭代速度快;
2、无需借助其他评测,只依赖自身标签;
3、无需提前划分社区数量,完全由迭代后进行决定。
缺点
1、随机性强,首次选中的节点可能会对后续节点的确定产生影响,进而影响全局标签;
2、节点更新顺序不确定,每次迭代的结果也不确定。
计算过程
1、初始化所有节点,标属每个节点的唯一标签;
2、随机选择一个节点N,将该节点的邻居节点(X1-Xn)的标签进行统计,选择频次最多的一个标签Xi;
3、如果有多个标签频次相同,那么随机选择一个标签,将该标签赋予N;
4、重复2、3步,直到标签不再变化或者迭代次数足够。
代码实现
我们以networkx中集成的LPA算法为例,来说明每个步骤:
import networkx as nx
from networkx.algorithms.community import asyn_lpa_communities as lpa
import random
首先,导入networkx以及LPA
G = nx.karate_club_graph()
data = lpa(G,weight='weight',seed=random)
for i,v in enumerate(data):
print(i,v)
其次,以networkx中的空手道数据为例,来运行一下
0 {0, 1, 2, 3, 7, 11, 12, 13, 17, 19, 21}
1 {10, 4}
2 {16, 5, 6}
3 {32, 33, 8, 9, 14, 15, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}
然后,我们可视化看一下聚类的结果:
如图所示,可以看出最终的数据经过LPA分成了4簇,从算法到数据是不是简单的不要了。
重点来了,源码分析
我们来剖析networkx是如何实现LPA算法的。
#定义每个节点的标签,即每个节点所对应的索引值
labels = {n: i for i, n in enumerate(G)}
#设定一个起始和终止条件
cont = True
while cont:
cont = False
#将图中的节点列表化
nodes = list(G)
#打乱列表中的数据
seed.shuffle(nodes)
#选择一个节点开始
for node in nodes:
#如果该节点为单独节点,则不需进行打标
if not G[node]:
continue
#判断是否需要依赖权重计算
if weight is None:
#在非权重图下,直接计算每个标签的个数,结果为“节点标签:标签个数”
label_freq = Counter(map(labels.get, G[node]))
else:
#定义字典
label_freq = defaultdict(float)
#遍历每个邻居节点的属性
for _, v, wt in G.edges(node, data=weight, default=1):
#获取每个节点的权重值,结果为“节点标签:每个标签累计权重之和”
label_freq[labels[v]] += wt
#选择频率最高或者权重最大的那个value
max_freq = max(label_freq.values())
#获取该值对应的标签
best_labels = [
label for label, freq in label_freq.items() if freq == max_freq
]
#判断该节点标签是否已经被新标签覆盖
if labels[node] not in best_labels:
#随机选择一个标签覆盖原来的标签
labels[node] = seed.choice(best_labels)
cont = True
#返回最终划分社区
yield from groups(labels).values()
整体看起来,networkx实现的算法很简洁,是根据异步更新实现的。其中,对是否加载图权重的问题分别进行实现,用起来还是非常方便了。
trick
请大家看一看,这张图和上面那张有什么地方不一样呢?
很明显,上面图中有4种颜色,而这张图中有3种颜色,也就是说,同样的数据,同样的算法,但是结果不太一致,这是为什么?
这正是因为初始的节点选择不同,导致了不太一样的结果,那么在实际应用中,在满足使用条件的前提下,多进行几次计算,选择簇类比较少的结果,可以更好的在后面使用中,尽量避免因为簇的个数较多或者簇中数据单一,导致该簇数据不可用。
以上trick仅针对使用的例子数据,仅做参考。
好啦,以上就是我对LPA的一个简单的理解和介绍,如果大家有什么问题或者补充,请加我QQ:1143948594,随时交流!!!