基於物品的協同過濾算法ItemCF算法實現


  基於物品的協同過濾算法(ItemCF)的基本思想是:給用戶推薦那些和他們之前喜歡的物品相似的物品。 比如,該算法會因為你購買過《Java從入門到精通》而給你推薦《Java並發編程實戰》。不過,基於物品的協同過濾算法並不利用物品的內容屬性計算物品之間的相似度,二是通過分析用戶的行為數據計算物品之間的相似度。該算法認為,物品A和物品B具有很大的相似度是因為喜歡物品A的用戶大都也喜歡物品B。

實現代碼:

  

# -*- coding=utf-8 -*-
from operator import itemgetter
from texttable import Texttable
from collections import defaultdict
import math

#讀取文件
def readFile(fileData):
    data=[]
    rates=[]
    f=open(fileData,"r")
    data=f.readlines()
    f.close()
    for line in data:
        dataLine=line.split("\t")
        rates.append([int(dataLine[0]),int(dataLine[1]),int(dataLine[2])])
    return rates

#創建字典,生成用戶評分的數據結構
#   輸入:數據集合,格式:用戶id\t硬盤id\t用戶評分
#   輸出:1.用戶字典:dic[用戶id]=[(電影id,電影評分)...]
#        2.電影字典:dic[電影id]=[用戶id1,用戶id2...]
def createDict(rates):
    user_dict={}
    movie_dict={}
    for i in rates:
        if i[0] in user_dict:
            user_dict[i[0]].append((i[1],i[2]))
        else:
            user_dict[i[0]]=[(i[1],i[2])]
        if i[1] in movie_dict:
            movie_dict[i[1]].append(i[0])
        else:
            movie_dict[i[1]]=[i[0]]
    return user_dict,movie_dict


#建立物品倒排表,計算物品相似度
def itemCF(user_dict):
    N=dict()
    C=defaultdict(defaultdict)
    W=defaultdict(defaultdict)
    for key in user_dict:
        for i in user_dict[key]:
            if i[0] not in N.keys(): #i[0]表示movie_id
                N[i[0]]=0
            N[i[0]]+=1               #N[i[0]]表示評論過某電影的用戶數
            for j in user_dict[key]:
                if i==j:
                    continue
                if j not in C[i[0]].keys():
                    C[i[0]][j[0]]=0
                C[i[0]][j[0]]+=1      #C[i[0]][j[0]]表示電影兩兩之間的相似度,eg:同時評論過電影1和電影2的用戶數
    for i,related_item in C.items():
        for j,cij in related_item.items():
            W[i][j]=cij/math.sqrt(N[i]*N[j]) 
    return W

#結合用戶喜好對物品排序
def recommondation(user_id,user_dict,K):
    rank=defaultdict(int)
    l=list()
    W=itemCF(user_dict)
    for i,score in user_dict[user_id]: #i為特定用戶的電影id,score為其相應評分
        for j,wj in sorted(W[i].items(),key=itemgetter(1),reverse=True)[0:K]: #sorted()的返回值為list,list的元素為元組
            if j in user_dict[user_id]:
                continue
            rank[j]+=score*wj #先找出用戶評論過的電影集合,對每一部電影id,假設其中一部電影id1,找出與該電影最相似的K部電影,計算出在id1下用戶對每部電影的興趣度,接着迭代整個用戶評論過的電影集合,求加權和,再排序,可推薦出前n部電影,我這里取10部。
    l=sorted(rank.items(),key=itemgetter(1),reverse=True)[0:10]
    return l
                                

#獲取電影列表
def getMovieList(item):
    items={}
    f=open(item,"r",encoding = 'ISO-8859-1')
    movie_content=f.readlines()
    f.close()
    for movie in movie_content:
        movieLine=movie.split("|")
        items[int(movieLine[0])]=movieLine[1:]
    # print(items)
    return items

#主程序
if __name__=='__main__':
    itemTemp=getMovieList("D:/movieRecommend/ml-100k/u.item") #獲取電影列表
    fileTemp=readFile("D:/movieRecommend/ml-100k/u.data")     #讀取文件
    user_dic,movie_dic=createDict(fileTemp)                        #創建字典
    user_id=66
    movieTemp=recommondation(user_id,user_dic,80)               #對電影排序
    rows=[]
    table=Texttable()                                              #創建表格並顯示
    table.set_deco(Texttable.HEADER)
    table.set_cols_dtype(['t','f','a'])
    table.set_cols_align(["l","l","l"])
    rows.append(["user name","recommondation_movie","from userid"])
    for i in movieTemp:
        rows.append([user_id,itemTemp[i[0]][0],""])
    table.add_rows(rows)
    print("推薦結果如下:")
    print(table.draw())

 

  運行結果:

 

 


免責聲明!

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



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