Bayesian Personalized Ranking(BPR个性化排序)

版权声明:本文为博主自我学习整合内容,欢迎转载,转载请注明出处。 https://blog.csdn.net/qq_39388410/article/details/85160996

在这里插入图片描述
如题,在推荐系统中我们在推荐给用户的商品中一定是需要先后顺序的,即我们需要关心的是用户将会更喜欢我们所推荐的商品,从而得到–个性化排序。但是没错,前几篇所整理的方法目的也是为了预测用户喜好,但往往我们只能通过观察到的正例去估计暗含着负例与缺失值的“?”中,而实际填充也如上图一样,一般用0做填充。然后基于此计算出得分,从某种意义上也可以得到用户优先级的排序,所以首先同样的我们需要解决的问题还是:
对于用户集U和物品集I的对应的 U × I 的预测排序矩阵 X,避免矩阵分解所需要的稠密性,同样采取分解为两个矩阵,即: X = W H T \overline{X} = WH^T 然后同样需要寻找最好的W和H,使其与真正X的误差最小,但是与先前的SVD不同,不是尝试对项目打分再排序,而且从整个思想上进行优化,所以作为先验与后验的桥梁----贝叶斯的思想。

在这里插入图片描述
**首先为了排序,引入三元组的概念:即如果用户u在同时有物品 i 和 j 的时候点击了 i,那么定义三元组<u,i,j><u,i,j>,即对用户u来说,i 的排序要比 j 靠前。如上图中,在左侧显示了观测数据和一些未知的“?”数据,三元组处理后,变成在右侧的,“+” 表示用户更喜欢项 i 大于 j 项;“-” 表示更喜欢j而不是i。

