计算机毕设 推荐系统设计与实现 协同过滤推荐算法

news2024/12/23 18:03:24

文章目录

  • 0 前言
        • 简介
        • 常见推荐算法
          • 协同过滤
          • 分解矩阵
          • 聚类
          • 深度学习
        • 协同过滤原理
        • 系统设计
            • 示例代码(py)
        • 系统展示
            • 系统界面
            • 推荐效果
  • 最后


0 前言

🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。

为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是

🚩 推荐系统设计与实现

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:3分
  • 工作量:3分
  • 创新点:4分
简介

推荐系统,是当今互联网背后的无名英雄。

我们在某宝首页看见的商品,某条上读到的新闻,某度上的搜索列表,甚至在各种地方看见的广告,都有赖于推荐算法和系统.

本片文章讲述有哪些常用的推荐算法, 协同过滤推荐算法的原理, 以及如何使用协同过滤算法设计一个商品推荐毕业设计系统.

常见推荐算法
协同过滤

协同过滤(Collaborative Filtering)作为推荐算法中最经典的类型,包括在线的协同和离线的过滤两部分。所谓在线协同,就是通过在线数据找到用户可能喜欢的物品,而离线过滤,则是过滤掉一些不值得推荐的数据,比比如推荐值评分低的数据,或者虽然推荐值高但是用户已经购买的数据。

协同过滤的模型一般为m个物品,m个用户的数据,只有部分用户和部分数据之间是有评分数据的,其它部分评分是空白,此时我们要用已有的部分稀疏数据来预测那些空白的物品和数据之间的评分关系,找到最高评分的物品推荐给用户。

一般来说,协同过滤推荐分为三种类型。第一种是基于用户(user-based)的协同过滤,第二种是基于项目(item-based)的协同过滤,第三种是基于模型(model based)的协同过滤。

基于用户的协同过滤的基本原理是,根据所有用户对物品或者信息的偏好,发现与当前用户口味和偏好相似的用户群,然后基于这些用户的历史偏好,为当前用户进行推荐。

在这里插入图片描述
假设用户A喜欢物品A、物品C,用户B喜欢物品B,用户C喜欢物品A、物品C和物品D。从这些用户的历史偏好中,我们可以看出用户A和用户C的偏好是类似的。同时我们可以看到用户C喜欢物品D,所以我们可以猜想用户A可能也喜欢物品D,因此可以把物品D推荐给用户A。

分解矩阵

这是一个非常优雅的推荐算法,因为当涉及到矩阵分解时,我们通常不会太多地去思考哪些项目将停留在所得到矩阵的列和行中。但是使用这个推荐引擎,我们清楚地看到,u是第i个用户的兴趣向量,v是第j个电影的参数向量。

在这里插入图片描述
所以我们可以用u和v的点积来估算x(第i个用户对第j个电影的评分)。我们用已知的分数构建这些向量,并使用它们来预测未知的得分。

例如,在矩阵分解之后,Ted的向量是(1.4; .8),商品A的向量是(1.4; .9),现在,我们可以通过计算(1.4; .8)和(1.4; .9)的点积,来还原商品A-Ted的得分。结果,我们得到2.68分。
    
在这里插入图片描述

聚类

上面两种算法都极其简单,适用于小型系统。在这两种方法中,我们把推荐问题当做一个有监督机器学习任务来解决。

现在,该开始用无监督学习来解决问题了。

假设我们正在建立一个大型推荐系统,这时协同过滤和矩阵分解花费的时间更长了。第一个浮现在脑海里的解决之道,就是聚类。

业务开展之初,缺乏之前的用户数据,聚类将是最好的方法。

不过,聚类是一种比较弱的个性化推荐,因为这种方法的本质是识别用户组,并对这个组内的用户推荐相同的内容。

当我们有足够数据时,最好使用聚类作为第一步,来缩减协同过滤算法中相关邻居的选择范围。这个方法还能挺高复杂推荐系统的性能。

每个聚类都会根据其中用户的偏好,来分配一组典型的偏好。每个聚类中的用户,都会收到为这个聚类计算出的推荐内容。

深度学习

在过去的十年中,神经网络已经取得了巨大的飞跃。如今,神经网络已经得以广泛应用,并逐渐取代传统的机器学习方法。

