python3实现基于用户的协同过滤

Python3实现基于用户的协同过滤

协同过滤是推荐系统中应用广泛的一种算法,其中基于用户的协同过滤是其中的一种常见方法。对于一个用户来说,根据他之前观看的电影或听过的歌曲,我们可以发现他喜欢哪些类型的电影或歌曲。对于相似的用户,我们可以基于他们相同或类似的偏好来推荐他们喜欢的电影或歌曲。下面是一个实现基于用户的协同过滤推荐系统的完整攻略。

数据集准备

在实现协同过滤算法之前,需要准备好一个数据集。以下是一个简单的例子,其中包含了5个用户以及他们的偏好值。

电影1 电影2 电影3 电影4 电影5
A 5 3 2 4 1
B 2 1 4 2 5
C 3 4 4 5 2
D 1 2 4 3 3
E 4 5 1 2 1

计算用户之间的相似度

计算用户之间的相似度是协同过滤算法的核心。我们可以使用“皮尔逊相关系数”或“余弦相似度”等方法计算用户之间的相似度。下面我们使用余弦相似度计算用户之间的相似度。

首先,我们需要对数据进行“归一化”,将偏好值从0到1之间的值。这里我们假设每个用户的偏好值均为非负整数。对于用户A,假设他总共评价了n部电影,$p_{i, A}$表示用户A对电影i的偏好值,$w_{i,A}$表示用户A对电影i的归一化偏好值,我们可以使用下面的公式将$p_{i, A}$转换为$w_{i,A}$:
$$w_{i,A}=\frac{p_{i,A}}{\sqrt{\sum_{k=1}^np_{k,A}^2}}$$

接下来,我们可以计算用户与用户之间的余弦相似度。假设用户A和用户B分别评价了n部电影,$w_{i,A}$表示用户A给电影i的归一化偏好值,$w_{i,B}$表示用户B给电影i的归一化偏好值,$s_{A,B}$表示用户A和用户B之间的相似度,则有以下公式:
$$s_{A,B}=\frac{\sum_{i=1}^{n}w_{i,A}w_{i,B}}{\sqrt{\sum_{i=1}^{n}(w_{i,A})^2}\sqrt{\sum_{i=1}^{n}(w_{i,B})^2}}$$

通过上面的公式,我们可以计算出每对用户之间的相似度。下面是一个示例代码:

import math

def cos_sim(pref1, pref2):
    """
    计算两个用户的余弦相似度
    :param pref1: 用户1的偏好字典
    :param pref2: 用户2的偏好字典
    :return: 余弦相似度
    """
    shared_items = set(pref1.keys()) & set(pref2.keys())
    if len(shared_items) == 0:
        return 0

    # 计算偏好向量的长度
    length1 = math.sqrt(sum([pow(pref1[item], 2) for item in shared_items]))
    length2 = math.sqrt(sum([pow(pref2[item], 2) for item in shared_items]))

    # 计算余弦相似度
    dot_product = sum([pref1[item] * pref2[item] for item in shared_items])
    return dot_product / (length1 * length2)

生成推荐结果

有了用户之间的相似度,我们就可以开始为每个用户生成推荐结果了。对于每个用户,我们可以找到与他相似度最高的K个用户,并从这K个用户中选出他没有评价过的电影作为推荐结果。

下面是一个示例代码:

def recommend(user, data, sim_func=cos_sim, k=3):
    """
    为用户推荐电影
    :param user: 用户
    :param data: 数据集
    :param sim_func: 相似度计算函数
    :param k: 取Top K个相似用户
    :return: 推荐结果
    """
    scores = {}
    total_sim = {}

    # 遍历所有用户
    for other in data.keys():
        if other == user:
            continue

        sim = sim_func(data[user], data[other])
        # 相似度小于等于0的用户不考虑
        if sim <= 0:
            continue

        # 遍历与用户其他相似的用户
        for item in data[other]:
            # 如果该用户已经评价过该电影,则不考虑
            if item in data[user]:
                continue

            # 计算评分总和和相似度总和
            scores.setdefault(item, 0)
            scores[item] += data[other][item] * sim
            total_sim.setdefault(item, 0)
            total_sim[item] += sim

    # 归一化评分
    rankings = [(item, round(score / total_sim[item], 2)) for item, score in scores.items()]

    # 按评分从高到低排序
    rankings.sort(key=lambda x: -x[1])

    # 选出前k个电影作为推荐结果
    return rankings[:k]

示例

下面是一个基于上述代码实现的简单示例。

