推荐算法的Python实现——ItemCF(基于物品的协同过滤)

简介: 推荐算法的Python实现——ItemCF(基于物品的协同过滤)

1. 数据集


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


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


如果嫌麻烦不想改ratings.dat文件的内容,改代码也可以,主要替换以下两行:


userid, itemid, record, _ = line.split(",")
# 替换为
userid, itemid, record, _ = line.split("::")


ibcf = ItemBasedCF('ratings.csv')
# 替换为
ibcf = ItemBasedCF('ratings.dat')


2. 代码


import math
class ItemBasedCF:
    def __init__(self, datafile):
        self.datafile = datafile
        self.data = []
        self.trainData = {}
        self.itemSimMatrix = []
    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):
        """
        把读入的数据转换为训练ICF模型需要的格式
        """
        traindata_list = {}
        for user, item, record in self.data:
            traindata_list.setdefault(user, {})
            traindata_list[user][item] = record
        self.trainData = traindata_list
    def itemSimilarity(self):
        """
        生成用户相似度矩阵
        """
        # 物品相似度矩阵
        self.itemSimMatrix = dict()
        # 物品-物品矩阵 格式:物品ID1:{物品ID2:同时给两件物品评分的人数}
        item_item_matrix = dict()
        # 物品-用户矩阵 格式:物品ID:给物品评分的人数
        item_user_matrix = dict()
        for user, items in self.trainData.items():
            for itemId, source in items.items():
                item_user_matrix.setdefault(itemId, 0) # 初始化item_user_matrix[itemId]
                item_user_matrix[itemId] += 1 # 给物品打分的人数+1
                item_item_matrix.setdefault(itemId, {})
                for i in items.keys():
                    if i == itemId:
                        continue
                    item_item_matrix[itemId].setdefault(i, 0)
                    # 计算同时给两个物品打分的人数,并对活跃用户进行惩罚
                    item_item_matrix[itemId][i] += 1 / math.log(1 + len(items) * 1.0)
        # 将物品-物品矩阵转换为物品相似度矩阵
        for itemId, relatedItems in item_item_matrix.items():
            self.itemSimMatrix.setdefault(itemId, dict()) # 初始化self.itemSimMatrix[itemId]
            for relatedItemId, count in relatedItems.items():
                self.itemSimMatrix[itemId][relatedItemId] = count / math.sqrt(item_user_matrix[itemId] * item_user_matrix[relatedItemId])
            # 归一化
            sim_max = max(self.itemSimMatrix[itemId].values())
            for item in self.itemSimMatrix[itemId].keys():
                self.itemSimMatrix[itemId][item] /= sim_max
    def recommend(self, user_id, k, N):
        """给用户推荐物品列表
            Args:
                userId:用户ID
                k:取和物品j最相似的K个物品
                N:推荐N个物品
            Return:
                推荐列表
            """
        rank = dict()
        interacted_items = self.trainData.get(user_id, {}) # 当前用户已经交互过的item
        # 遍历用户评分的物品列表
        for itemId, score in interacted_items.items(): # 取出每一个当前用户交互过的item
            # 取出与物品itemId最相似的K个物品及其评分
            for i, sim_ij in sorted(self.itemSimMatrix[itemId].items(), key=lambda x: x[1], reverse=True)[0:k]:
                # 如果这个物品j已经被用户评分了,舍弃
                if i in interacted_items.keys():
                    continue
                # 对物品ItemID的评分*物品itemId与j的相似度 之和
                rank.setdefault(i, 0)
                rank[i] += score * sim_ij
        # 堆排序,推荐权重前N的物品
        return dict(sorted(rank.items(), key=lambda x:x[1], reverse=True)[0:N])
if __name__ == "__main__":
    ibcf = ItemBasedCF('ratings.csv')
    ibcf.readData() # 读取数据
    ibcf.preprocessData() # 预处理数据
    ibcf.itemSimilarity() # 计算物品相似度矩阵
    # ------ 为用户 i 产生推荐 ------ #
    i = 1
    topN = ibcf.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 ibcf.trainData:
    #     topN = ibcf.recommend(each_user, k=3, N=10) # item的id和评分
    #     topN_list[each_user] = list(topN.keys()) # 只取对应的item的id
    #
    #     print("------ topN ------")
    #     print(topN)
    #     print("------ topN_list[each_user] ------")
    #     print(topN_list[each_user])
    # print("------ topN_list ------")
    # print(topN_list)


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


------ i ------
1
------ topN_list ------
[318, 1196, 364, 2858, 2096, 1302, 593, 1265, 1198, 1704]
相关文章
|
14天前
|
存储 算法 调度
【复现】【遗传算法】考虑储能和可再生能源消纳责任制的售电公司购售电策略(Python代码实现)
【复现】【遗传算法】考虑储能和可再生能源消纳责任制的售电公司购售电策略(Python代码实现)
119 26
|
22天前
|
机器学习/深度学习 算法 机器人
【机器人路径规划】基于D*算法的机器人路径规划(Python代码实现)
【机器人路径规划】基于D*算法的机器人路径规划(Python代码实现)
|
22天前
|
机器学习/深度学习 算法 机器人
【机器人路径规划】基于改进型A*算法的机器人路径规划(Python代码实现)
【机器人路径规划】基于改进型A*算法的机器人路径规划(Python代码实现)
|
22天前
|
机器学习/深度学习 编解码 算法
【机器人路径规划】基于迪杰斯特拉算法(Dijkstra)的机器人路径规划(Python代码实现)
【机器人路径规划】基于迪杰斯特拉算法(Dijkstra)的机器人路径规划(Python代码实现)
125 4
|
22天前
|
机器学习/深度学习 算法 机器人
【机器人路径规划】基于A*算法的机器人路径规划研究(Python代码实现)
【机器人路径规划】基于A*算法的机器人路径规划研究(Python代码实现)
113 4
|
22天前
|
机器学习/深度学习 算法 机器人
【机器人路径规划】基于深度优先搜索(Depth-First-Search,DFS)算法的机器人路径规划(Python代码实现)
【机器人路径规划】基于深度优先搜索(Depth-First-Search,DFS)算法的机器人路径规划(Python代码实现)
|
22天前
|
算法 机器人 定位技术
【机器人路径规划】基于流场寻路算法(Flow Field Pathfinding)的机器人路径规划(Python代码实现)
【机器人路径规划】基于流场寻路算法(Flow Field Pathfinding)的机器人路径规划(Python代码实现)
机器学习/深度学习 算法 自动驾驶
154 0
|
1月前
|
算法 定位技术 调度
基于蚂蚁优化算法的柔性车间调度研究(Python代码实现)
基于蚂蚁优化算法的柔性车间调度研究(Python代码实现)
|
1月前
|
机器学习/深度学习 算法 PyTorch
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)

热门文章

最新文章

推荐镜像

更多