3

我有一个带有 2 种节点的图:person& food。我有 1 种关系 -Ate有一个属性 - count。每次 aperson a foodcount关系的属性就会增加。

person我的目标是计算两个节点之间的相似度。我在网上找到了这个算法来计算相似度,我想用它。如何将其转换为 Cypher Query ?

sim = 0
for k = 1 to n:
  sim = sim + (1 - Math.abs((N1k/H1 - N2k/H2)))(N1k+N2k)/(H1+H2)

在哪里:

sim = 相似性指数
H1 = 1food吃掉的物品 总数 H2 = 2吃掉的物品总数 n = 共有节点数 N1k = 1 吃掉“ n”个常见物品中的第k 个”物品的 次数 N2k = 2 吃过“ n”个常见物品中的“第 k 个”物品的次数person
foodperson
food
personfoodfood
personfoodfood

我已经准备好了骨架,但我只是不知道如何进行。

Start me=node(name="%s")
MATCH me-[r1:Ate]->some_food<-[r2:Ate]-other_dude
// do some stuff here to find out sim
RETURN other_dude, sim
ORDER BY sim DESC
LIMIT 10

帮助表示赞赏!

4

2 回答 2

5

我在 Neo4j 邮件列表上看到了这个问题,但昨天无法回复。

我是 Cypher 的新手。但是,我可以帮助您解决 Gremlin 中的问题。我可以创建一个类似于您的图表并在其上运行 Gremlin 遍历。

我的图表看起来像:

gremlin> g.v(1,2,3,4)_().outE('eats').inV.path{it.name}{it.count}{it.name}  
==>[Neo, 5, Meat]
==>[Neo, 1, Cheese]
==>[Neo, 4, Chicken]
==>[Morpheus, 3, Bread]
==>[Morpheus, 3, Cheese]
==>[Morpheus, 2, Chicken]
==>[Trinity, 1, Apple]
==>[Trinity, 2, Bread]
==>[Trinity, 4, Meat]
==>[Trinity, 2, Cheese]
==>[Smith, 3, Apple]
==>[Smith, 4, Ham]
==>[Smith, 5, Pork]
gremlin> 

我编写了一个遍历来为任何一个顶点生成相似性索引,由start剩余的 ID 数组指示。我的最终遍历看起来像:

simarray=[];start=3;
[1,2,4].each{
                p1=start;p2=it;
                first=g.v(p1);
                second=g.v(p2);
                sim=0;
                h1=first.out('eats').count().toFloat();
                h2=second.out('eats').count().toFloat();
                first.outE('eats').as('edges')
                .inV.in('eats').has('id',second.id).back('edges')
                .each{
                        n1k = it.count;
                        n2k = it.inV.inE('eats').outV
                                .has('id', second.id).back(2).count.next();
                        sim = sim + (1 - ((n1k/h1)-(n2k/h2)).abs())*(n1k+n2k)/(h1+h2)
                        };
                simarray.add(sim)
            };
simarray

输出:

gremlin> simarray=[];start=3;[1,2,4].each{p1=start;p2=it; first=g.v(p1); second=g.v(p2); sim=0; h1=first.out('eats').count().toFloat(); h2=second.out('eats').count().toFloat(); first.outE('eats').as('edges').inV.in('eats').has('id',second.id).back('edges').each{n1k = it.count; n2k = it.inV.inE('eats').outV.has('id', second.id).back(2).count.next(); sim = sim + (1 - ((n1k/h1)-(n2k/h2)).abs())*(n1k+n2k)/(h1+h2)}; simarray.add(sim)};simarray
==>0.7857142857142856
==>0.7142857142857143
==>0.14285714285714285

上面的遍历直接转化为您的公式/计算。它可以针对图形遍历的性能进行优化。此外,您可能需要阅读 Gremlin 的文档以详细了解相关内容。 https://github.com/tinkerpop/gremlin/wiki

除了您已经是 Neo4j 邮件列表的成员之外,您还可以在 Gremlin 邮件列表上提出您的疑问: https ://groups.google.com/group/gremlin-users

于 2012-05-30T06:07:57.250 回答
2

对公式不太好,但是有两篇关于计算相似度的博客文章您可能会感兴趣-您可以随时根据您的公式对其进行调整以使其更精确-

这个使用 Gremlin: http ://blog.everymansoftware.com/2012/02/similarity-based-recommendation-engines.html

这使用 Cypher: http ://thought-bytes.blogspot.in/2012/02/similarity-based-recommendations-with.html

于 2012-05-29T03:37:26.043 回答