3

我想根据给定的用户偏好(用户喜欢的项目)对项目进行排名,该偏好基于在 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])。

  • 为了继续步行,我需要更改什么以将循环步骤返回到“out('likes')”步骤来喂养新用户(例如 [User2])?

  • 一旦这段代码工作,它可以被视为“个性化 PageRank”的实现吗?


这里是运行示例的代码:

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> 
4

1 回答 1

1

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

  1. 我不确定步骤是否有问题shuffle。在您的情况下,它似乎没有正确随机化。我似乎无法在这种情况下重新创建问题,所以我不确定它是否与您的数据大小或其他东西有关。
  2. 我在使用 ofMath.random()打破循环时遇到了奇怪的问题。

无论如何,我想我已经在这里抓住了你的代码的精髓,我所做的更改似乎可以满足你的要求:

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()工作,因为它在一些迭代中对我来说表现是可以预见的。

于 2014-07-17T12:20:57.153 回答