基于用户的全序关系的贝叶斯就变成:
P ( θ &gt; u ) = P ( &gt; u θ ) P ( θ ) P ( &gt; u ) P(\theta|&gt;_u) = \frac{P(&gt;_u|\theta)P(\theta)}{P(&gt;_u)}
其中W和H用 θ \theta 表示,为了得到最好的W,H,即得到最好的 θ \theta ,需要优化后面的这一堆,同样的分母(某用户的全序,对所有的都是物品一样)一样,可以先舍去不考虑。那么对于分子第一项可以有最大似然估计: u U P ( &gt; u θ ) = ( u , i , j ) ( U × I × I ) P ( i &gt; u j θ ) δ ( ( u , i , j ) D ) ( 1 P ( i &gt; u j θ ) ) δ ( ( u , j , i ) ̸ D ) \prod_{u \in U}P(&gt;_u|\theta) = \prod_{(u,i,j) \in (U \times I \times I)}P(i &gt;_u j|\theta)^{\delta((u,i,j) \in D)}(1-P(i &gt;_u j|\theta))^{\delta((u,j,i) \not\in D) } 其中 δ ( b ) = { 1 i f &ThickSpace; b &ThickSpace; i s &ThickSpace; t r u e 0 e l s e \delta(b)= \begin{cases} 1&amp; {if\; b\; is \;true}\\ 0&amp; {else} \end{cases}
P(i >u j | θ)即<u,i,j>,i 排名高于 j。
但是其实,既然是排序–定义使 i 大于 j,那么就使P(i >u j|θ)出现的概率越大越好就行了。那么 P ( i &gt; u j θ ) = σ ( x u i j ( θ ) ) σ P(i &gt;_u j|\theta) = \sigma(\overline{x}_{uij}(\theta)),其中\sigma函数用于优化计算 而且如果要是一方的概率越大,那么另一方就小就好,那么自然期望他们之间的差异就越大即: x u i j = x u i x u j \overline{x}_{uij} = \overline{x}_{ui} - \overline{x}_{uj} 而且这就已经直接是预测矩阵X中的对应位置的值了。即分子第一项变为: u U P ( &gt; u θ ) = ( u , i , j ) D σ ( x u i x u j ) \prod_{u \in U}P(&gt;_u|\theta) = \prod_{(u,i,j) \in D} \sigma(\overline{x}_{ui} - \overline{x}_{uj})
然后分子第二项 P ( θ ) P(\theta) ,直接使用贝叶斯假设,即 θ \theta 符合正太分布,而总所周知,正太分布的对数形式是跟 θ 2 ||\theta||^2 成比的!(除了优化式子外,居然还能曲线救国,漂亮的完成了正则化的作用??所以直接假设使用参数符合正太分布的操作设计很巧妙呀)那么整个下来的的式子就直接变成了: l n &ThickSpace; P ( θ &gt; u ) l n &ThickSpace; P ( &gt; u θ ) P ( θ ) = l n &ThickSpace; ( u , i , j ) D σ ( x u i x u j ) + l n P ( θ ) = ( u , i , j ) D l n σ ( x u i x u j ) + λ θ 2 &ThickSpace; ln\;P(\theta|&gt;_u) \propto ln\;P(&gt;_u|\theta)P(\theta) = ln\;\prod\limits_{(u,i,j) \in D} \sigma(\overline{x}_{ui} - \overline{x}_{uj}) + ln P(\theta) = \sum\limits_{(u,i,j) \in D}ln\sigma(\overline{x}_{ui} - \overline{x}_{uj}) + \lambda||\theta||^2\;

然后同样让我们求导,让我们使用梯度。(不过这里需要使用梯度上升法,因为为了求最大值,即求“上坡”) l n &ThickSpace; P ( θ &gt; u ) θ ( u , i , j ) D 1 1 + e x u i x u j ( x u i x u j ) θ + λ θ \frac{\partial ln\;P(\theta|&gt;_u)}{\partial \theta} \propto \sum\limits_{(u,i,j) \in D} \frac{1}{1+e^{\overline{x}_{ui} - \overline{x}_{uj}}}\frac{\partial (\overline{x}_{ui} - \overline{x}_{uj})}{\partial \theta} + \lambda \theta x u i x u j = f = 1 k w u f h i f f = 1 k w u f h j f \overline{x}_{ui} - \overline{x}_{uj} = \sum\limits_{f=1}^kw_{uf}h_{if} - \sum\limits_{f=1}^kw_{uf}h_{jf}
所以最后的训练算法为:

在这里插入图片描述

def bpr_mf(user_count, item_count, hidden_dim):
    u = tf.placeholder(tf.int32, [None])
    i = tf.placeholder(tf.int32, [None])
    j = tf.placeholder(tf.int32, [None])

    with tf.device("/cpu:0"):
        user_emb_w = tf.get_variable("user_emb_w", [user_count+1, hidden_dim], 
                            initializer=tf.random_normal_initializer(0, 0.1))
        item_emb_w = tf.get_variable("item_emb_w", [item_count+1, hidden_dim], 
                                initializer=tf.random_normal_initializer(0, 0.1))
                                
        #矩阵的分解可以理解为embedding的转化
        u_emb = tf.nn.embedding_lookup(user_emb_w, u)
        i_emb = tf.nn.embedding_lookup(item_emb_w, i)
        j_emb = tf.nn.embedding_lookup(item_emb_w, j)
    
    #第一部分的i 和 j的差值计算
    x = tf.reduce_sum(tf.multiply(u_emb, (i_emb - j_emb)), 1, keep_dims=True)
    
    mf_auc = tf.reduce_mean(tf.to_float(x > 0))
    
    #第二部分完美的正则项
    l2_norm = tf.add_n([
            tf.reduce_sum(tf.multiply(u_emb, u_emb)), 
            tf.reduce_sum(tf.multiply(i_emb, i_emb)),
            tf.reduce_sum(tf.multiply(j_emb, j_emb))
        ])
    
    #整个loss
    regulation_rate = 0.0001
    bprloss = regulation_rate * l2_norm - tf.reduce_mean(tf.log(tf.sigmoid(x)))
    
    #梯度上升
    train_op = tf.train.GradientDescentOptimizer(0.01).minimize(bprloss)
    return u, i, j, mf_auc, bprloss, train_op

完整代码开源在:https://github.com/dongx-duan/bpr

猜你喜欢

转载自blog.csdn.net/qq_39388410/article/details/85160996
今日推荐