强连通和连通算法在关联图谱中的应用
本文介绍社群发现算法在关联图谱中的应用。社群发现算法是图算法中的一种,图算法是图分析的工具之一。
图算法提供了一种最有效的分析连接数据的方法,它们描述了如何处理图以发现一些定性或者定量的结论。
图算法基于图论,利用节点之间的关系来推断复杂系统的结构和变化。我们可以使用这些算法来发现隐藏的信息,验证业务假设,并对行为进行预测。
一、图论中基本名词
- 1. 连通图(Connected Graphs):图中任意两点之间都有路相连。
- 2. 非连通图(Disconnected Graphs):图中存在两点之间没有路相连。
- 3. 有向图(Directed Graphs):节点的关系指定了方向。
- 4. 无向图(Undirected Graphs):节点的关系是双向的。
- 5. 加权图(Weighted Graphs): 节点或边上赋予权重。
- 6. 未加权图(Unweighted Graphs):节点和边上都没有权重。
- 7. 循环图(Cyclic Graphs):图中存在一些特殊的路径,它们的起点和终点是同一个节点。注:有向图的路径须需遵循边的方向。
- 8. 非循环图(Acyclic Graphs):图中不存在循环路径。
- 9. 子图(Subgraph):一张图的一部分,指节点集和边集分别是某一图的节点集的子集和边集的子集的图。
二、导入数据
把点和关系数据放到import文件夹下,运行如下语句:
using periodic commit 10000 load csv with headers from "file:/node_gzh.csv" as line with line create (:gzh {item:line.item, trans_amount_sum:line.trans_amount_sum, trans_cnt:line.trans_cnt, type:line.type});
CREATE INDEX ON :gzh(item)
using periodic commit 10000 load csv with headers from "file:/node_rela_gzh.csv" as line match (from:gzh {item: line.item_l}),(to:gzh {item:line.item_r}) merge (from)-[c:gzh{relation:line.relation}]-(to)
更详细的数据导入说明参见文章:neo4j中导入数据的两种常用方式(千万级和亿级)。
接下来详细阐述社群发现算法在关联图中的应用。
三、强连通算法
1 名词解释
1.两个节点强连通:在有向图G中,若两个节点u和v间有一条从u到v的有向路径,同时还有一条从v到u的有向路径,则称两个节点强连通。
2.强连通图:若有向图G的每两个节点都强连通,则称图G是一个强连通图。
3.强连通分量(Strongly Connected Components,简称SCC):有向图的极大强连通子图。
2 在图中找强连通分量的具体算法
在neo4j中运行如下语句,即可找出图中所有的强连通分量。
CALL algo.scc.stream("gzh","gzh")
YIELD nodeId, partition
MATCH (u:gzh) WHERE id(u) = nodeId
RETURN u.item AS item, partition
注:使用社群发现算法需要在neo4j中安装algo模块,可自行到网上搜寻教程安装。
参数说明:
scc:强连通分量的缩写,代表算法的类型。
gzh:第一个gzh代表节点的标签,第二个gzh代码关系的类型,我在导入数据时都写成了gzh所以是一样的,可根据具体数据调整。
(u:gzh):填入节点标签。
u.item:返回节点的属性,可根据需要自行调整。
得到结果如下:
3 数据分析与查询
对下载(页面中下载箭头)的数据用透视表进行分析排序,得到每一强连通分量中商户的数量,具体结果如下:
为了让大家更清晰地理解这个算法,从结果中挑一个(partition为8634)强连通分量进行回查展示。
在neo4j中运行如下语句:
WITH ['8635',
'8671',
'8698',
'16995',
'17808',
'18121',
'18622',
'18626',
'18688',
'18976',
'24924'
] AS arr
MATCH p=(n)-[]->(m)
WHERE n.item IN arr or m.item IN arr
RETURN p
with中的数据是partition为8634(11个点)组别中的item(商户编号),该语句查找这些节点所有对外的关系构成的子图。
得到结果如下:
图中总计13个点,红框中是11个点构成的强连通分量,任意两个节点之间都强连通。
由于查询的是这个强连通分量中所有点对外关系构成的子图,查到了item为61886的节点还有两个对外的关系。
虽然这11个点有到这两个点的路径,但是这两个点没有11个点的路径,所有这两个点不是这个强连通分量中的一员。
四、连通算法
顾名思义,连通算法是在全量图中寻找连通的子图,其中同一子图中的所有节点构成一个连通的组件。
1 一个通俗易懂的小例子
小胖、小华、小明、小雪、小红、小芳是同班同学,由于疫情好久都没有见面了。
小胖给小华打了3分钟电话,小胖给小明打了10分钟电话。小雪给小红打了11分钟电话,小红给小芳打了5分钟电话。
由上面的描述知小胖、小华、小明三人联系过,小雪、小红、小芳三人联系过。在neo4j中把如上关系转成关联图。
具体语句如下:
create (xiaopang:Person {name:'小胖'})
create (xiaohua:Person {name:'小华'})
create (xiaoming:Person {name:'小明'})
create (xiaoxue:Person {name:'小雪'})
create (xiaohong:Person {name:'小红'})
create (xiaofang:Person {name:'小芳'})
CREATE (xiaopang)-[:LINK {weight: 3}]->(xiaohua)
CREATE (xiaopang)-[:LINK {weight: 10}]->(xiaoming)
CREATE (xiaoxue)-[:LINK {weight: 11}]->(xiaohong)
CREATE (xiaohong)-[:LINK {weight: 5}]->(xiaofang);
先创建点,再创建关系,把通话时长作为关系的权重。
创建好的图如下(有向图):
下面用连通算法寻找大图中的子连通图。
2 未加权连通图算法
不考虑边的权重,在整个图中寻找连通子图,具体语句如下:
CALL algo.unionFind.stream('Person', 'LINK')
YIELD nodeId, setId
RETURN algo.asNode(nodeId).name AS Name, setId AS ComponentId
ORDER BY ComponentId, Name
参数说明:
unionFind:连通分量的英文,代表算法的类型。
Person代表节点标签,LINK代表关系类型。如果不写代表在所有标签和关系中寻找连通子图。
最后返回了组别id和对应节点的名称,并对组别进行排序展示。
注:如果只有一种节点和一种关系可以省略('Person', 'LINK')括号中的内容,直接写一个括号即可。
得到结果:
可以发现小胖、小华、小明三人分在一组,小雪、小红、小芳分在一组。
说明连通不考虑关系的方向,可以理解成把图当成无向图处理,两个点之间只要有边就连通。
那么这个算法有什么用呢?
如果一个犯罪团伙之间有相互转账的关联关系,可以通过连通算法把所有有关联的人员放到一个组别(一张子图)中进行分析。
3 加权连通图算法
在官网中给出了加权连通图算法,可以通边和边的权重对连通图进行一个更细的划分。
具体语句如下:
CALL algo.unionFind.stream('Person', 'LINK', {weightProperty: 'weight',threshold: 4,concurrency:1})
YIELD nodeId, setId
RETURN algo.asNode(nodeId).name AS Name, setId AS ComponentId
ORDER BY ComponentId, Name
如果把threshold设为4,由于小胖和小华的关系weight为3,会把小华单独列为一类。
但是我在运行该代码时一直在报错,欢迎大家在研究过程中和我探讨。
接下来会研究标签传播算法和模块度算法在知识图谱中的具体应用,欢迎大家持续关注。
参考文献
https://blog.csdn.net/Revjie/article/details/100151420
https://blog.csdn.net/qq_42712462/article/details/81409208
https://neo4j.com/docs/graph-algorithms/current/algorithms/wcc/#algorithms-wcc-syntax
https://baike.baidu.com/item/%E5%BC%BA%E8%BF%9E%E9%80%9A%E5%88%86%E9%87%8F/7448759?fr=aladdin
- linux配置ssh互信实现免密登陆
- uva--1339 - Ancient Cipher(模拟水体系列)
- Python获得13位unix时间戳
- Centos7下LVM对文件系统进行在线扩容
- centos7编译安装Redis
- hdu----(5023)A Corrupt Mayor's Performance Art(线段树区间更新以及区间查询)
- Redis单线程架构
- hdu----(4521)小明系列问题——小明序列
- Redis数据结构和内部编码
- Redis全局命令
- nginx使用GeoIP限制国家访问
- shell获取每月最后一天
- 定向转发和重定向实现 <select >下拉表单数据传送
- Python:获取某月第一天和最后一天
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 一起来学matlab-matlab学习笔记10 10_5 通用字符串操作和比较函数
- 一个案例彻底弄懂如何正确使用 mysql inndb 联合索引
- 一起来学matlab-matlab学习笔记11 11_2 高维数组处理和运算 squeeze, ind2sub, sub2ind
- matlab结构体 rmfield,arrayfun,structfun,struct2cell,cell2struct
- PHP函数参数传递方法的具体改进技巧
- matlab学习笔记11_3 高维数组处理 filp, shiftdim, size, permute, ipermute
- 看完这篇文章,你的Linux基础就差不多了
- jzy3D从入门到弃坑
- git丢弃本地修改的所有文件(新增、删除、修改)
- Jmetal设置Solution Variables
- git log 查看某文件的修改历史
- 进程和线程的概念、区别和联系
- CDATA和转义字符
- 递归解决全排列问题
- 支付的时候的参数校验