協同過濾演算法——基於物品(Item)

語言: CN / TW / HK

本站內容均來自興趣收集,如不慎侵害的您的相關權益,請留言告知,我們將盡快刪除.謝謝.

一、資料準備

Liu Yi,3,1001
Chen Er,4,1001
Zhang San,3,1001
Li Si,3,1001
Liu Yi,3,1002
Li Si,4,1002
Liu Yi,4,1003
Zhang San,5,1003
Li Si,5,1003
Liu Yi,4,1004
Zhang San,3,1004
Liu Yi,5,1005

二、計算物品和物品之間的共現矩陣

對上面的資料作一下調整,按使用者排列

使用者 評分 物品(BookId)

再計算物品和物品的共現矩陣中的每一個元素

1001和1002,同時被Liu Yi和Li Si兩個使用者購買,所以其共現值為2

1001和1003,同時被Liu Yi, Zhang San和Li Si三個使用者購買,所以其共現值為3

1001和1004,同時被Liu Yi和Zhang San兩個使用者購買,所以其共現值為2

1001和1005,只同時被Liu Yi購買, 所以其共現值為1

1002和1003,同時被Liu Yi和Li Si兩個使用者購買,所以其共現值為2

1002和1004,只同時被Liui Yi購買, 所以其共現值為1

1002和1005,只同時被Liui Yi購買, 所以其共現值為1

1003和1004,同時被Liu Yi和Zhang San兩個使用者購買,所以其共現值為2

1003和1005,只同時被Liui Yi購買, 所以其共現值為1

1004和1005,只同時被Liui Yi購買, 所以其共現值為1

最終,得到的共現矩陣為

三、計算物品被多少個不同的使用者購買

購買1001的有Liu Yi, Chen Er, Zhang San和Li Si

購買1002的有Liu Yi和Li Si

購買1003的有Liu Yi, Zhang San和Li Si

購買1004的有Liu Yi和Zhang San

購買1005的有Liu Yi

四、計算相似度矩陣

兩個物品餘弦相似度的計算公式為:

根據此公式,

1001與1002的相似度為2 / sqrt(4 * 2) = 0.707

1001與1003的相似度為3 / sqrt(4 * 3) = 0.866

1001與1004的相似度為2 / sqrt(4 * 2) = 0.707

1001與1005的相似度為1 / sqrt(4 * 1) = 0.5

1002與1003的相似度為2 / sqrt(2 * 3) = 0.816

1002與1004的相似度為1 / sqrt(2 * 2) = 0.5

1002與1005的相似度為1 / sqrt(2 * 1) = 0.707

1003與1004的相似度為2 / sqrt(3 * 2) = 0.816

1003與1005的相似度為1 / sqrt(3 * 1) = 0.577

1004與1005的相似度為1 / sqrt(2 * 1) = 0.707

所以,相似度矩陣為

假設取K=3

(1) 對於Li Si買過的1001來說,相似度排在前3名的物品和評分為:

1003,0.866

1002,0.707

1004,0.707

這三個物品中,只有1004是Li Si不曾買過的,其推薦值為

1004與1001的相似度 * Li Si對1001的評分 = 0.707 * 3 = 2.121

(2) 對於Li Si買過的1002來說,相似度排在前3名的物品和評分為:

1003,0.816

1001,0.707

1005,0.707

這三個物品中,只有1005是Li Si不曾買過的,其推薦值為

1005與1002的相似度 * Li Si對1002的評分 = 0.707 * 4 = 2.828

(3) 對於Li Si買過的1003來說,相似度排在前3名的物品和評分為:

1001,0.866

1002,0.816

1004,0.816

這三個物品中,只有1004是Li Si不曾買過的,其推薦值為

1004與1003的相似度 * Li Si對1003的評分 = 0.816 * 5 = 4.08

綜上,可以給Li Si推薦的書為

程式碼:

#!/usr/bin/env python
#-*-coding:utf-8-*-
import math
import pdb
class ItemBasedCF:
    def __init__(self,train_file):
        self.train_file = train_file
        self.readData()
        
    def readData(self):
        #讀取檔案,並生成使用者-物品的評分表和測試集
        self.train = dict()
        #使用者-物品的評分表
        for line in open(self.train_file):
            user,score,item = line.strip().split(",")
            self.train.setdefault(user,{})
            self.train[user][item] = int(float(score))
    def ItemSimilarity(self):
        #建立物品-物品的共現矩陣
        cooccur = dict()  #物品-物品的共現矩陣
        buy = dict()  #物品被多少個不同使用者購買N
        for user,items in self.train.items():
            for i in items.keys():
                buy.setdefault(i,0)
                buy[i] += 1
                cooccur.setdefault(i,{})
                for j in items.keys():
                    if i == j : continue
                    cooccur[i].setdefault(j,0)
                    cooccur[i][j] += 1
        #計算相似度矩陣
        self.similar = dict()
        for i,related_items in cooccur.items():
            self.similar.setdefault(i,{})
            for j,cij in related_items.items():
                self.similar[i][j] = cij / (math.sqrt(buy[i] * buy[j]))
        return self.similar
    #給使用者user推薦,前K個相關使用者,前N個物品
    def Recommend(self,user,K=3,N=10):
        rank = dict()
        action_item = self.train[user]     
        #使用者user產生過行為的item和評分
        for item,score in action_item.items():
            sortedItems = sorted(self.similar[item].items(),key=lambda x:x[1],reverse=True)[0:K]
            for j,wj in sortedItems:
                if j in action_item.keys():
                    continue
                rank.setdefault(j,0)
                rank[j] += score * wj
        return dict(sorted(rank.items(),key=lambda x:x[1],reverse=True)[0:N])
    
#宣告一個ItemBasedCF的物件    
item = ItemBasedCF("item_book.txt")
item.ItemSimilarity()
recommedDict = item.Recommend("Li Si")
for k,v in recommedDict.items():
    print(k,"\t",v)

執行結果:

1004    6.203803248198273
1005    2.82842712474619