基于Spark Grahpx+Neo4j 实现用户社群发现
上一篇文章知识图谱在大数据中的应用我们介绍了知识图谱的一些概念和应用场景,今天我们就来看一个具体的应用案例了解下知识图谱的应用。用户增长对于一个APP的生存起到了至关重要的作用,没有持续的用户增长,再好的APP也不会走的长远,为了获得更多的用户,APP运营商往往会鼓励老用户拉新并给与奖励,比如趣头条的收徒模式,用户每收一个徒弟就会得到几块到十几块的现金返现,但是这种模式同时也会引起广大黑产团伙的注意,黑产会利用各种手段来薅这些APP运营商的羊毛。
中国有句老话,叫物以类聚,人以群分,在反作弊和市场营销等应用中,如果我们能根据用户间的某些联系发现社群,然后对这些社群进行反作弊分析或商品推荐,往往会起到意想不到的效果。
本文就来介绍一个简单的社群发现的实践。构建社群我们首先需要找到社群用户的某种联系,上文提到的收徒模式本身就是用户间的一个天然联系,我们可以根据用户的师徒关系来构建社群。如下图所示,根据师徒关系我们构建了一个社群,点表示用户,边表示师徒关系。
有了这样的社群之后,我们就可以基于社群维度分析设备及用户行为的异常,比如单个设备登陆过多的用户,设备一直处于充电状态,所有用户行为高度一致等,同时可以计算社群用户作弊率来通过已知作弊用户来发现新的作弊用户。
理清了需求之后我们开始着手根据用户师徒关系构建社群。对"紧密联系"的不同理解产生了很多社区发现算法。下图是几种经典的社群发现算法。
社群算法
- Triangle Counting:三角关系,图论基础知识。
- Connected Components:连通图,图论基础知识。
- Strongly Connected Components:强连通图,图论基础知识。
- Label Propagation:标签传播算法。
- Louvain:一种基于"模块度"的经典算法。
因为本文重点不是讲述社群发现算法,所以这个算法具体的含义此处略过,有感兴趣的读者可自行研究。本文选用了最简单的连通图算法来实现社群发现,即只要两个节点之间有边我们就把它们归属为一个社群。下面我们进入根据用户师徒关系生成社群阶段。
Spark Graphx构建社群
Spark Graphx本身就提供了构建图并生成连通图的接口,我们只需要按要求输入数据就好了。如下图所示:
我们构建点和边,然后调用Graphx接口生成图,最后调用图的接口直接获取连通图。需要注意的是,Spark Graphx构建点和边时,id需要用Long类型的数字表示,所以我们需要维护一张用户id到数字id的维表。
//构建用户节点
val users: RDD[(VertexId, String)] =
spark.sparkContext.parallelize(Array((3L, "u3"), (7L, "u7"),(5L, "u5"), (2L, "u2"), (4L, "u4"),(6L, "u6"),(8L, "u8")))
//构建用户边
val relationships: RDD[Edge[String]] =
spark.sparkContext.parallelize(Array(Edge(7L, 3L,""), Edge(5L, 3L,""),Edge(5L, 2L,""), Edge(6L, 4L,""),Edge(8L, 6L,"")))
//组合节点和边构建图
val graph = Graph(users, relationships)
//从图中抽取出连通图
val components = graph.connectedComponents()
//获取连通图中的点,vertices是一个tuple类型,key分别为所有的顶点id,value为key所在的连通图id(连通图中顶点id最小值)
val vertices = components.vertices
得到的vertices是如下的k-v数据:
/**
* vertices:
* (6,4)
* (8,4)
* (3,2)
* (7,2)
* (5,2)
*
* 是一个tuple类型,key分别为所有的顶点id,value为key所在的连通图id(连通图中顶点id最小值)
*/
然后我们将边relationships与vertices求出每条边所在连通图里顶点id最小值。
val result = relationships.map(x =>{
(x.srcId,x.dstId.toString)
}).join(vertices)
.map(y =>{
// (7,(3,2)) => (2,(7,3))
(y._2._2,(y._1,y._2._1))
})
我们将结果存入图数据Neo4j,可视化后如下所示,可以看到我们得到了两个社群。
至此,我们利用Spark Graphx构建出了社群,每个社群都有自己的一个社群id,然后我们就可以基于社群做一些具体分析了,比如,我可以计算社群作弊率,并取出TOP N的社群,如下所示。
想及时了解更多大数据实践,请关注我的公众号《大数据技术进阶》
上面只是一个简单的示例,其实我们可以给点和边加上更多的属性,利用图的特性进行检索,可以更高效的检索出更多的信息。为了更方便的存储和查询社群内的数据,我们可以将社群存储到图数据库Neo4j。上面的社群图就是用Neo4j展示的,那么什么是Neo4j呢?下面我们简单的介绍下。
Neo4j简介
Neo4j是一个嵌入式的、基于磁盘的、具备完全的事务特性的图数据存储引擎。作为图数据库,Neo4j最大的特点是关系数据的存储。图数据库除了能够像普通的数据库一样存储一行一行的数据之外,还可以很方便的存储数据之间的关系信息。
例如,对于一个社交网络的用户数据库,你除了要存储每个用户的姓名、性别、喜好这些基本信息外,你还需要存储一个用户和哪些用户是朋友,和哪个用户是情侣这些关系数据,这个时候Neo4j这样的图数据库就可以派上用场啦。
通过下图,大家可以了解下什么是图数据库以及什么是关系数据。
在上图中,包含两个标签为"人"的数据节点,分别代表Ann和Dan两个用户。这两个数据节点还包含姓名、出生地等属性信息,用于表示两个用户的基本信息,就如同常规数据库中的两行数据。
除此之外,两个数据节点之间还包含两条关系数据,即Ann嫁给了Dan,Ann和Dan同居。利用这些关系数据,你就可以方便的作出基于关系的查询,例如你可以查询Ann跟谁结婚了,这就是图数据库的优势。
可能有人会说,上边写的这种关系数据结构,SQL也可以通过多表join等方法实现,那要Neo4j还有什么用?但毕竟术业有专攻,对于大量、复杂的关系数据处理,Neo4j在性能和使用方便程度上都是要远胜于SQL的。下边给大家简单总结下Neo4j的特点。
Neo4j的特点
- 像SQL一样的查询语言cypher
- 它遵循属性图数据模型
- 它通过使用Apache Lucence支持索引
- 它支持UNIQUE约束
- 它包含一个用于执行cypher命令的UI:Neo4j数据浏览器
- 它支持完整的ACID(原子性,一致性,隔离性和持久性)规则
- 它支持查询的数据导出到JSON和XLS格式
- 它提供了REST API,可以被任何编程语言(如Java,Spring,Scala等)访问
- 它提供了可以通过任何UI MVC框架(如Node JS)访问的Java脚本
- 它支持两种Java API:Cypher API和Native Java API来开发Java应用程序
- 支持高可用性主从集群部署。
Cypher语言
Cypher是Neo4j的图形查询语言,关键字大小写不敏感。语法和SQL很像,学起来相对简单。
基本格式
MATCH WHERE RETURN模式
() 表示节点
[] 表示关系,关系是有向的,连接的点分为源点和目标点
{} 表示属性,每个属性通过key:value的形式表示,多个属性之间用逗号隔开,关系也可以有属性标签
用来标识一个节点属于哪一类。一个节点可以有多个或0个标签。标签没有属性。
node:label1:label2 通过冒号给节点添加标签,通过冒号分隔多个标签基本的增删改查
插入一个节点
CREATE (n:Person {name : 'Andres'});
插入一条边
MATCH (a:Person),(b:Person) WHERE a.name = 'Node A' AND b.name = 'Node B‘ CREATE (a)-[r:Follow]->(b);
更新节点
MATCH (n:Person { name: 'Andres' }) SET n.name = 'Taylor';
删除节点
MATCH (n:Person { name:'Taylor' }) DETACH DELETE n;
删除边
MATCH (a:Person)-[r:Follow]->(b:Person) WHERE a.name = 'Node A' AND b.name = 'Node B‘ DELETE r;
查询一个节点的所有Follow
MATCH (:Person { name:'Taylor' })-[r:Follow]->(Person) RETURN Person.name;
查询一个节点最短路径
MATCH (ms:Person { name:'Node A' }),(cs:Person { name:'Node B' }), p = shortestPath((ms)-[r:Follow]-(cs)) RETURN p;
清空数据库
MATCH (n) DETACH DELETE n
Neo4j数据浏览器
通过Neo4j浏览器就可以直接进行图的查询。
Cypher演示示例
我们使用Cypher查询语言对Neo4j中的一个家庭进行建模,包括年龄,性别和家庭成员之间的关系等个人属性。我们创建了一些朋友来扩大我们的社交图,然后添加键/值对来生成每个用户看过的电影列表。最后,我们查询了我们的数据,使用图形分析来搜索一个用户没有看到但可能喜欢的电影。
创建家庭成员节点及关系
CREATE (person:Person {name: "Steven", age: 45}) RETURN person
CREATE (person:Person {name: "Michael", age: 16}) RETURN person
CREATE (person:Person {name: "Rebecca", age: 7}) RETURN person
CREATE (person:Person {name: "Linda",age:40}) RETURN person
MATCH (steven:Person {name: "Steven"}), (linda:Person {name: "Linda"}) CREATE (steven)-[:IS_MARRIED_TO]->(linda) return steven, linda
MATCH (michael:Person {name: "Michael"}), (rebecca:Person {name: "Rebecca"}) CREATE (michael)-[:IS_SIBLILNG]->(rebecca) return michael, rebecca
MATCH (steven:Person {name: "Steven"}), (michael:Person {name: "Michael"}) CREATE (steven)-[:HAS_CHILD]->(michael) return steven, michael
MATCH (steven:Person {name: "Steven"}), (rebecca:Person {name: "Rebecca"}) CREATE (steven)-[:HAS_CHILD]->(rebecca) return steven, rebecca
MATCH (linda:Person {name: "Linda"}), (michael:Person {name: "Michael"}) CREATE (linda)-[:HAS_CHILD]->(michael) return linda, michael
MATCH (linda:Person {name: "Linda"}), (rebecca:Person {name: "Rebecca"}) CREATE (linda)-[:HAS_CHILD]->(rebecca) return linda, Rebecca
添加朋友节点及关系,组成社交网络
MATCH (michael:Person {name: "Michael"}) CREATE (michael)-[:FRIEND]->(charlie:Person {name: "Charlie", age: 16}) RETURN michael, charlie
MATCH (michael:Person {name: "Michael"}) CREATE (michael)-[:FRIEND]->(koby:Person {name: "Koby"}) RETURN michael, koby
MATCH (michael:Person {name: "Michael"}) CREATE (michael)-[:FRIEND]->(grant:Person {name: "Grant"}) RETURN michael, grant
MATCH (rebecca:Person {name: "Rebecca"}) CREATE (rebecca)-[:FRIEND]->(jordyn:Person {name: "Jordyn"}) RETURN rebecca, jordyn
MATCH (rebecca:Person {name: "Rebecca"}) CREATE (rebecca)-[:FRIEND]->(katie:Person {name: "Katie"}) RETURN rebecca, katie
添加电影节点及关系,并携带打分属性
CREATE (movie:Movie {title:"Avengers"}) RETURN movie
MATCH (michael:Person {name:"Michael"}), (avengers:Movie {title:"Avengers"}) CREATE (michael)-[:HAS_SEEN {rating:5}]->(avengers) return michael, avengers
CREATE (movie:Movie {title:"Batman"}) RETURN movie
CREATE (movie:Movie {title:"Gone with the Wind"}) RETURN movie
CREATE (movie:Movie {title:"Spongebob Square Pants"}) RETURN movie
CREATE (movie:Movie {title:"Avengers 2"}) RETURN movie
MATCH (charlie:Person {name:"Charlie"}), (movie:Movie {title:"Batman"}) CREATE (charlie)-[:HAS_SEEN {rating:4}]->(movie) return charlie, movie
MATCH (charlie:Person {name:"Charlie"}), (movie:Movie {title:"Gone with the Wind"}) CREATE (charlie)-[:HAS_SEEN {rating:0}]->(movie) return charlie, movie
MATCH (koby:Person {name:"Koby"}), (movie:Movie {title:"Batman"}) CREATE (koby)-[:HAS_SEEN {rating:4}]->(movie) return koby, movie
MATCH (koby:Person {name:"Koby"}), (movie:Movie {title:"Avengers 2"}) CREATE (koby)-[:HAS_SEEN {rating:5}]->(movie) return koby, movie
MATCH (grant:Person {name:"Grant"}), (movie:Movie {title:"Spongebob Square Pants"}) CREATE (grant)-[:HAS_SEEN {rating:1}]->(movie) return grant, movie
MATCH (jordyn:Person {name:"Jordyn"}), (movie:Movie {title:"Spongebob Square Pants"}) CREATE (jordyn)-[:HAS_SEEN {rating:5}]->(movie) return jordyn, movie
MATCH (michael:Person {name: "Michael"}) SET michael.gender = "male" RETURN michael
MATCH (rebecca:Person {name: "Rebecca"}) SET rebecca.gender = "female" RETURN rebecca
最后我们通过下面语句查询steven的孩子的男性朋友看过而且打分大于3分的电影
MATCH (steven:Person {name:"Steven"})-[:HAS_CHILD]-(child:Person)-[:FRIEND]-(friend:Person)-[hasSeen:HAS_SEEN]-(movie:Movie) WHERE child.gender = "male" AND hasSeen.rating > 3 RETURN DISTINCT movie.title
总结
本文主要介绍了利用Spark Graphx实现了一个简单的连通图社群发现示例,并将社群存入到图数据库Neo4j中,同时进一步介绍了Neo4j的一些概念和使用,最后用Neo4j演示了一个社交网络的图检索示例。
想及时了解更多大数据实践,请关注我的公众号《大数据技术进阶》
基于Spark Grahpx+Neo4j 实现用户社群发现的更多相关文章
- 基于Spark的用户行为路径分析
研究背景 互联网行业越来越重视自家客户的一些行为偏好了,无论是电商行业还是金融行业,基于用户行为可以做出很多东西,电商行业可以归纳出用户偏好为用户推荐商品,金融行业可以把用户行为作为反欺诈的一个点,本 ...
- 客户流失?来看看大厂如何基于spark+机器学习构建千万数据规模上的用户留存模型 ⛵
作者:韩信子@ShowMeAI 大数据技术 ◉ 技能提升系列:https://www.showmeai.tech/tutorials/84 行业名企应用系列:https://www.showmeai. ...
- 苏宁基于Spark Streaming的实时日志分析系统实践 Spark Streaming 在数据平台日志解析功能的应用
https://mp.weixin.qq.com/s/KPTM02-ICt72_7ZdRZIHBA 苏宁基于Spark Streaming的实时日志分析系统实践 原创: AI+落地实践 AI前线 20 ...
- 京东基于Spark的风控系统架构实践和技术细节
京东基于Spark的风控系统架构实践和技术细节 时间 2016-06-02 09:36:32 炼数成金 原文 http://www.dataguru.cn/article-9419-1.html ...
- 基于Spark ALS构建商品推荐引擎
基于Spark ALS构建商品推荐引擎 一般来讲,推荐引擎试图对用户与某类物品之间的联系建模,其想法是预测人们可能喜好的物品并通过探索物品之间的联系来辅助这个过程,让用户能更快速.更准确的获得所需 ...
- 大数据实时处理-基于Spark的大数据实时处理及应用技术培训
随着互联网.移动互联网和物联网的发展,我们已经切实地迎来了一个大数据 的时代.大数据是指无法在一定时间内用常规软件工具对其内容进行抓取.管理和处理的数据集合,对大数据的分析已经成为一个非常重要且紧迫的 ...
- 基于 Spark 的文本情感分析
转载自:https://www.ibm.com/developerworks/cn/cognitive/library/cc-1606-spark-seniment-analysis/index.ht ...
- 基于微信小程序的用户列表点赞功能
代码地址如下:http://www.demodashi.com/demo/13997.html 一.前言 (1).适合人群 1.微信小程序开发者 2.前端工程师 3.想入门学习小程序开发的人员 4.想 ...
- 基于Spark的电影推荐系统(电影网站)
第一部分-电影网站: 软件架构: SpringBoot+Mybatis+JSP 项目描述:主要实现电影网站的展现 和 用户的所有动作的地方 技术选型: 技术 名称 官网 Spring Boot 容器 ...
随机推荐
- 常用的HTTP状态代码(4xx、5xx)详解
HTTP状态代码常用的如下: 400 无法解析此请求. 401.1 未经授权:访问由于凭据无效被拒绝. 401.2 未经授权: 访问由于服务器配置倾向使用替代身份验证方法而被拒绝. 401.3 未经授 ...
- kafka 名词概念
ProducerConsumerBrokerTopicPartitionConsumer Group分布式 Broker Kafka集群包含一个或多个服务器,这种服务器被称为brokerTop ...
- feign之间传递oauth2-token的问题和解决
在微服务架构里,服务与服务之间的调用一般用feign就可以实现,它是一种可视化的rpc,并且集成了ribbon的负载均衡能力,所以很受欢迎. 授权服务 在授权服务里,用户通过用户名密码,或者手机和验证 ...
- 【Spring源码解析】—— 策略模式在Spring中的应用
一. 什么是策略模式 策略模式的定义/含义:策略本身就是为了实现某一个目标而采取的一种工作方式,因此只要能够达成目标,则采取哪一种策略都可以:因此多种实际的策略之间是相互平行的. 注意 ...
- mysql 安装使用
本节掌握内容: MySQL的介绍安装.启动 windows上制作服务 MySQL破解密码 MySQL中统一字符编码 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 O ...
- Oracle数据库---序列、索引、同义词
--创建序列create sequence deptno_seqstart with 50increment by 10maxvalue 70cache 3; --为了方便演示,创建了一个和dept表 ...
- Nginx代理和负载均衡实验
一.构建两个tomcat容器并启动 [root@localhost bin]# ps -ef|grep tomcat root : pts/ :: /usr/bin/java -Djava.util. ...
- 安卓学习资料推荐《深入理解Android:卷2》下载
下载地址:百度云下载地址 编辑推荐 <深入理解Android:卷2>编辑推荐:经典畅销书<深入理解Android:卷I>姊妹篇,51CTO移动开发频道和开源中国社区一致鼎力推荐 ...
- 托管堆和垃圾回收(GC)
一.基础 首先,为了深入了解垃圾回收(GC),我们要了解一些基础知识: CLR:Common Language Runtime,即公共语言运行时,是一个可由多种面向CLR的编程语言使用的"运 ...
- Spring MVC源码(三) ----- @RequestBody和@ResponseBody原理解析
概述 在SpringMVC的使用时,往往会用到@RequestBody和@ResponseBody两个注解,尤其是处理ajax请求必然要使用@ResponseBody注解.这两个注解对应着Contro ...