推荐系统多维度方法
引言
谈到推荐系统,我总是想起80年代情景喜剧《欢聚》的主题曲。以下是原因
"你想去人们认识你的地方,那里的人都是一样的" - 基于内容的
"你想去可以看到的地方,我们的烦恼都是一样的" - 协同过滤
"从所有烦恼中休息一下,当然会有很大帮助。你不想逃离一下吗?"...在哪里,和谁?- 上下文感知。
在这里,我想使用Neo4j根据上下文信息提供餐厅推荐。
什么是上下文?
上下文是可以用来描述实体情境的任何信息。实体是指被认为与用户和应用程序之间交互相关的人、地点或对象,包括用户和应用程序本身(AK Dey & GD Abowd - 人机交互大会(CHI 2000),第5卷/第1期,第4-7页,2001)。
最常见的上下文类型是身份(“谁”)、活动(“什么”)、时间(“何时”)和位置(“哪里”),并且可以使用这些信息来确定“为什么”会出现这种情况。
传统的推荐系统使用两个实体(二维)用户和物品。通过使用多维度方法包含上下文信息,可以使这种推荐更加个性化。
应用于餐厅推荐
从https://archive.ics.uci.edu/ml/datasets/Restaurant+%26+consumer+data导入与墨西哥相关的餐厅和消费者数据。
用户数据包含位置、习惯(如吸烟、饮酒)、婚姻状况、菜系、预算以及许多其他信息。对于用户,我们可以将每个上下文(如吸烟、菜系、预算)作为一个维度。

餐厅数据包括位置、菜系、吸烟、酒精、价格和其他信息。对于餐厅,我们也将有多个维度,以便根据用户的偏好提供更好的餐厅选择。
下面显示了三维方法的图示描述

用户立方体中的三个维度是用户、吸烟和菜系,餐厅立方体中的三个维度是餐厅、吸烟和菜系。用户立方体的彩色切片代表喜欢相同菜系但对吸烟偏好不同的用户。然后,这些选择将用于选择与所选用户选择匹配的餐厅。餐厅立方体的彩色切片呈现与用户所选选择匹配的餐厅。
相同的方法也适用于更高的维度。
设置
四个数据文件:Users_50.csv(选择50个用户)UCuisine.csv(用户/菜系)Restaurants.csv RestCuisine.csv(餐厅/菜系)
用于设置数据库的Cypher查询
使用此查询可以更好地可视化USER_PROFILE和RESTAURANT路径。
MATCH (c)-[r:USER_PROFILE|RESTAURANT]->(n)-[]->(p)
WHERE n.uid IN['U1001', 'U1002', 'U1003'] or n.pid IN [132609, 132613, 132630]
RETURN c, n, p LIMIT 20;

左半部分是餐厅,右半部分是用户画像。
根据用户偏好推荐餐厅
三个偏好:墨西哥菜、禁烟和中等价位。
//Users with selected choices..............
MATCH (c)-[]->(n)-[:CUISINE]->(r)-[:LIKES]->(t:Food {name: "Mexican"})
WITH COLLECT (n) as nodes, t
UNWIND nodes as n1
MATCH (c)-[]->(n1)-[:HABITS]->(q)-[:SMOKER]->(v:Smoker {attr1: "false"})
WITH COLLECT (n1) as nodes, t, v
UNWIND nodes as n2
MATCH (c)-[]->(n2)-[:HABITS]->(q)-[:BUDGET]->(v1:Budget {attr13: "medium"})
WITH v1, t, v MATCH (c)-[]->(n)-[:CUISINE]->(r)-[:LIKES]->(t:Food {name: "Mexican"})
WITH COLLECT (n) as nodes, t
UNWIND nodes as n1
MATCH (c)-[]->(n1)-[:HABITS]->(q)-[:SMOKER]->(v:Smoker {attr1: "false"})
WITH COLLECT (n1) as nodes, t, v
UNWIND nodes as n2
MATCH (c)-[]->(n2)-[:HABITS]->(q)-[:BUDGET]->(v1:Budget {attr13: "medium"})
WITH v1, t
//WITH v1, t, v1, n2
//RETURN n2.uid as User, t.name as Cuisine, v.attr1 as Smoker, v1.attr13 as Budget;
// Find the restaurants that match the user preferences......
MATCH (c)-[]->(n2)-[:REST_CUISINE]->(p:Cusine {name: t.name})
WITH COLLECT(n2) as pn, v1
UNWIND pn as n3
MATCH (c)-[]->(n3)-[:FEATURES]->(q1:Features {price: v1.attr13, smoking: "none"})
WITH COLLECT(n3) as pn
UNWIND pn as n4
WITH DISTINCT n4
MATCH (c)-[]->(n4)-[:ADDRESS]-(k)
RETURN n4.name as Restaurant, k.city as City;
四个偏好:日式料理、禁烟、中等价位和氛围(朋友)。
MATCH (c)-[]->(n)-[:CUISINE]->(r)-[:LIKES]->(t:Food {name: "Japanese"})
WITH COLLECT (n) as nodes, t
UNWIND nodes as n1
MATCH (c)-[]->(n1)-[:HABITS]->(q)-[:SMOKER]->(v:Smoker {attr1: "false"})
WITH COLLECT (n1) as nodes, t, v
UNWIND nodes as n2
MATCH (c)-[]->(n2)-[:HABITS]->(q)-[:BUDGET]->(v1:Budget {attr13: "medium"})
WITH COLLECT (n2) as nodes, t, v, v1
UNWIND nodes as n3
MATCH (c)-[]->(n3)-[:HABITS]->(q)-[:AMBIENCE]->(v2:Ambnce {attr4: "friends"})
WITH COLLECT (n3) as nodes, t, v, v1, v2
UNWIND nodes as n4
WITH t, v1
//WITH v, t, v1, v2, n4
//RETURN n4.uid as User, t.name as Cuisine, v.attr1 as Smoker, v1.attr13 as Budget, v2.attr4 as Ambience;
MATCH (c)-[]->(n2)-[:REST_CUISINE]->(p:Cusine {name: t.name})
WITH COLLECT(n2) as pn, v1
UNWIND pn as n3
MATCH (c)-[]->(n3)-[:FEATURES]->(q1:Features {price: v1.attr13, smoking: "none", ambience: "familiar"})
WITH COLLECT(n3) as pn2
UNWIND pn2 as n4
WITH DISTINCT n4
MATCH (c)-[]->(n4)-[:ADDRESS]-(k)
RETURN n4.name as Restaurant, k.city as City;
此页面是否有帮助?