一、ConnectedComponents算法
ConnectedComponents即连通体算法用id标注图中每个连通体,将连通体中序号最小的顶点的id作为连通体的id。
图关系如下时:
//创建点
val vertexRDD: RDD[(VertexId, (String,Int))] = SC.makeRDD(Array(
(1L, ("Alice", 28)),
(2L, ("Bob", 27)),
(3L, ("Charlie", 65)),
(4L, ("David", 42)),
(5L, ("Ed", 55)),
(6L, ("Fran", 50))
))
//创建边,边的属性代表 相邻两个顶点之间的距离
val edgeRDD: RDD[Edge[Int]] = SC.makeRDD(Array(
Edge(2L, 1L, 7),
Edge(2L, 4L, 2),
Edge(3L, 2L, 4),
Edge(3L, 6L, 3),
Edge(4L, 1L, 1),
Edge(2L, 5L, 2),
Edge(5L, 3L, 8),
Edge(5L, 6L, 3)
))
//点RDD+边RDD=图graph
val graphDistance: Graph[(String, PartitionID), PartitionID] = Graph(vertexRDD, edgeRDD)
ConnectedComponents
.run(graphDistance,Int.MaxValue)
.vertices.foreach(println)
结果如下
(5,1)
(3,1)
(6,1)
(2,1)
(4,1)
(1,1)
Process finished with exit code 0
图关系如下时:
ConnectedComponents
.run(graphDistance,Int.MaxValue)
.vertices.foreach(println)
结果如下
(4,1)
(3,3)
(1,1)
(6,3)
(5,3)
(2,1)
Process finished with exit code 0
二、StringlyConnectedComponents算法
有向图中最大的强连通子,输出每个强连通子图顶点对应的最小顶点编号。
图关系如下:
StronglyConnectedComponents
.run(graphDistance,Int.MaxValue)
.vertices.foreach(println)
结果如下:
(6,6)
(4,4)
(3,2)
(5,2)
(1,1)
(2,2)
Process finished with exit code 0
解析:1、4、6顶点构不成环,所以在StronglyConnectedComponent下最小顶点id为自身
2 -> 5 -> 3构成强连通图,故其最小顶点id为2
应用场景★★★
话单分析人物关系
企业信息族谱
三、ShortestPaths法
ShortestPaths 是可以计算节点到节点的最短路径,该最小路径为最小步长,并非最短距离。
图关系如下:
ShortestPaths
.run(graphDistance,vertexRDD.map(_._1).collect().toSeq)
.vertices.foreach(println)
结果如下:
(4,Map(4 -> 0, 1 -> 1))
(3,Map(2 -> 1, 5 -> 2, 4 -> 2, 1 -> 2, 3 -> 0, 6 -> 1))
(2,Map(2 -> 0, 5 -> 1, 4 -> 1, 1 -> 1, 3 -> 2, 6 -> 2))
(6,Map(6 -> 0))
(1,Map(1 -> 0))
(5,Map(2 -> 2, 5 -> 0, 4 -> 3, 1 -> 3, 3 -> 1, 6 -> 1))
Process finished with exit code 0
应用场景★★★
物联网(物流)
社交:六度空间(每两个人之间最多间隔5个人,即每两个人之间的最短路径<=6)
四、LabelPropagation算法(没理解过程)
LabelPropagation,是一种基于图的半监督学习算法(Semi-supervised learning),应用场景为:社区发现(Community detection)。传统意义上的社区指的是网络中的一组节点间具有较大的相似性,从而形成的一种内部连接紧密,而外部稀疏的群体结构,根据各社区节点有无交集,又可分为非重叠型社区和重叠型社区。对给定的网络图寻找其社区结构的过程称为“社区发现”。大体上看,社区发现的过程就是一种聚类的过程。
基本思想:
标签传播算法的应用场景是不重叠社区发现,其基本思想是:将一个节点的邻居节点的标签中数量最多的标签作为该节点自身的标签。给每个节点添加标签(label)以代表它所属的社区,并通过标签的“传播”形成同一标签的“社区”结构。简而言之,你的邻居属于哪个label最多,你就属于哪个label。该算法的有点是收敛周期短,除了迭代次数无需任何先验参数(不需事先指定社区个数和大小),算法执行过程中不需要计算任何社区指标。
时间复杂度:对顶点分配标签的复杂度为O(n),每次迭代时间为O( m),找出所有社区的复杂度为O (n +m),这是一次迭代的时间复杂度,非多次。标签传播算法的计算复杂度十分便宜,但是它不保证收敛,且迭代次数足够多之后,所有联通节点最终收敛为一个社区。
传播过程:
1)初始时,给每个节点一个唯一的标签;
2)每个节点使用其邻居节点的标签中最多的标签来更新自身的标签。
3)反复执行步骤2),直到每个节点的标签都不再发生变化为止。
一次迭代过程中一个节点标签的更新可以分为同步和异步两种。所谓同步更新,即节点z在第t次迭代的label依据于它的邻居节点在第t-1次迭代时所得的label;异步更新,即节点z在第t次迭代的label依据于第t次迭代已经更新过label的节点和第t次迭代未更新过label的节点在第t-1次迭代时的label。很拗口,简言之,同步指所有邻居节点这一轮都还未更新,t 节点是这其中的第一个更新者,异步指t不是其中的第一个更新者,邻居中同时存在此轮已更新和未更新者。
注意事项:
1、迭代次数设定一个阈值,可以防止过度运算;
2、对于二分图等网络结构,同步更新会引起震荡;
3、类似(“强”社区>)定义的结构(该社区>=);
4、每个顶点在初始的时候赋予唯一的标签,即“重要性”相同,而迭代过程又采用随机序列,会导致同一初始状态不同结果甚至巨型社区的出现;
5、如果能预测“社区中心”点,能有效提高社区发现的准确度,大幅提高效率;
6、同一节点的邻居节点的标签可能存在多种社区最大数目相同的情况,取“随机”一个作为其标签
图关系如下:
LabelPropagation
.run(graphDistance,6)//最大迭代次数一般设置为点数量
.vertices.foreach(println)
结果如下:
(5,2)
(6,2)
(4,2)
(1,2)
(3,2)
(2,2)
Process finished with exit code 0
解析:
第一次迭代后
第二次迭代
第三次迭代
第四次迭代
应用场景★★★
游戏通过聊天记录在玩家中找代理
信息传播源头推断:以消息为主题,查看消息传播的始作俑者
五、TriangleCount算法
Triangle Count的算法思想如下:
- 计算每个结点的邻结点,
- 对通过每条边的两个顶点相联的顶点的相邻点集合计算交集,并找出交集中id大于前两个结点id的结点,
- 对每个结点统计Triangle总数,注意只统计符合计算方向的Triangle Count。
注意:计算三角形时,要有计算方向(如,起始结点id<中间结点id<目的结点id)。
图关系如下:
TriangleCount
.run(graphDistance)
.vertices.foreach(println)
结果如下:
(6,1)
(3,2)
(1,1)
(5,2)
(2,2)
(4,1)
Process finished with exit code 0
应用场景★★★
社群发现:社群耦合关系紧密程度(一个人的社交网络中三角形数量越多说明社交关系越稳定
6. PageRank算法
- 用于评估网页链接的质量和数量,以确定该网页的重要性和权威性的相对分数,范围为0到10
- 从本质上讲,PageRank是找出图中顶点(网页链接)的重要性
- GraphX提供了PageRank API用于计算图的PageRank
val rddUrl: RDD[(VertexId, String)] = SC.makeRDD(Seq(
(1L, "baidu.com"),
(2L, "taobao.com"),
(3L, "jd.com"),
(4L, "qq.com"),
(5L, "360.com"),
(6L, "163.com"),
(7L, "hotmail.com")
))
val rddLink: RDD[Edge[String]] = SC.makeRDD(Seq(
Edge(1L, 2L ,"baidu->taobao"),
Edge(1L, 3L ,"baidu->jd"),
Edge(1L, 4L ,"baidu->qq"),
Edge(1L, 5L ,"baidu->360"),
Edge(2L, 1L ,"taobao->baidu"),
Edge(2L, 3L ,"taobao->jd"),
Edge(2L, 6L ,"taobao->163"),
Edge(2L, 7L ,"taobao->hotmail"),
Edge(3L, 1L ,"jd->baidu"),
Edge(3L, 5L ,"jd->360"),
Edge(4L, 1L ,"baidu->baidu"),
Edge(4L, 2L ,"baidu->taobao"),
Edge(4L, 3L ,"baidu->jd"),
Edge(5L, 2L ,"360->taobao"),
Edge(5L, 4L ,"360->qq")
))
val graphUrl = Graph(rddUrl, rddLink)
第一种:(静态)在调用时提供一个参数number,用于指定迭代次数,即无论结果如何,该算法在迭代number次后停止计算,返回图结果。
PageRank
.run(graphUrl,10)
.vertices
.collect()
.sortBy(_._2)
.foreach(println)
结果如下:
(6,0.5601493916091493)
(7,0.5601493916091493)
(4,1.0215278983104827)
(5,1.0578345140682444)
(3,1.1420385213274413)
(2,1.314244837000053)
(1,1.34405544607548)
Process finished with exit code 0
第二种:(动态)在调用时提供一个参数tol,用于指定前后两次迭代的结果差值应小于tol,以达到最终收敛的效果时才停止计算,返回图结果。
graphUrl
.pageRank(0.05)
.vertices
.collect()
.sortBy(_._2)
.foreach(println)
结果如下:
(6,0.6235956698404268)
(7,0.6235956698404268)
(4,1.0148403853406844)
(5,1.0413239067133522)
(3,1.1425268669793902)
(2,1.2661772790078105)
(1,1.2879402222779095)
Process finished with exit code 0
runParallelPersonalizedPageRank算法,相对于sources:Array[VertedId]列表中的参考节点的权重,即参考节点对该节点权重的影响程度
PageRank
.runparallelPersonalizedPageRank(graphUrl,10,0.15,Array(1L,2L))
.vertices
.foreach(println)
结果如下:
(7,(2,[0,1],[0.03475481014527509,0.08110471115501951]))
(2,(2,[0,1],[0.1669295290441871,0.3823587222638205]))
(1,(2,[0,1],[0.3526859544632016,0.1583346769425601]))
(6,(2,[0,1],[0.03475481014527509,0.08110471115501951]))
(4,(2,[0,1],[0.13062446672807568,0.07175465420224969]))
(5,(2,[0,1],[0.13491670492451835,0.09055335657128549]))
(3,(2,[0,1],[0.14533372454946697,0.13478916771004518]))
Process finished with exit code 0