推荐算法的Python实现——UserCF(基于用户的协同过滤)

Posted 白水baishui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了推荐算法的Python实现——UserCF(基于用户的协同过滤)相关的知识,希望对你有一定的参考价值。

1. 数据集

本博客用Movielens-1m数据集的ratings.dat作为推荐数据来训练UserCF推荐模型。第一列是用户id(user_id)、第二列是物品id(item_id)、第三列是用户对物品的评分(score)、第四列是时间戳(timestamp)

在Movielens-1m的元素数据集中,ratings.dat是用::作为分隔符的。在本次的python实现中,提前将分隔符::替换为了,,文件名ratings.dat改为了ratings.csv

如果嫌麻烦不想该,改代码也可以,主要替换以下两行:

userid, itemid, record, _ = line.split(",")
# 替换为
userid, itemid, record, _ = line.split("::")
ubcf = UserBasedCF('ratings.csv')
# 替换为
ubcf = UserBasedCF('ratings.dat')

2. 代码

import math

class UserBasedCF:
    def __init__(self, datafile):
        self.datafile = datafile
        self.data = []
        self.trainData = {}
        self.userSimMatrix = []

    def readData(self):
        """
        在Movielens数据集中读取数据
        """
        datalist = []
        for line in open(self.datafile):
            userid, itemid, record, _ = line.split(",") # 用逗号分割
            datalist.append((int(userid), int(itemid), int(record)))
        self.data = datalist

    def preprocessData(self):
        """
        把读入的数据转换为训练UCF模型需要的格式
        """
        traindata_list = {}
        # 存储格式:
        for user, item, record in self.data:
            traindata_list.setdefault(user, {})
            traindata_list[user][item] = record
        self.trainData = traindata_list

    def userSimilarity(self):
        """
        生成用户相似度矩阵
        """
        self.userSimMatrix = dict()
        # 物品用户倒排表
        item_users = dict()
        for u, item in self.trainData.items():
            for i in item.keys():
                item_users.setdefault(i, set())
                item_users[i].add(u)
        # 计算用户间同时评分的物品
        user_item_count = dict()
        count = dict()
        for item, users in item_users.items():
            for u in users:
                user_item_count.setdefault(u, 0)
                user_item_count[u] += 1
                for v in users:
                    if u == v : continue
                    count.setdefault(u, {})
                    count[u].setdefault(v, 0)
                    count[u][v] += 1
        # 计算相似度矩阵
        for u, related_users in count.items():
            self.userSimMatrix.setdefault(u, dict())
            for v, cuv in related_users.items():
                self.userSimMatrix[u][v] = cuv / math.sqrt(user_item_count[u] * user_item_count[v] * 1.0)

    def recommend(self, user_id, k, N):
        '''
        给用户推荐K个与之相似用户喜欢的物品
        :param user: 用户id
        :param k: 近邻范围
        :param N: 推荐列表长度
        :return: 推荐列表
        '''
        rank = dict() # k个近邻用户的
        interacted_items = self.trainData.get(user_id, {}) # 当前用户已经交互过的item
        # 取最相似的k个用户的item
        # nbor_u是近邻用户的id,nbor_u_sim是近邻用户与当前用户的相似度
        for nbor_u, nbor_u_sim in sorted(self.userSimMatrix[user_id].items(), key=lambda x:x[1], reverse=True)[0:k]:
            for i, i_score in self.trainData[nbor_u].items(): # 取出所有近邻用户的item
                if i in interacted_items: # 不计入用户已经交互过的item
                    continue
                rank.setdefault(i, 0) # 初始化rank
                rank[i] += nbor_u_sim # 相似度求和,作为item的得分
        # 取出得分最高的N个item作为推荐列表
        return dict(sorted(rank.items(), key=lambda x:x[1], reverse=True)[0:N])

if __name__ == "__main__":
    ubcf = UserBasedCF('ratings.csv')
    ubcf.readData() # 读取数据
    ubcf.preprocessData() # 预处理数据
    ubcf.userSimilarity() # 计算用户相似度矩阵

    # ------ 为用户 i 产生推荐 ------ #
    i = 1
    topN = ubcf.recommend(i, k=3, N=10)  # 输出格式:item的id和评分
    topN_list = list(topN.keys())  # 只取对应的item的id

	print("------ i ------")
    print(i)
    print("------ topN_list ------")
    print(topN_list)

    # ------ 为全部用户产生推荐 ------ #
    # topN_list = {} # 存储为每一个用户推荐的列表
    # for each_user in ubcf.trainData:
    #     topN = ubcf.recommend(each_user, k=3, N=10) # item的id和评分
    #     topN_list[each_user] = list(topN.keys()) # 只取对应的item的id
    #
    #     print("------ topN_list[each_user] ------")
    #     print(topN_list[each_user])
    # print(topN_list)

对用户1(user_id=1)产生一次推荐的输出结果:

------ i ------
1
------ topN_list ------
[2078, 2081, 593, 2080, 2096, 2858, 1617, 2137, 596, 1282]

以上是关于推荐算法的Python实现——UserCF(基于用户的协同过滤)的主要内容,如果未能解决你的问题,请参考以下文章

推荐算法之基于用户的协同过滤

推荐系统手写ItemCF/UserCF代码,你会吗?

基于上下文的推荐 -- 包括时间衰减算法和位置推荐算法(代码实现)

基于上下文的推荐 -- 包括时间衰减算法和位置推荐算法(代码实现)

《推荐系统实践》 3. 通用推荐模型

07-02 基于协同过滤的推荐算法