说明:使用neo4j算法库时需引入跟neo4j数据库对应的算法库插件或自定义算法库
1.简介
Adamic Adac算法公式如下:
其中N(u)是与相邻的节点集u。
值A(x,y)=0表示两个节点不接近,而较高的值表示节点较近
该库包含一个计算两个节点之间接近都的函数
2.语法示例及使用场景
语法:
RETURN gds.alpha.linkprediction.adamicAdar(node1:Node, node2:Node, {
relationshipQuery:String,
direction:String
})
参数 | 类型 | 默认 | 可选 | 说明 |
node1 | 节点 | null | 无 | 节点 |
node2 | 节点 | null | 无 | 另一个节点 |
relationshipQuery | 字符串 | null | 是的 | 用于计算node1 和之间相似度的关系类型node2 |
direction | 字符串 | 两者 | 是的 | 用于计算node1 和之间相似度的关系方向node2 。可能的值为OUTGOING 、INCOMING 和BOTH |
Adamic Adac算法常用于社交链路中关系的预测,如好友推荐,美食推荐等等,目前国内社交市场火爆的抖音中就有好友推荐或者视频推荐,学习此算法后可以实现此功能
3.neo4j中Adamic Adac算法使用示例
1.初始化数据
CREATE
(zhen:Person {name: 'Zhen'}),
(praveena:Person {name: 'Praveena'}),
(michael:Person {name: 'Michael'}),
(arya:Person {name: 'Arya'}),
(karin:Person {name: 'Karin'}),
(zhen)-[:FRIENDS]->(arya),
(zhen)-[:FRIENDS]->(praveena),
(praveena)-[:WORKS_WITH]->(karin),
(praveena)-[:FRIENDS]->(michael),
(michael)-[:WORKS_WITH]->(karin),
(arya)-[:FRIENDS]->(karin)
2.预测Michael和Karin的Adamic Adar分数
MATCH (p1:Person {name: 'Michael'})
MATCH (p2:Person {name: 'Karin'})
RETURN algo.linkprediction.adamicAdar(p1, p2) AS score
结果:0.9102392266268373
3.我们还可以根据特定关系类型计算一对节点的分数
MATCH (p1:Person {name: 'Michael'})
MATCH (p2:Person {name: 'Karin'})
RETURN algo.linkprediction.adamicAdar(p1, p2, {relationshipQuery: 'FRIENDS'}) AS score
结果:0.0
4.源码解析
public double adamicAdarSimilarity(@Name("node1") Node node1, @Name("node2") Node node2,
@Name(value = "config", defaultValue = "{}") Map<String, Object> config) {
if (node1 == null || node2 == null) {
throw new RuntimeException("Nodes must not be null");
}
ProcedureConfiguration configuration = ProcedureConfiguration.create(config);
RelationshipType relationshipType = configuration.getRelationship();
Direction direction = configuration.getDirection(Direction.BOTH);
Set<Node> neighbors = new NeighborsFinder(api).findCommonNeighbors(node1, node2, relationshipType, direction);
return neighbors.stream().mapToDouble(nb -> 1.0 / Math.log(degree(nb, relationshipType, direction))).sum();
}
1.将传入的config参数放入ProcedureConfiguration的config中
ProcedureConfiguration configuration = ProcedureConfiguration.create(config);
2.获取ProcedureConfiguration类config中relationshipQuery参数(此参数为关系名称)
RelationshipType relationshipType = configuration.getRelationship();
3.获取config中direction参数,此为指定关系方向
Direction direction = configuration.getDirection(Direction.BOTH);
4.条件返回节点1的关系节点,并且过滤掉与节点2没有关系的节点(即取节点1和节点2同时有relationshipType关系的且方向为direction的节点)
Set<Node> neighbors = new NeighborsFinder(api).findCommonNeighbors(node1, node2, relationshipType, direction);
5.遍历4中结果节点,并获取每个节点的关系节点数,对结果取1/对数值Math.log(result),在此基础上再求和,得到分数值
由上源码可知:
- 使用此函数时,node1和node2不能为空
- config中可传入参数relationshipQuery和direction