data = {"A": {"电影1": 5, "电影2": 3, "电影3": 2, "电影4": 4, "电影5": 1},
        "B": {"电影1": 2, "电影2": 1, "电影3": 4, "电影4": 2, "电影5": 5},
        "C": {"电影1": 3, "电影2": 4, "电影3": 4, "电影4": 5, "电影5": 2},
        "D": {"电影1": 1, "电影2": 2, "电影3": 4, "电影4": 3, "电影5": 3},
        "E": {"电影1": 4, "电影2": 5, "电影3": 1, "电影4": 2, "电影5": 1}}

print(recommend("A", data, k=2))
# 输出 [('电影3', 0.94), ('电影2', 0.81)]

上述代码中,我们传入了数据集以及要查询的用户A,并设置了k=2,表示要返回Top2的推荐结果。程序运行后,会返回评分最高的两个电影,即“电影3”和“电影2”,以及他们的预测分值。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python3实现基于用户的协同过滤 - Python技术站

(0)
上一篇 2023年5月14日
下一篇 2023年5月14日

相关文章

  • 详解Python 函数式复合和柯里化

    Python 函数式编程中,函数复合和柯里化是两种常见的方法,可以帮助我们更加高效地编写程序。下面对这两种方法进行详细讲解。 函数式复合 函数复合是指将多个函数组合成一个新函数的过程,在Python中可以使用 compose 函数进行实现。compose 函数接受一个可变参数,其中每个参数都是一个函数,返回值是一个新的函数。 我们可以通过以下的代码实现 co…

    python-answer 2023年3月25日
    00
  • python修改包导入时搜索路径的方法

    要修改Python的搜索路径,让Python在运行时可以搜索到自己想要的模块或者包而不是默认路径下的,可以通过sys.path来进行设置,sys.path是Python搜索模块的路径集合的列表,可以根据需要来修改。下面是修改搜索路径的两种示例: 在代码中直接修改sys.path import sys sys.path.insert(0, ‘/path/to/…

    python 2023年6月3日
    00
  • Python中的列表知识点汇总

    以下是详细讲解“Python中的列表知识点汇总”的完整攻略。 在Python中,列表是一种非常常用的数据类型,它可以存储多个元素,并且支持各种操作。本文将介绍中列表的知识点,包括创建列表、访问列表元素、添加和删除元素、列表切片、列表排序等。 创建列表 在中可以使用方括号[]或list()函数来创建一个列表。例如: lst1 = [1, 2, 3, 4, 5]…

    python 2023年5月13日
    00
  • python实现一行输入多个值和一行输出多个值的例子

    下面我来为你详细讲解Python实现一行输入多个值和一行输出多个值的例子的完整攻略。 一行输入多个值 使用split()方法 在Python中,我们可以使用input()函数进行控制台输入操作。对于一行输入多个值的情况,我们可以使用split()方法将一行输入的值拆分成一个列表。 例如,输入一行以逗号分隔的多个数值,我们可以使用以下代码实现: # 输入一行以…

    python 2023年6月5日
    00
  • 详解Python 切片语法

    在Python中,切片语法是一种非常方便的操作列表、字符串和元组的方法。它可以让我们快速地获取一个序列的子序列,或者对序列进行切割、拼接等操作。下面将介绍Python切语法的详细使用方法。 切片语法的基本用法 Python切片语法的基本用法是:[start:stop:],其中start表示起始位置,stop表示结束位置(不包含),step表示步长。如果不指定…

    python 2023年5月13日
    00
  • 如何使用pandas对超大csv文件进行快速拆分详解

    当处理非常大的CSV文件时,会遇到性能和速度上的问题。Pandas是一个强大的数据处理工具,可以帮助我们快速处理大型CSV文件。在本篇攻略中,我们将介绍如何使用Pandas分割超大的CSV文件以提高处理速度。 1.读取CSV文件 首先,我们需要使用Pandas的read_csv()函数读取超大的CSV文件。Pandas是基于内存的,因此处理非常大的CSV文件…

    python 2023年6月3日
    00
  • 详解Python 数组数据结构

    下面是Python数组数据结构的完整攻略,包括定义、基本操作和示例说明: 数组数据结构 定义 数组是Python中基本的数据结构之一。它是一种有序的、可变的、容器型的数据结构,可以存储不同类型的数据元素。 在Python中,数组可以通过list类型来实现。例如,下面的代码定义了一个由整数和字符串组成的数组: my_list = [1, 2, "He…

    python-answer 2023年3月25日
    00
  • Python简明讲解filter函数的用法

    下面就是“Python简明讲解filter函数的用法”的完整攻略。 什么是filter函数? filter()是Python内置的用于过滤列表、元组、集合等可迭代对象的函数。它的作用就是从一个序列中过滤出符合条件的元素,返回由符合条件元素组成的新列表或迭代器。 filter()函数的定义如下: filter(function, iterable) 其中,fu…

    python 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部