我正在使用neo4j建立一个推荐系统。我有以下设置:
节点:
Relationships
(m:Movie)-[w:WEIGHT {weight: 10}]->(a:Attribute)(u:User)-[r:RATED {rating: 5}]->(m:Movie)下面是它的外观图:

我现在正努力研究如何应用协作过滤方案,其工作方式如下:
user喜欢的属性(通过喜欢电影隐式地检查)other usersuser推荐顶级电影,用户还没有看过,但是other users也看过类似的电影。条件显然是每个属性对每部电影都有一定的权重。例如,adventure的重量可以是“指环王”的10,而“泰坦尼克号”的5可以是重量。
此外,系统需要考虑到每部电影的收视率。例如,如果other user对指环王5进行了评级,那么他/她对恒河之王的属性将由5而不是10来衡量。对隐式属性进行评级的user也应该接近于5,因此应该推荐该影片,而不是其他将相似属性评为更高的用户。
一开始,我只是简单地推荐了其他用户所评价的其他电影,但我不知道如何考虑关系评分和权重。它也不起作用:
MATCH (user:User)-[:RATED]->(movie1)<-[:RATED]-(ouser:User),
(ouser)-[:RATED]->(movie2)<-[:RATED]-(oouser:User)
WHERE user.uid = "user4"
AND NOT (user)-[:RATED]->(movie2)
RETURN oouser发布于 2017-04-22 21:22:47
从数学上讲,您要寻找的是两个用户之间的简化Jaccard指数。也就是说,根据他们有多少共同之处,他们有多相似。我说简化是因为我们没有考虑到他们不同意的电影。基本上,按照你的命令,它将是:
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-属性组合都有一行。
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所以现在我们有一个行(因为最后一行是唯一的)与任何匹配的otherUser。在这里,老实说,我需要确保如果只包含1种类型的otherUsers。如果是的话,就需要一个额外的过滤器。但我觉得应该在我们完成这件事之后。
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 (正规化 )。在任何其他情况下,电影总重量之间的差异会导致不公平的比较。
我写这篇文章时没有经过适当的研究(论文、铅笔、方程式、统计),也没有在样本数据集中尝试这些代码。我希望它能对你有帮助!
如果您希望在不考虑用户评分或属性权重的情况下执行此建议,那么只需分别用r.rating或w.weight替换1)和2)行中的数学就足够了。费率和权重关系仍将被使用,因此,例如,冒险电影的消费者推荐热衷于冒险电影的消费者,而不是按我们选择的评级或属性权重来修改电影。
编辑:编辑以修正注释中讨论的语法错误的代码。
发布于 2017-03-26 06:37:01
回答您的第一个问题:
检查用户喜欢的属性(通过喜欢电影隐式地)
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 })它是一个子查询结构,在其中您可以找到用户分级的电影,然后查找电影的属性,最后返回喜欢的属性列表。
如果需要整个节点,可以将返回语句修改为 (a)作为属性
https://stackoverflow.com/questions/42789290
复制相似问题