标签传播算法_基于graphx的标签传播算法实现

上一篇讲了一下spark graphx入门的一些小知识,这周开始做了一下标签传播算法的实现。标签传播算法,即label propagation,是社交网路中用于发现社区结构的一个非常简单高效的算法。时间复杂度低,实现简单。该方法同样能用于标签挖掘场景,通过少量的已标注数据进行指导并预测未标记数据的标签。操作简单,运算量小,适合大规模数据信息的挖掘和处理。

标签传播算法主要包含两个步骤:

第一步: 为所有节点指定一个唯一的标签,可以直接以节点id作为标签;

第二步: 逐轮刷新所有节点的标签, 对于某一个节点,考察其所有邻居节点的标签,并进行统计,将出现个数最多的那个标签赋给当前节点。当个数最多的标签不唯一时,随机选一个。

重复第二步直到达到收敛条件为止,通常会设置一个迭代次数的限制。一般来说,收敛的快慢和图的大小无关,迭代5次基本上95%以上的节点就会收敛。

在大规模图数据集上,并行的图计算是非常必要的。graphx提供了Pregel计算接口。pregel主要包含三个函数:vprog函数、sendMsg函数、mergeMsg函数。其源码如下:

def pregel[A: ClassTag](
initialMsg: A,
maxIterations: Int = Int.MaxValue,
activeDirection: EdgeDirection = EdgeDirection.Either)(
vprog: (VertexId, VD, A) => VD,
sendMsg: EdgeTriplet[VD, ED] => Iterator[(VertexId, A)],
mergeMsg: (A, A) => A)
: Graph[VD, ED] = {
Pregel(graph, initialMsg, maxIterations, activeDirection)(vprog, sendMsg, mergeMsg)
}

代码中A表示消息的类型。从中可以看到,vprog函数是运行在每个节点上的,通过接收信息,更新自身的节点属性值。sendMsg是发送消息的。mergeMsg则是合并消息的。

object LabelPropagation { 
def run[VD, ED: ClassTag](graph: Graph[VD, ED], maxSteps: Int): Graph[VertexId, ED] = { 
//初始化每个定点的社区表示为当前结点的id值 
val lpaGraph = graph.mapVertices { case (vid, _) => vid } 
//定义消息的发送函数,将顶点的社区标识发送到相邻顶点 
def sendMessage(e: EdgeTriplet[VertexId, ED]): Iterator[(VertexId, Map[VertexId, Long])] = { 
Iterator((e.srcId, Map(e.dstAttr -> 1L)), (e.dstId, Map(e.srcAttr -> 1L))) 
} 
//顶点的消息聚合函数 将每个节点消息聚合,做累加;例如一个定点出现了两次,id->2 
def mergeMessage(count1: Map[VertexId, Long], count2: Map[VertexId, Long]) 
: Map[VertexId, Long] = { 
(count1.keySet ++ count2.keySet).map { i => 
val count1Val = count1.getOrElse(i, 0L) 
val count2Val = count2.getOrElse(i, 0L) 
i -> (count1Val + count2Val) 
}.toMap 
} 
//顶点属性更新,如果有消息,取出现次数最大的作为自身的新标记
def vertexProgram(vid: VertexId, attr: Long, message: Map[VertexId, Long]): VertexId = { 
if (message.isEmpty) attr else message.maxBy(_._2)._1 
} 
val initialMessage = Map[VertexId, Long]
Pregel(lpaGraph, initialMessage, maxIterations = maxSteps)( 
vprog = vertexProgram, 
sendMsg = sendMessage, 
mergeMsg = mergeMessage) 
} 
} 

根据LPA算法的原理,可以看到代码中传递的消息类型就是Map[VertexId, Long],即节点所在标签和其出现的次数。

整个的原理和实现差不多就讲完了。在具体的应用过程中,其实还需要考虑很多东西,比如在人群标签扩散中,节点之间的关系紧密程度、关系的类型都会影响标签的传播准确性。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值