接下来,我要介绍一下YouTube如何使用深度学习方法来做个性化推荐。

毫无疑问,由于体量庞大、动态库和各种观察不到的外部因素,为YouTube用户提供推荐内容是一项非常具有挑战性的任务。

根据《Deep Neural Networks for YouTube Recommendations》( https://static.googleusercontent.com/media/research.google.com/ru//pubs/archive/45530.pdf ),YouTube的推荐系统算法由两个神经网络组成:一个用于候选生成,一个用于排序。如果你没时间仔细研究论文,可以看看我们下面给出的简短总结。

在这里插入图片描述
以用户的浏览历史为输入,候选生成网络可以显著减小可推荐的视频数量,从庞大的库中选出一组最相关的视频。这样生成的候选视频与用户的相关性最高,然后我们会对用户评分进行预测。

这个网络的目标,只是通过协同过滤提供更广泛的个性化。

在这里插入图片描述
进行到这一步,我们得到一组规模更小但相关性更高的内容。我们的目标是仔细分析这些候选内容,以便做出最佳的选择。

这个任务由排序网络完成。

所谓排序就是根据视频描述数据和用户行为信息,使用设计好的目标函数为每个视频打分,得分最高的视频会呈献给用户。
在这里插入图片描述
通过这两步,我们可以从非常庞大的视频库中选择视频,并面向用户进行有针对性的推荐。这个方法还能让我们把其他来源的内容也容纳进来。
在这里插入图片描述
推荐任务是一个极端的多类分类问题。这个预测问题的实质,是基于用户(U)和语境©,在给定的时间t精确地从库(V)中上百万的视频类(i)中,对特定的视频观看(Wt)情况进行分类。

协同过滤原理

使用基于物品的协同过滤,需要维护一个物品相似度矩阵;使用基于用户的协同过滤,需要维护一个用户相似度矩阵。
在这里插入图片描述
两用户之间的相似度的计算其实很简单,用户i与用户j的相似度 = (i、j都打开过的网页数)/根号(i打开过的网页数 * j打开过的网页数)。这个计算与“基于物品的协同过滤”中的物品之间相似度的计算是类似的。

在这里插入图片描述

上面是一个用户相似度计算的案例。我们试着计算A和D之间的相似度。从“用户打开过的网页”可以看出,A和D都打开过的网页只有d,也就是1个。用户A打开过的网页数=3,用户D打开过的网页数=3。所以A和D的相似度=1/根号(3*3)。其他的计算也是类似的。

有了用户之间的相似度之后,就可以计算推荐度了。假设e是刚刚发布的文章,这时候用户B、C、D都浏览到e新闻的标题,其中C、D点击了,我们就可以计算A对e的兴趣度。

A对e的兴趣度=A与B的相似度B对e的兴趣度 + A与C的相似度C对e的兴趣度 + A与D的相似度*D对e的兴趣度。 因为我们这里用的不是评分制,而是考虑是否点击,那么D点击了e,D对e的兴趣度=1。

A对e的兴趣度 = 1/根号(6)*1 + 1/根号(6)*1 + 1/根号(9)*1

所以,比如100篇新的文章出来之后,对部分用户进行了曝光,然后就可以根据用户相似度,来预计其他用户对这篇文章的兴趣度,进而挑选这100篇中预计兴趣度最高的30篇曝光给这群用户。

系统设计
示例代码(py)
from abc import ABCMeta, abstractmethod
import numpy as np
from collections import defaultdict


class CF_base(metaclass=ABCMeta):
    def __init__(self, k=3):
        self.k = k
        self.n_user = None
        self.n_item = None

    @abstractmethod
    def init_param(self, data):
        pass

    @abstractmethod
    def cal_prediction(self, *args):
        pass

    @abstractmethod
    def cal_recommendation(self, user_id, data):
        pass

    def fit(self, data):
        # 计算所有用户的推荐物品
        self.init_param(data)
        all_users = []
        for i in range(self.n_user):
            all_users.append(self.cal_recommendation(i, data))
        return all_users


class CF_knearest(CF_base):
    """
    基于物品的K近邻协同过滤推荐算法
    """

    def __init__(self, k, criterion='cosine'):
        super(CF_knearest, self).__init__(k)
        self.criterion = criterion
        self.simi_mat = None
        return

    def init_param(self, data):
        # 初始化参数
        self.n_user = data.shape[0]
        self.n_item = data.shape[1]
        self.simi_mat = self.cal_simi_mat(data)
        return

    def cal_similarity(self, i, j, data):
        # 计算物品i和物品j的相似度
        items = data[:, [i, j]]
        del_inds = np.where(items == 0)[0]
        items = np.delete(items, del_inds, axis=0)
        if items.size == 0:
            similarity = 0
        else:
            v1 = items[:, 0]
            v2 = items[:, 1]
            if self.criterion == 'cosine':
                if np.std(v1) > 1e-3:  # 方差过大,表明用户间评价尺度差别大需要进行调整
                    v1 = v1 - v1.mean()
                if np.std(v2) > 1e-3:
                    v2 = v2 - v2.mean()
                similarity = (v1 @ v2) / np.linalg.norm(v1, 2) / np.linalg.norm(v2, 2)
            elif self.criterion == 'pearson':
                similarity = np.corrcoef(v1, v2)[0, 1]
            else:
                raise ValueError('the method is not supported now')
        return similarity

    def cal_simi_mat(self, data):
        # 计算物品间的相似度矩阵
        simi_mat = np.ones((self.n_item, self.n_item))
        for i in range(self.n_item):
            for j in range(i + 1, self.n_item):
                simi_mat[i, j] = self.cal_similarity(i, j, data)
                simi_mat[j, i] = simi_mat[i, j]
        return simi_mat

    def cal_prediction(self, user_row, item_ind):
        # 计算预推荐物品i对目标活跃用户u的吸引力
        purchase_item_inds = np.where(user_row > 0)[0]
        rates = user_row[purchase_item_inds]
        simi = self.simi_mat[item_ind][purchase_item_inds]
        return np.sum(rates * simi) / np.linalg.norm(simi, 1)

    def cal_recommendation(self, user_ind, data):
        # 计算目标用户的最具吸引力的k个物品list
        item_prediction = defaultdict(float)
        user_row = data[user_ind]
        un_purchase_item_inds = np.where(user_row == 0)[0]
        for item_ind in un_purchase_item_inds:
            item_prediction[item_ind] = self.cal_prediction(user_row, item_ind)
        res = sorted(item_prediction, key=item_prediction.get, reverse=True)
        return res[:self.k]


class CF_svd(CF_base):
    """
    基于矩阵分解的协同过滤算法
    """

    def __init__(self, k=3, r=3):
        super(CF_svd, self).__init__(k)
        self.r = r  # 选取前k个奇异值
        self.uk = None  # 用户的隐因子向量
        self.vk = None  # 物品的隐因子向量
        return

    def init_param(self, data):
        # 初始化,预处理
        self.n_user = data.shape[0]
        self.n_item = data.shape[1]
        self.svd_simplify(data)
        return data

    def svd_simplify(self, data):
        # 奇异值分解以及简化
        u, s, v = np.linalg.svd(data)
        u, s, v = u[:, :self.r], s[:self.r], v[:self.r, :]  # 简化
        sk = np.diag(np.sqrt(s))  # r*r
        self.uk = u @ sk  # m*r
        self.vk = sk @ v  # r*n
        return

    def cal_prediction(self, user_ind, item_ind, user_row):
        rate_ave = np.mean(user_row)  # 用户已购物品的评价的平均值(未评价的评分为0)
        return rate_ave + self.uk[user_ind] @ self.vk[:, item_ind]  # 两个隐因子向量的内积加上平均值就是最终的预测分值

    def cal_recommendation(self, user_ind, data):
        # 计算目标用户的最具吸引力的k个物品list
        item_prediction = defaultdict(float)
        user_row = data[user_ind]
        un_purchase_item_inds = np.where(user_row == 0)[0]
        for item_ind in un_purchase_item_inds:
            item_prediction[item_ind] = self.cal_prediction(user_ind, item_ind, user_row)
        res = sorted(item_prediction, key=item_prediction.get, reverse=True)
        return res[:self.k]


if __name__ == '__main__':
    # data = np.array([[4, 3, 0, 5, 0],
    #                  [4, 0, 4, 4, 0],
    #                  [4, 0, 5, 0, 3],
    #                  [2, 3, 0, 1, 0],
    #                  [0, 4, 2, 0, 5]])
    data = np.array([[3.5, 1.0, 0.0, 0.0, 0.0, 0.0],
                     [2.5, 3.5, 3.0, 3.5, 2.5, 3.0],
                     [3.0, 3.5, 1.5, 5.0, 3.0, 3.5],
                     [2.5, 3.5, 0.0, 3.5, 4.0, 0.0],
                     [3.5, 2.0, 4.5, 0.0, 3.5, 2.0],
                     [3.0, 4.0, 2.0, 3.0, 3.0, 2.0],
                     [4.5, 1.5, 3.0, 5.0, 3.5, 0.0]])
    # cf = CF_svd(k=1, r=3)
    cf = CF_knearest(k=1)
    print(cf.fit(data))
系统展示
系统界面

在这里插入图片描述

推荐效果

在这里插入图片描述

最后

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1202179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PM2.5数据-省份、城市、区县(1998-2021年)

PM2.5是指直径小于或等于2.5微米的颗粒物,能深入人体呼吸系统,对人体健康产生重大影响。该份数据是关于中国省市县PM2.5的数据集,是根据Atmospheric Composition Analysis Group的PM2.5数据进行整理得到的面板数据。记录了中国各省、市、县的…

ESP32 BLE特征值示例

键盘特征值初始化示例 void BleKeyboard::begin(void) {BLEDevice::init(deviceName);BLEServer* pServer BLEDevice::createServer();pServer->setCallbacks(this);hid new BLEHIDDevice(pServer);inputKeyboard hid->inputReport(KEYBOARD_ID); // <-- input R…

媒体软文投放的流程与媒体平台的选择

海内外媒体软文&#xff1a;助力信息传播与品牌建设 在当今数字化时代&#xff0c;企业如何在庞大的信息海洋中脱颖而出&#xff0c;成为品牌建设的领军者&#xff1f;媒体软文投放无疑是一项强大的策略&#xff0c;通过选择合适的平台&#xff0c;精准投放&#xff0c;可以实…

软件推荐目录——按类划分

之前的文章中&#xff0c;博主介绍过诸多实用的软件&#xff0c;今天博主就继续来泛总结一下电脑常用的功能里&#xff0c;有哪些天花板级别存在的软件呢。 1. 浏览器 在之前的文章中&#xff0c;学长已经详细介绍过优秀的浏览器产品&#xff0c;还是同样的套路&#xff1a;外网…

蓝桥杯每日一题2023.11.13

题目描述 蓝桥杯大赛历届真题 - C 语言 B 组 - 蓝桥云课 (lanqiao.cn) 题目分析 由于每次吹灭的蜡烛与年龄相同故我们想到使用前缀和可以让我们求出各个区间的和&#xff0c;我们将每个区间都枚举一遍&#xff0c;如果符合要求就输出区间开始的位置&#xff08;答案&#xff…

专业开源人员的需求仍在增长

Linux 基金会执行总监根据 Dice.com 的一项调查结果表示&#xff1a;「开源正变得越来越专业化&#xff0c;各大公司都在寻求具备这方面技能的专业型人才。」网上有研究分析了两组「2017 年度开源工作调查与报告」&#xff0c;主要分析结果如下&#xff1a; 89% 的招聘人员表示…

机带RAM:16G(可用2G)

文章目录 机带RAM 16G&#xff08;可用2G&#xff09;一 、问题描述二、解决办法2.1 最大内存设置 2.2 系统激活重启 机带RAM 16G&#xff08;可用2G&#xff09; 一 、问题描述 戴尔商务计算机 Windows11系统 16GB内存 之前一直是正常使用的&#xff0c;突然有一天内存占用率…

【杂记】WinServer 2019解决net3.5无法安装问题

1. 问题描述 由于QA环境中的OSCE V16服务端是部署在虚拟机Windows Server 2019上&#xff0c;当进行数据库的迁移操作时&#xff0c;操作系统会提示缺少.NET Framework 3.5组件(SQL Server数据库系统的运行需要依靠.NET Framework 3.5&#xff0c;但是Windows Server2019默认情…

【rl-agents代码学习】01——总体框架

文章目录 rl-agent Get startInstallationUsageMonitoring 具体代码 学习一下rl-agents的项目结构以及代码实现思路。 source: https://github.com/eleurent/rl-agents rl-agent Get start Installation pip install --user githttps://github.com/eleurent/rl-agentsUsage…

第一章:线性查找

系列文章目录 文章目录 系列文章目录前言一、线性查找二、实现查找算法三、循环不变量四、复杂度分析五、常见复杂度六、测试算法性能总结 前言 从线性查找入手算法。 一、线性查找 线性查找目的在线性数据结构中一个一个查找目标元素输入数组和目标元素输出目标元素所在的索…

LCA

定义 最近公共祖先简称 LCA&#xff08;Lowest Common Ancestor&#xff09;。两个节点的最近公共祖先&#xff0c;就是这两个点的公共祖先里面&#xff0c;离根最远的那个。 性质 如果 不为 的祖先并且 不为 的祖先&#xff0c;那么 分别处于 的两棵不同子树中&#…

Clickhouse学习笔记(13)—— Materialize MySQL引擎

该引擎用于监听 binlog 事件&#xff0c;类似于canal、Maxwell等组件 ClickHouse 20.8.2.3 版本新增加了 MaterializeMySQL 的 database 引擎&#xff0c;该 database 能映射到 MySQL中的某个database &#xff0c;并自动在ClickHouse中创建对应ReplacingMergeTree。 ClickHous…

【Python Opencv】图片与视频的操作

文章目录 前言一、opencv图片1.1 读取图像1.2 显示图像1.3 写入图像1.4 示例代码 二、Opencv视频2.1 从相机捕获视频获取摄像头一帧一帧读取显示图片VideoCapture 中的get和set函数示例代码 2.2 从文件播放视频示例代码 2.3 保存视频示例代码 总结 前言 在计算机视觉和图像处理…

As Const:一个被低估的 TypeScript 特性

目录 理解 as const TypeScript的期望与现实 解决方案&#xff1a;as const 与 object.freeze 的比较 一个配合 as const 的更清洁的 go to root 函数 使用 as const 提取对象值 基于Vue3.0的优秀低代码项目 你有没有感觉 TypeScript中可能有一些被低估但却非常有用的工…

解析JSON字符串:属性值为null的时候不被序列化

如果希望属性值为null及不序列化&#xff0c;只序列化不为null的值。 1、测试代码 配置代码&#xff1a; mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 或者通过注解JsonInclude(JsonInclude.Include.NON_NULL) //常见问题2&#xff1a;属性为null&a…

操作系统 | 虚拟机及linux的安装

​ &#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《操作系统实验室》&#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 目录结构 1.操作系统实验之虚拟机及linux的安装 1.1 实验目的 1.2 实验内容 1.3 实验步骤 …

修改django开发环境runserver命令默认的端口

runserver默认8000端口 虽然python manage.py runserver 8080 可以指定端口&#xff0c;但不想每次runserver都添加8080这个参数 可以通过修改manage.py进行修改&#xff0c;只需要加三行&#xff1a; from django.core.management.commands.runserver import Command as Ru…

蓝桥杯 选择排序

选择排序的思想 选择排序的思想和冒泡排序类似&#xff0c;是每次找出最大的然后直接放到右边对应位置&#xff0c;然后将最 右边这个确定下来&#xff08;而不是一个一个地交换过去&#xff09;。 再来确定第二大的&#xff0c;再确定第三大的… 对于数组a[]&#xff0c;具体…

虹科方案 | 汽车电子电气架构设计仿真解决方案

来源&#xff1a;虹科汽车电子 虹科方案 | 汽车电子电气架构设计仿真解决方案 导读 本文将介绍面向服务&#xff08;SOA&#xff09;的汽车TSN网络架构&#xff0c;并探讨RTaW-Pegase仿真与设计软件在TSN网络设计中的应用。通过RTaW将设计问题分解&#xff0c;我们可以更好地理…

低代码、零代码开源与不开源:区别解析

在如今日益发展的数字时代&#xff0c;程序开发变得越来越重要。为了实现日益提高的业务需求&#xff0c;开发人员必须能够以更高效、更灵活的方式构建和交货软件解决方案。低代码和零代码开源是近几年流行的两种开发方法。本文将探讨它们与传统非开源程序开发的差别&#xff0…