基於物品協同過濾實現商品推薦系統


一、背景

某電商平台,有一批用戶瀏覽、收藏、購買物品的日志數據。實現用戶進入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_{u\in N(i) \bigcap N(j)}}{\sqrt{|N(i)||N(j)|}}\tag{1} \]

\(N(i)\)\(N(j)\)分別表示喜歡物品\(i\)和物品\(j\)的人數。

顯式評分

\[\text{cosine_sim}(i, j) = \frac{\sum\limits_{u \in U_{ij}} r_{ui} \cdot r_{uj}}{\sqrt{\sum\limits_{u \in U_{ij}} r_{ui}^2} \cdot\sqrt{\sum\limits_{u \in U_{ij}} r_{uj}^2}}\tag{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 兩天在首頁展示的推薦商品,要求不一樣。一個解決方案:過濾掉昨天的推薦物品。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM