协同过滤cypher与neo4j中的属性

时间:2017-03-14 14:52:33

标签: neo4j cypher graph-databases collaborative-filtering

我正在使用neo4j来设置推荐系统。我有以下设置:

节点

  • 用户
  • 电影属性(例如流派)

关系

  • __declspec(dllexport)
  • (m:Movie)-[w:WEIGHT {weight: 10}]->(a:Attribute)

以下是它的外观图表:

enter image description here

我现在正试图弄清楚如何应用协同过滤方案,其工作原理如下:

  1. 检查(u:User)-[r:RATED {rating: 5}]->(m:Movie)喜欢哪些属性(隐含地喜欢看电影)
  2. 查找喜欢这些类似属性的类似user
  3. 将热门电影推荐给用户未见过的other users,但类似的user已经看过。
  4. 显然,每个属性对每部电影都有一定的权重。例如。类型other users对于指环王而言可以具有adventure的权重,但对于泰坦尼克号来说可以具有10的权重。

    此外,系统需要考虑每部电影的评分。例如。如果5已经评定指环王other user,那么他/她的范围之王的属性将按5而不是5进行缩放。对隐式属性进行评级的10也接近user应该推荐这部电影,而不是另一个评价相似属性的用户。

    我首先只推荐其他用户评价的其他电影,但我不确定如何考虑关系评级和重量。它也没有用:

    5

2 个答案:

答案 0 :(得分:4)

从数学上讲,您所寻找的是两个用户之间的简化Jaccard index。也就是说,它们的相似之处在于它们有多少共同点。我说简化是因为我们没有考虑他们不同意的电影。基本上,按照您的订单,它将是:

1)获取每个用户的每个属性的总权重。例如:

MATCH (user:User{name:'user1'})
OPTIONAL MATCH (user)-[r:RATED]->(m:Movie)->[w:WEIGHT]->(a:Attribute)
WITH user, r.rating * w.weight AS totalWeight, a
WITH user, a, sum(totalWeight) AS totalWeight

我们需要最后一行,因为每个Movie-Attribute组合都有一行

2)然后,我们得到具有相似品味的用户。这是一个性能危险区域,有些过滤可能是必要的。但是粗暴强迫它,我们让用户喜欢10%错误中的每个属性(例如)

WITH user, a, totalWeight*0.9 AS minimum, totalWeight*1.10 AS maximum
MATCH (a)<-[w:WEIGHT]-(m:Movie)<-[r:RATES]-(otherUser:User)
WITH user, a, otherUser
WHERE w.weight * r.rating > minimum AND w.weight * r.rating < maximum
WITH user, otherUser

所以现在我们有一行(由于最后一行而是唯一的)与任何匹配的其他用户。在这里,说实话,我需要尝试确定是否包含只有1种类型匹配的其他用户..如果是,则需要额外的过滤器。但我认为应该在我们开始之后继续这样做。

3)现在很容易:

MATCH (otherUser)-[r:RATES]->(m:Movie)
WHERE NOT (user)-[:RATES]->(m)
RETURN m, sum(r.rating) AS totalRating ORDER BY totalRating DESC

如前所述,棘手的部分是2),但在我们知道如何进行数学运算之后,应该会更容易。哦,关于数学,为了使它正常工作,电影的总重量应该加1(normalizing)。在任何其他情况下,电影总重量之间的差异会导致不公平的比较。

我没有经过适当的研究(纸张,铅笔,方程式,统计数据)并在样本数据集中尝试代码。无论如何,我希望它可以帮到你!

如果你想要这个推荐而不考虑用户评级或属性权重,那么分别用r.rating或w.weight代替1)和2)中的数学就足够了。仍然会使用费率和权重关系,因此,冒险电影的狂热消费者将推荐冒险电影的消费者使用电影,但不会按照我们选择的等级或属性权重进行修改。

编辑:编辑代码以修复评论中讨论的语法错误。

答案 1 :(得分:1)

回答第一个问题:

检查用户喜欢哪些属性(隐含地喜欢看电影)

MATCH (user:User)
OPTIONAL MATCH (user)-[r:RATED]->(m:movie)
OPTIONAL MATCH (m)-[r:RATED]->(a:Attribute)
WHERE user.uid = "user4"
RETURN user, collect ({ a:a.title })

这是一个子查询构造,您可以在其中找到用户评分的电影,然后查找电影的属性,最后返回喜欢的属性列表

如果需要整个节点,可以将return语句修改为 收集(a)作为属性