【问题标题】:GraphX or GraphFrame - community detection in undirected weighted graphGraphX 或 GraphFrame - 无向加权图中的社区检测
【发布时间】:2020-05-07 17:47:40
【问题描述】:

我正在尝试识别大型群体中的强关联社区(无向加权图)。或者,识别导致原本不相关的子组(社区)连接的​​顶点。

该问题是更广泛的 Databricks 解决方案的一部分,因此 Spark GraphX 和 GraphFrames 是解决该问题的首选。

从附图中可以看出,我需要找到顶点“X”作为可以分割连接组件算法识别的大连续组的点(val result = g.connectedComponents.run())

强连通分量法(仅适用于有向图)、三角形计数或 LPA 社区检测算法不适用,即使所有权重都相同,例如1.

Picture with point, where should be cut big group ST0

问题“Cut in a Weighted Undirected Connected Graph”中很好地描述了类似的逻辑,但仅作为数学表达式。

感谢任何提示。

// Vertex DataFrame
val v = sqlContext.createDataFrame(List( 
  (1L, "A-1", 1),       // "St-1"
  (2L, "B-1", 1),
  (3L, "C-1", 1),
  (4L, "D-1", 1),

  (5L, "G-2", 1),      // "St-2"
  (6L, "H-2", 1),
  (7L, "I-2", 1),
  (8L, "J-2", 1),  
  (9L, "K-2", 1),

  (10L, "E-3", 1),     // St-3
  (11L, "F-3", 1),
  (12L, "Z-3", 1),

  (13L, "X-0", 1)      // split point
)).toDF("id", "name", "myGrp")

// Edge DataFrame
val e = sqlContext.createDataFrame(List( 
  (1L, 2L, 1),
  (1L, 3L, 1),
  (1L, 4L, 1),
  (1L, 13L, 5),  // critical edge
  (2L, 4L, 1),

  (5L, 6L, 1),
  (5L, 7L, 1),
  (5L, 13L, 7),   // critical edge
  (6L, 9L, 1),    
  (6L, 8L, 1),  
  (7L, 8L, 1),   

  (12L, 10L, 1),
  (12L, 11L, 1),
  (12L, 13L, 9),  // critical edge
  (10L, 11L, 1)
)).toDF("src", "dst", "relationship")

val g = GraphFrame(v, e)

【问题讨论】:

  • 有趣的问题!您能否详细说明为什么“三角形计数或 LPA 社区检测算法不适合”?从您附加三角形或循环计数的草图中可以解决问题,不是吗?
  • @JanLauGe,你是对的,三角形计数会缩小选项。 X 将有 0 个三角形。但是,对于 C 和 K,您也会得到 0。现在想象一下,会有额外的节点连接到 C 或 K。你知道在这种情况下如何利用三角形计数吗?
  • 在示例中,K 和 C 是终端顶点。如果这是设计使然,而不仅仅是巧合,我们可以只切割没有三角形的非终端节点的边缘。正如您正确指出的那样,如果有其他节点连接到 C 和 K 这不再“削减”(看看我在那里做了什么?)......根据实际数据,也许三角形计数与度中心性可能有帮助吗?
  • @JanLauGe 好点!非终端节点上不存在三角形标识可疑顶点。缺少节点的集群可能存在一些风险(例如,如果没有 B - D 边缘,则 A 将被标记为与 X 完全相同)。这意味着需要一些额外的方法,但你的想法会有所帮助!
  • @Palo 你写过这段代码吗?如果您不介意发布结果,我希望能够参考它?谢谢!

标签: graph-algorithm spark-graphx graphframes


【解决方案1】:

Betweenness centrality 似乎是适合这个问题的算法之一。此方法计算连接任何其他顶点对的所有最短路径中通过每个顶点的最短路径的数量。

据我所知,GraphFrame 具有中介中心性,其最短路径仅提供顶点之间的环数,而不会列出实际路径。使用bfs(广度优先搜索)方法可以为我们提供合理的近似值(注意:bfs 也不反映距离/边长;它还按指示处理每个图):

  • 确保在两个方向上定义每个顶点,以使bfs 将图视为无向
  • 用以下字段声明可变结构(例如 ArrayBuffer)pathMembers[fromId, toId, pathId, vertexId]
  • 对于图中的每个顶点 o g.vertices(外循环)
    • 对于图中g.vertices.filter($"id" < lit(o.id)) 中的每个顶点 i(内循环 - 仅查看小于 o.id 的 i.id,因为 shortestPath(o.id, i.id) 与 shortestPath(i.id, o.id) 在无向图中)
      • 申请val paths = g.bfs.fromExpr("id = " + o.id).toExpr("id = " + i.id).run()
      • 转置paths为每条路径存储路径中的所有顶点,并将它们存储在pathMembers
  • 计算每个vertexId 出现在每个fromId, toId 路径中的时间(即vertexId 计数除以pathId 每个fromId, toId 对的计数)
  • 对每个vertexId 的计算求和以获得介数中心度度量

模式的顶点“X”将获得最高值。直接连接到“X”的顶点的值将下降。如果由“X”交叉连接的大多数组具有可比的大小,则差异会很大。

注意:如果您的图太大,则完整的介数中心性算法将非常长,可以随机选择用于计算最短路径的对子集。样本量是可接受的处理时间和在图的单个分支中选择大多数对的概率之间的折衷。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-18
    • 1970-01-01
    • 2017-12-07
    • 2021-05-22
    • 2018-01-05
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    相关资源
    最近更新 更多