美文网首页编程那些事每天写1000字
neo4j recommendation sandbox推荐系统

neo4j recommendation sandbox推荐系统

作者: redcohen | 来源:发表于2019-03-12 11:52 被阅读90次

    以下内容大多都翻译自neo4j官方沙盒文档,仅做了翻译及必要说明。
    -redcohen

    1 . 注册&登录

    首先,注册一个沙盒账号。


    沙盒登录页

    然后,按照提示登录类似如下网址(浏览器也可以自动跳转):

    https://10-0-1-148-?????.neo4jsandbox.com/browser/
    
    沙盒浏览器demo

    如果第二天以后不能访问了,记得在沙盒页面的detail选项卡页中找到密码(账号一般是neo4j),登录认证下即可。如下图


    账号密码demo

    2. 推荐系统简介

    推荐里面分为两种:基于内容的过滤和协同过滤。

    2.1 基于内容的过滤

    一句话表达:根据商品推荐商品

    content-based filtering

    在上面这个电影的例子里面,假设'Casino'是一个你已看的电影,那么就可能给你推荐'Goodfellas'。因为它们从风格/导演/主演等几个角度都有相同之处。

    代码类似如下:

    MATCH p=(m:Movie {title: "Casino"})-[:ACTED_IN|:IN_GENRE|:DIRECTED*2]-()
    RETURN p LIMIT 25
    

    2.2 协同过滤

    一句话表达:根据人推荐商品


    collaborative filtering

    从上图例子,Guy Davis和Misty Williams看电影的趣味很相似,那么前者还看了'Net, The', 'Basketball Diaries, The'这两部电影,那么就可以推荐给后者。

    官网给的两个代码段都不是很贴意,所以省去!

    3. 深入: 基于内容的过滤

    基于内容的过滤是基于商品(item)的属性(attributes)、特性(traits)来寻找相类似的商品。

    3.1 基于共同属性推荐

    对于电影,最简单的相似度是基于genres这个属性。

    内容推荐之功夫熊猫

    比如上图,根据'功夫熊猫3'的genre属于动作、冒险类,可以推荐出'碟中谍5:神秘国度'

    实操下,执行如下代码,在沙盒中召回和'Inception'类似的影片。

    // Find similar movies by common genres
    MATCH (m:Movie)-[:IN_GENRE]->(g:Genre)<-[:IN_GENRE]-(rec:Movie)
    WHERE m.title = "Inception"
    WITH rec, COLLECT(g.name) AS genres, COUNT(*) AS commonGenres
    RETURN rec.title, genres, commonGenres
    ORDER BY commonGenres DESC LIMIT 10;
    
    基于内容推荐召回Inception类似影片

    3.2 来点个性化

    以上方法完全忽略用户的个性化,因此无法达到千人千面,现在考虑个性化。

    推荐用户A没看过的但和已看过的风格类似的影片。

    实操代码类似如下:

    // Content recommendation by overlapping genres
    MATCH (u:User {name: "Angelica Rodriguez"})-[r:RATED]->(m:Movie),
      (m)-[:IN_GENRE]->(g:Genre)<-[:IN_GENRE]-(rec:Movie)
    WHERE NOT EXISTS( (u)-[:RATED]->(rec) )
    WITH rec, [g.name, COUNT(*)] AS scores
    RETURN rec.title AS recommendation, rec.year AS year,
    COLLECT(scores) AS scoreComponents,
    REDUCE (s=0,x in COLLECT(scores) | s+x[1]) AS score
    ORDER BY score DESC LIMIT 10
    

    沙盒结果如下:


    来点个性化之内容过滤

    来看下代码。
    第一行表达匹配A这个人看的电影涉及到的genre,以此去找rec候选。
    第二行WHERE这句,表示A没RATE过,也就是没看过。
    第三行WITH这句,表示看下每个推荐候选rec,它对应的genre都出现了几次(在第一行的匹配中),也就是这种类似的电影A看过多少次。做下聚集,作为scores。因为每个电影rec都可能属于多个genre,因此后半部分要用一个list[]表达。
    第四行RETURN这句,表示要返回的数据项,第一个是电影title,第二个year,第三个把scorers归集为scoreComponent,第四个是对第三个中每项的第二个元素求和为score。
    第五行ORDER这句,表示按score降序排列,取前10个。

    3.3 多种属性,加权式计算相似度

    上文中只是用了genre一个属性,而且是很粗糙的累加计分策略。本节展示下结合多种属性/特性,并且采用一些简单的加权(weighting)策略。

    比如,除了gener,我们还可以根据演员/导演等等的相似度来判断两个电影的相似度。
    示例代码:

    // Find similar movies by common genres
    MATCH (m:Movie) WHERE m.title = "Wizard of Oz, The"
    MATCH (m)-[:IN_GENRE]->(g:Genre)<-[:IN_GENRE]-(rec:Movie)
    
    WITH m, rec, COUNT(*) AS gs
    
    OPTIONAL MATCH (m)<-[:ACTED_IN]-(a:Actor)-[:ACTED_IN]->(rec)
    WITH m, rec, gs, COUNT(a) AS as
    
    OPTIONAL MATCH (m)<-[:DIRECTED]-(d:Director)-[:DIRECTED]->(rec)
    WITH m, rec, gs, as, COUNT(d) AS ds
    
    RETURN rec.title AS recommendation, (5*gs)+(3*as)+(4*ds) AS score ORDER BY score DESC LIMIT 100
    

    沙盒效果如下:


    多属性加权推荐

    来解读下代码。
    第一行MATCH这句,表示锚点是绿野仙踪这个电影,用m代表。
    第二行MATCH这句,表示召回和m拥有共同genre的电影候选用rec代表,同时也召回genre用g代表。
    第三行WITH这句,往下传递(类似管道)m,rec, 并且把g统计总数记为gs。
    第四行OPTIONAL MATCH这句,考虑在m,rec的限定下,有交集的演员a。
    第五行WITH这句,往下传递m, rec, gs, 并把a统计总数记为as。
    第六行~第七行,类似处理导演。

    第八行RETURN这句,最主要看score这块,把genre, actor, director这三个属性的计数分别乘以5,3,4的权重,然后相加成为最后的score。

    3.4 一个较为鲁棒的相似度: Jaccard距离

    前文所谓‘相似度’,说法不准确。只能算一个相关度的计算公式。而要成为一个严格意义上的相似度度量,则需要满足很多条件。比如:归一、稳定、语义清晰等等。

    本节介绍一个最最简单的相似度度量:Jaccard相似度。主要用来衡量两个集合的相似度。


    jaccard similarity

    具体cypher实现,先看只用在genre上的: 用Jaccard相似度看和'Inception'的genre相似的。

    MATCH (m:Movie {title: "Inception"})-[:IN_GENRE]->(g:Genre)<-[:IN_GENRE]-(other:Movie)
    WITH m, other, COUNT(g) AS intersection, COLLECT(g.name) AS i
    MATCH (m)-[:IN_GENRE]->(mg:Genre)
    WITH m,other, intersection,i, COLLECT(mg.name) AS s1
    MATCH (other)-[:IN_GENRE]->(og:Genre)
    WITH m,other,intersection,i, s1, COLLECT(og.name) AS s2
    
    WITH m,other,intersection,s1,s2
    
    WITH m,other,intersection,s1+filter(x IN s2 WHERE NOT x IN s1) AS union, s1, s2
    
    RETURN m.title, other.title, s1,s2,((1.0*intersection)/SIZE(union)) AS jaccard ORDER BY jaccard DESC LIMIT 100
    

    对代码稍作解读:
    取交集特别简单,就是第一行MATCH中的g
    取并集需要几步:

    1. 先把m的全集取到:第四行s1
    2. 再把other的全集取到:第六行s2
    3. 在第八行,计算出并集union
      最后一行RETURN计算出jaccard值。

    这段代码可以帮大家体会类似foreach这种操作。其中的other实际是在
    foreach式遍历。

    沙盒测试结果如下:


    jaccard by genre

    把genre, actor, director这些都结合起来,也类似。代码如下:

    MATCH (m:Movie {title: "Inception"})-[:IN_GENRE|:ACTED_IN|:DIRECTED]-(t)<-[:IN_GENRE|:ACTED_IN|:DIRECTED]-(other:Movie)
    WITH m, other, COUNT(t) AS intersection, COLLECT(t.name) AS i
    MATCH (m)-[:IN_GENRE|:ACTED_IN|:DIRECTED]-(mt)
    WITH m,other, intersection,i, COLLECT(mt.name) AS s1
    MATCH (other)-[:IN_GENRE|:ACTED_IN|:DIRECTED]-(ot)
    WITH m,other,intersection,i, s1, COLLECT(ot.name) AS s2
    
    WITH m,other,intersection,s1,s2
    
    WITH m,other,intersection,s1+filter(x IN s2 WHERE NOT x IN s1) AS union, s1, s2
    
    RETURN m.title, other.title, s1,s2,((1.0*intersection)/SIZE(union)) AS jaccard ORDER BY jaccard DESC LIMIT 100
    

    从中看出,cypher代码一样简洁。

    沙盒验证效果如下:


    jaccard by multiple attributes

    (未完待续)

    相关文章

      网友评论

        本文标题:neo4j recommendation sandbox推荐系统

        本文链接:https://www.haomeiwen.com/subject/nxawpqtx.html