用Gremlin在二分图上随机游走

时间:2014-07-16 14:18:40

标签: groovy gremlin bipartite graph-traversal random-walk

我想根据给定的用户偏好(用户喜欢的项目)对项目进行排名,这是基于在groovy中使用gremlin的有向二分图上的随机游走。

该图具有以下基本结构:

[User1] ---'喜欢' ---> [ItemA]< ---'喜欢' --- [User2] ---'喜欢' ---> [ItemB]

此后我提出的查询:

def runRankQuery(def userVertex) {
    def m = [:]
    def c = 0
    while (c < 1000) {
        userVertex
            .out('likes')   // get all liked items of current or similar user
            .shuffle[0]     // select randomly one liked item
            .groupCount(m)  // update counts for selected item
            .in('likes')    // get all users who also liked item
            .shuffle[0]     // select randomly one user that liked item
            .loop(5){Math.random() < 0.5}   // follow liked edge of new user (feed new user in loop) 
                                            // OR abort query (restart from original user, outer loop)      
            .iterate()
        c++
    }
    m = m.sort {a, b -> b.value <=> a.value}
    println "intermediate result $m"
    m.keySet().removeAll(userVertex.out('likes').toList())
    // EDIT (makes no sense - remove): m.each{k,v -> m[k] = v / m.values().sum()}
    // EDIT (makes no sense - remove): m.sort {-it.value }
    return m.keySet() as List;
}

但是,此代码未找到新项目(上例中的[ItemB]),但给定用户的喜欢项目(例如[ItemA])。

  • 我需要更改为新用户(例如[用户2])进行更改,然后循环退回到&#39; out(&#39; likes&#39;)&#39;步骤继续散步?

  • 一旦此代码有效,是否可以将其视为&#39;个性化PageRank&#39;

  • 的实施

这里是运行示例的代码:

g = new TinkerGraph()

user1 = g.addVertex()
user1.name ='User1'
user2 = g.addVertex()
user2.name ='User2'
itemA = g.addVertex()
itemA.name ='ItemA'
itemB = g.addVertex()
itemB.name ='ItemB'

g.addEdge(user1, itemA, 'likes')
g.addEdge(user2, itemA, 'likes')
g.addEdge(user2, itemB, 'likes')

println runRankQuery(user1)

输出:

intermediate result [v[2]:1000]
[]
==>null
gremlin> g.v(2).name
==>ItemA
gremlin> 

1 个答案:

答案 0 :(得分:1)

我发现这是一个非常奇怪的问题。我发现了几个非常奇怪的问题,这些问题不容易解释,最后,我不确定它们为什么会这样。对我来说很奇怪的两件大事是:

  1. 我不确定shuffle步是否有问题。在这种情况下,它似乎没有正确随机化。我似乎无法在这种情况之外重新创建问题,因此我不确定它是否与您的数据大小或其他内容有关。
  2. 我使用Math.random()打破了循环,遇到了奇怪的问题。
  3. 无论如何,我认为我已经在这里捕获了代码的本质,我的更改看起来像你想做的那样:

    runRankQuery = { userVertex ->
        def m = [:]
        def c = 0
        def rand = new java.util.Random()
        while (c < 1000) {
            def max = rand.nextInt(10) + 1
            userVertex._().as('x')
                .out('likes')   
                .gather.transform{it[rand.nextInt(it.size())]}
                .groupCount(m) 
                .in('likes')    
                .gather.transform{it[rand.nextInt(it.size())]}
                .loop('x'){it.loops < max}  
                .iterate()
            c++
        }
        println "intermediate result $m"
        m.keySet().removeAll(userVertex.out('likes').toList())
        m.each{k,v -> m[k] = v / m.values().sum()}
        m.sort {-it.value }
        return m.keySet() as List;
    }
    

    我通过从收集的列表中随机选择一个顶点,用我自己的品牌“shuffle”替换shuffle。我还随机选择了max个循环,而不是依赖Math.random()。当我现在运行时,我想我得到了你正在寻找的结果:

    gremlin> runRankQuery(user1)                                       
    intermediate result [v[2]:1787, v[3]:326]
    ==>v[3]
    gremlin> runRankQuery(user1)
    intermediate result [v[2]:1848, v[3]:330]
    ==>v[3]
    gremlin> runRankQuery(user1)
    intermediate result [v[2]:1899, v[3]:339]
    ==>v[3]
    gremlin> runRankQuery(user1)
    intermediate result [v[2]:1852, v[3]:360]
    ==>v[3]
    

    你可能会让Math.random()工作,因为它在使用它的一些迭代中对我来说可行。