美文网首页
3_基于用户的协同过滤方法

3_基于用户的协同过滤方法

作者: 蓝冻 | 来源:发表于2020-11-24 15:30 被阅读0次

    1 直观描述

    用户A有几个“关系很好”的朋友 B、C、D,通常B或C或D买了什么东西的话,A也要跟着买。昨天,B新买了一个物品 g ,而用户A之前也从没见过物品 g ,那么,购物平台就将 g 推荐给A。

    2 基于用户协同过滤的步骤

    ⑴ 计算用户间的相似度。

        \omega_{uv} =\frac{同时被用户u和用户v喜欢的物品数}{用户u喜欢的物品数乘以用户v喜欢的物品数,再对乘积开根号}

    ⑵ 预测某一用户对物品集中他尚未进行评分的物品的评分,并依据计算出来的评分高低来进行推荐。也可以先对所有物品进行评分预测,然后剔除掉已评分的物品,对剩下的物品进行排序。

    3 用户相似度的计算

    用两个for循环遍历user_dict中的用户,通过集合的交集运算,很容易得到同时被用户u和用户v喜欢的物品数,至于每个用户喜欢的物品数,通过len()函数很容易得到,于是就得到所有的\omega_{uv} 了。

    上面这种做法将会把每两个用户之间的相似度都算一遍,计算量太大而且也没必要,因为在实际场景下,与用户A“关系很好”的朋友的数量通常是有限的。我们将用户A “关系很好 ”的那几个朋友找出来并计算他们与A的相似度就行了。

    这就可以用上倒排表了。所谓倒排表,指的是从用户评分文件转换而来的物品用户倒排表。设倒排表为字典 T,则 T 中记录的是各个物品被哪些用户操作过。之后我们只计算操作过同一物品的不同用户之间的相似度就行了,计算的方法就是:对一个物品,用for循环遍历两遍其用户集。当然,我们还需要把所有物品给遍历一遍,这样才能累加得到同时被用户u和用户v喜欢的物品数。

    下面我们定义一个函数实现用户相似度的计算。

    def  user_similarity( user_dict ):

            # 构建倒排表

            item_users = dict()

            for u, u_items in user_dict.items():

                    for i in u_items.keys():

                            item_users.setdefault( i, set() )

                            if user_dict[u][i] > 0.0:

                                    item_users[ i ].add(u)    # 把用户u加入到物品 i 的用户集合中去

            # 上面的过程得到了倒排表 item_users

            # 构建用户在物品集上的同现矩阵,只对出现在同一个用户集里的两个用户进行计算

            user_itemcount = dict()    # 记录每个操作的物品数,后面要当做分母

            count = dict()   # 同现矩阵

             for i , i_users in item_users.items():

                    for u in i_users:

                            user_itemcount.setdefault( u, 0 )

                            user_itemcount[u] += 1

                            count.setdefault(u, {} )

                            for v in i_users:

                                    count[u].setdefault( v, 0 )

                                    if u == v:

                                            continue

                                    count[u][v] += 1 / math.log( 1 + len(i_users) )  

                                    # len(i_users)表示操作过物品 i 的用户集里用户的数目,此处对热门物品进行了惩罚

            similarity = dict()    # 记录用户相似度

            for u , u_users in count.items():

                    similarity.setdefault(u, {})

                    for v, v_u in  u_users.items():

                            if u == v:

                                    continue

                            similarity[u].setdefault(v, 0.0)

                            similarity[u][v] = v_u / math.sqrt( user_itemcount [u] * user_itemcount[v] )

            return similarity

    4 预测评分的过程

    我们可以定义一个近邻用户数 k 。在对某个用户进行推荐时,我们把与该用户 “关系最好”的其它 k 个用户所操作过的物品全部找出来,并从中剔除掉该用户已经操作过的物品,然后只对剩下的物品进行评分预测。

    我们先找出该用户评价过的所有物品,假设保存在 item_of_thisuser字典里,字典的键为各个评价过的物品。事实上, item_of_thisuser 很容易从原始评分文件user_dict中提取出来。

    下面我们定义一个函数实现评分预测的过程,暂时不考虑最终的排序问题。

    def prediction(thisuser, k=8):

            result = dict()

            sort_similarity = sorted( similarity[ thisuser ].items(), key=lambda x: x[1], reverse=True)

            for v, wuv in sort_similarity[0: k]:

                    for i, r_vi in user_dict[v].items():

                            if i in item_of_thisuser:

                                    continue

                            result.setdefault(i, 0)

                            result[i] += r_vi * wuv

            return result

    5 用户协同与物品协同的比较

    从推荐场景而言,在电子商务、电影网站和图书网站等领域,用户数量远大于物品数量,且物品的数量更新速度并不快,可以考虑物品协同的方法。

    对于新闻、博客等类似于信息流的领域,由于内容更新频率非常高,且内容很容易过时,可以考虑用户协同的方法。

    用户协同更注重社会化因素,而物品协同更注重个性化因素。

    相关文章

      网友评论

          本文标题:3_基于用户的协同过滤方法

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