【导读】
Spark GraphX是一个分布式图处理框架,它是基于Spark平台提供对图计算和图挖掘简洁易用的而丰富的接口,极大的方便了对分布式图处理的需求。但如果我们想熟练的开发Spark GraphX的应用程序还有很长的路要走,本系列文章是GraphX的从入门到精通,会持续更新,如果你对图计算感兴趣就关注起来吧。
【前言】
思考一个问题:现实生活中我们有哪些可用的图?以及这些可用的图都是什么样的图?
有向图和无向图
用图可以对事物以及事物之间的联系建模。首先来弄清楚【图3.9】中的有向图和无向图的不同。在一个有向图中,联系是从源顶点到目标顶点万维网中的一个页面到另一个页面的链接,学术论文中的引用,都是比较典型的例子。在有向图中,一条边的两个顶点般扮演着不同的角色,如父子关系,页面A链接向页面B。
在一个无向图中,边是没有方向;关系都是对称的。社交网络中一个典型的联系是,通常A如果是B的朋友,我们很可能认为B也是A的朋友。更进一步,如果我们到Kevin Bacon是六度关系,那么Kevin Bacon到我们也是六度关系。GraphX中的一个很重要的概念是,所有的边都有一个方向,那么图就是有向图;如果忽略边的方向,就是无向图。
有环图和无环图
有环图是包含循环的一系列顶点连接成一个环(参见【图3.10】)。一个无环图没有环。需要了解有环图和无环图的区别的原因是,如果你有个算法,通过连接的顶点,沿着连接的边有向图就会造成这样的风险:不恰当的算法实现会卡住,在环上永远循环下去。
有环图的一个有趣的特征是,其形成一个三角形关系,即每个顶点都与其他两个顶点相连。三角形关系的用途之一是作为一个预测特征来区分垃圾邮件和非垃圾邮件。
有标签的图和无标签的图
有标签图是顶点或边除了有唯一标示,还有与之关联的数据(标签)(参见【图3.11】)。对顶点做了标签称为顶点标签图,对边做了标签的称为边标签图。
上面讲到了GraphXGraphLoader.edgeListFile()创建边,它同时会对边的两个顶点(源顶点目标顶点)创建一个默认属性值1。一个确定了边标签类型的图就是大家熟知的权重图。权重图一般会用作计算比如城镇之间的最短路径。这里提到的权重是对边打标签,表示两个顶点(城镇〉之间的距离。
平行边和环
平行边和环区别在于是否许在同一对顶点上同存在多条边,还是边的起点和终点都是同个顶点,如【图3.12】所示的两种可能性。GrapbX是伪图,会存在平行边和自环,所以需要通过groupEdges()和subgrap()来排除这两种情况。
二分图
二分图有一个如【图3.13】所示的特定的结构,整个图的顶点被分成两个不同的集合,所有的源顶点是一个集合(所有源顶点之间没有联系),所有的目标顶点是一个集合(目标顶点之间没有联系),在两个集合内都不存在相连的边。
可以用二分图对两个不同类型实体之间的关系建模,例如,对申请上大学的学生,吧每个学生划分到一个顶点集合,把要申请的大学划分到另一个顶点集合。另一个例子就是推荐系统,把用户划分在一个集合中,用户所购买的产品划分在另一个集合中。
RDF图和属性图
资源描述框架(RDF)是由万维网联盟(W3C)在1997年首次提出的针对语义WEB的图标准。它实现了一部分2004年开始更新的RDFa标准。旧的图数据库、图处理系统只支持RDF三元组(主体、谓语、对象),而新的图数据库、图处理系统(包括GraphX)支持属性图(参见【图3.14】)。
由于其自身的局限性,RDF元组必须扩展到四元组(包括某种身份〉甚至五元组(包括一些所谓的上下文)。这些都是RDF图的问题。但尽管其有局限性,RDF图由于图数据的原因还是很重要的,例如来自维基百科、WordNet岱如和地理名称的YAG02数据库。属性图很容易满足新的图数据的需要。
邻接矩阵
另一种表示图论的方式是邻接矩阵(参见【图3.15】),这不是GraphX表示图的方式。抛开GraphX,Spark的MLlib机器学习库已经支持邻接矩阵,还有更通用的稀疏矩阵。如果你不需要边属性,可以在MLlib找到比GraphX性能更好的算法。例如,推荐系统,从性能的角度来看,mllib.recommendation.ALS会是比graphx.lib.SVDPlusPlus更好的选择,虽然不同场景适用不同算法。
图查询系统
有几十种图查询语言,这里挑出三个最常用的来跟Saprk进行比较。
这里统一使用这个查询示例:“请告诉我小名的朋友的朋友”
SPARKQL
SPARKQL是一个类SQL的语言,由W3C为了查询RDF图而推出:
SELECT ?p
{
"xiaoming" foaf:knows{2} ?p
}
Cypher
Cypher是属性图数据库Neo4j使用的查询语言:
MATCH (ann {ann.name: 'xiaoming'})-[:knows*2..2]-(p)
RETURN p
Tinkerpop Gremlin
Tinkeop努力创建个图数据库和图处理系统的接口标准,就像JDBC一样,只不过比JDBC更复杂。Tinkerpop多个组件构成,而Gremlin是查询系统。有一个把Gremlin整合到GraphX尝试,即Spark-Gremlin工程,可https://github.com/kellrott/spark-gremlin上查看,截止到2015月1月,这个工程的最新状态:是没什么要做的了。
g.V("name","ann").out('knows').aggregate(x).out('knows').except(x)
GraphX
截止到Spark1.6, GraphX还没有查询语言。GraphXAPI更适合在一个大图上运行一些算法,而不是查找一些特定顶点和一些直接的边和顶点。虽然如此,但也可以实现类似的查询功能,虽然不太好看:
val g2 = g .outerJoinVertices (g .aggregateMessages [Int] ( ctx => if (ctx.srcAttr ==”Ann”&& ctx.attr ==”knows") ctx.sendToDst(l), math.max(, ))) ((vid, vname, d) => (vname, d.getOrElse(O)))
g2.outerJoinVertices(g2.aggregateMessages[Int] ( ctx => if (ctx.srcAttr. 2 == 1 && ctx.attr ==”knows”) ctx. sendToDst ( 2) , math.max(, )))((vid, vname, d) => (vname, d.getOrElse(O))). vertices. map( . 2) .filter( . 2 == 2) .map( . 1. 1) .collect
参考文献:
《GraphX实战》
作者简介:大飞
算法工程师、知识搬运工、干货拾荒机
大飞原创不易,如转载请注明出处,学习是一生的事业。
PS:投稿请添加微信
wuyuanzahuopu(五元杂货铺)