zoukankan      html  css  js  c++  java
  • 基于物品协同过滤实现商品推荐系统

    一、背景

    某电商平台,有一批用户浏览、收藏、购买物品的日志数据。实现用户进入APP之后第一页显示商品的个性化推荐。ps:当前阶段,显示数据为随机选取。

    二、思考

    1、因为是某一品类的特殊电商平台,卖的商品几百种,但是用户几十万。这种情况,考虑使用ItemCF,至于为什么不是UserCF:物品相似度矩阵为 500*500,用户相似度矩阵为 500000*500000。但是也有一个问题,使用物品相似度矩阵会不会使信息丢失更多。
    2、类似电影评分数据集,用户-电影-评分数据,要把原始数据转换为用户-物品-评分格式。

    浏览:1,收藏:3,购买:5 # 每种行为对应的得分
    

    三、代码实现

    1、从mysql数据库读取数据,并转换为 用户-商品-评分 字典

    class DataPro:
          def __init__(self):
              self.train = dict()
              logs = mysql.fetchall(select_sql)
              for temp in logs: # mysql查询得到的用户日志
                  user = temp['user_id']
    
                  item = temp['product_id']
                  type = temp['type']
                  #print(user,item)
                  score = int(type_score_dict[type])
                  if user not in self.train.keys():
                      self.train.setdefault(user, {})
                  if item not in self.train[user].keys():
                      self.train[user].setdefault(item,0)
        
                  if score > self.train[user][item]:
                      self.train[user][item] = score
                            
    

    2、可以将结果序列化,保存到本地,在实验过程就不需要查询数据库

    # 保存到本地
     output = open('../model/data.pkl', 'wb')
     pickle.dump(self.train, output)
     output.close()
    # 读取文件
    pkl_file = open('../model/data.pkl', 'rb')
    self.data = pickle.load(pkl_file)
    

    3、计算物品-物品相似度矩阵
    显示评分和隐式评分的数据,其相似度矩阵的计算公式有所不同
    隐式评分

    [sim(i,j) =frac{sum_{uin N(i) igcap N(j)}}{sqrt{|N(i)||N(j)|}} ag{1} ]

    (N(i))(N(j))分别表示喜欢物品(i)和物品(j)的人数。

    显式评分

    [ ext{cosine_sim}(i, j) = frac{sumlimits_{u in U_{ij}} r_{ui} cdot r_{uj}}{sqrt{sumlimits_{u in U_{ij}} r_{ui}^2} cdotsqrt{sumlimits_{u in U_{ij}} r_{uj}^2}} ag{2} ]

    其中(r_{ui})(r_{uj})分别表示用户 (u) 对物品 (i)(j) 的评分,(U_{ij})代表同时喜欢物品 (i)(j) 的用户集合。

    3.1 基于隐式评分

    def ItemSimilarity(self):
            # 一个字典,记录 rui*ruj
            # 一个字典 记录 rui^2
            # 建立物品-物品的共现矩阵
            item2item = dict()  # 物品-物品的共现矩阵。分子
            buy = dict()  # 物品被多少个不同用户进行过评分。分母
            for user, items in self.data.items():
                for i in items.keys():
                    buy.setdefault(i, 0)
                    
                    buy[i] += 1
                    item2item.setdefault(i, {})
                    for j in items.keys():
                        if i == j: continue
                        item2item[i].setdefault(j, 0)
                        item2item[i][j] += 1
            # 计算相似度矩阵
            self.similar_matrix = dict()
            for i, related_items in item2item.items():
                self.similar_matrix.setdefault(i, {})
                for j, cij in related_items.items():
                    self.similar_matrix[i][j] = cij / (math.sqrt(buy[i]) * math.sqrt(buy[j]))
            return self.similar_matrix
    

    3.2 基于显式评分

     def ItemSimilarity(self):
            # 一个字典,记录 rui*ruj
            # 一个字典 记录 rui^2
            # 建立物品-物品的共现矩阵
            item2item = dict()  # 物品-物品的共现矩阵。记录rui*ruj,分子
            buy = dict()  # 物品被多少个不同用户进行过评分。记录rui*rui分母
            for user, items in self.data.items():
                for i in items.keys():
                    buy.setdefault(i, 0)
                    temp = items[i]*items[i]
                    buy[i] += temp
                    item2item.setdefault(i, {})
                    for j in items.keys():
                        if i == j: continue
                        item2item[i].setdefault(j, 0)
                        item2item[i][j] += items[i]*items[j]
            # 计算相似度矩阵
            self.similar_matrix = dict()
            for i, related_items in item2item.items():
                self.similar_matrix.setdefault(i, {})
                for j, cij in related_items.items():
                    self.similar_matrix[i][j] = cij / (math.sqrt(buy[i]) * math.sqrt(buy[j]))
            return self.similar_matrix
    

    4、相似度矩阵计算完成之后,根据用户id进行商品推荐。需要的参数:K:某个物品其相似物品的个数。N:给用户推荐N个商品。

     def get_recommend(self,user_id):
        K = 20 # 和某物品相似的k个物品
        N = 10 # 推荐最相似的10个物品
        rank = {}
    
        watched_items = self.data[user_id]
    
        for item,rating in watched_items.items():
            for related_item,w in sorted(self.similar_matrix[item].items(),key=itemgetter(1),reverse=True)[:K]:
                rank.setdefault(related_item,0)
                rank[related_item] += w*float(rating)
        return  sorted(rank.items(),key=itemgetter(1),reverse=True)[:N]
    

    四、后续思考

    1、用户多次浏览同一个商品,其权重如何在代码中体现
    2、基于当前数据的ItemCF完成之后,之后对每天活跃的用户进行推荐结果更新。此时,要实现相似度矩阵的增量更新。

    五、电影推荐系统和实际场景中商品推荐系统的区别

    对于电影推荐,计算得到推荐的电影即可。
    商品推荐,额外的要求是每天推荐结果的新颖性。2020-8-10 和 2020-8-11 两天在首页展示的推荐商品,要求不一样。一个解决方案:过滤掉昨天的推荐物品。

  • 相关阅读:
    超详细的sql2005图解安装全过程【图文】SQL Server 2005 安装图解(图文详解+全程截图)
    C# WinForm控件的拖动和缩放的实现
    C#中使用组合键事件,c#2005中组合键的应用
    C#判断Shift,Alt,Ctrl是否被按下,确定所按下的组合键
    详解破解VS2010正式版的方法(仅供技术交流)
    C# listview中显示imagelist中的图片
    序列化
    收集一些常用的正则表达式【转载】
    iframe+ajaxSubmit结合续篇(判断图片(文件)大小,上传图片,验证码刷新)
    完美去掉a标签和按钮加背景图片阴影
  • 原文地址:https://www.cnblogs.com/leimu/p/13391490.html
Copyright © 2011-2022 走看看