矩阵分解算法

news2025/2/28 0:33:22

文章目录

  • 0 前言
  • 1. 矩阵分解原理
  • 1.1 LFM
      • 公式推导
      • LFM损失函数
      • 算法关键代码实现
    • 1.2 BiasSVD
    • 1.3 SVD++
  • 参考

0 前言

在协同过滤算法中 我们知道近邻协同过滤算法的显著缺点:

  • 没有充分利用物品本身的属性信息
  • 处理稀疏矩阵能力很弱,泛化能力很弱

为了解决以上问题,引入了基于矩阵分解(Matrix Factorization,MF)的协同过滤算法

矩阵分解协同过滤算法:通过矩阵分解的方式将用户物品共线矩阵实现降维,从而泛化预测 用户物品未知位置的评分

下图是《深度学习推荐系统》中的协同过滤算法与矩阵分解算法在推荐场景下的原理比较

在这里插入图片描述

协同过滤算法找到用户可能喜欢的视频的方式很直接,即基于用户的观看历史,找到跟目标用户看过同样视频的相似用户,然后找到这些相似用户喜欢看的其他视频,推荐给目标用户。

矩阵分解算法则期望为每一个用户和视频生成一个隐向量,将用户和视频定位到隐向量的表示空间上(如图 2-4(b)所示),距离相近的用户和视频表明兴趣特点接近,在推荐过程中,就应该把距离相近的视频推荐给目标用户。例如,如果希望为图 2-4(b)中的用户 Dave 推荐视频,可以发现离 Dave 的用户向量最近的两个视频向量分别是“Ocean’s 11”和“The Lion King”,那么可以根据向量距离由近到远的顺序生成 Dave 的推荐列表。

最初的思路是利用SVD矩阵分解,然后到**LFM隐语义(因子)**模型。到现在这一类的模型被叫做 交替最小二乘(Alternating Least Squares, ALS)已经变成最优化的方法了。

1. 矩阵分解原理

对矩阵进行矩阵分解的主要方法有三种:

  1. 特征值分解 Eigen Decomposition) ,只能作用于方阵,显然不适用于分解用户-物品矩阵
  2. 奇异值分解 ( Singular Value Decomposition,SVD )
  3. 梯度下降 ( GradientDescent)

相比特征值分解的要求矩阵是方阵SVD 更具有普适性,在SLAM中应用广泛。这里我们只简单介绍一下它的表示含义
A = U Σ V T A = U\Sigma V^T A=UΣVT
在这里插入图片描述

矩阵 A m × n A m × n Am×n :m可以表示用户;n可以表示物品

矩阵 U m × m U m × m Um×m

矩阵 Σ m × n {\Sigma} m × n Σm×n: 除了主对角线上的元素以外全为0,主对角线上的每个元素都称为奇异值

矩阵 $ V m × n : U 和 V 都 是 酉 矩 阵 , 即 满 足 : U和V都是酉矩阵,即满足 :UVUTU=I,VTV=I$

大家只要知道 SVD的分解形式 有了解就可以 具体数学推导可以参考(奇异值分解(SVD)

代码实现

# 奇异值分解
np.linalg.svd(a, full_matrices=True, compute_uv=True)

# 参数
a : 是一个形如(M,N)矩阵

full_matrices:的取值是为0或者1,默认值为1,这时u的大小为(M,M),v的大小为(N,N) 。否则u的大小为(M,K),v的大小为(K,N) ,K=min(M,N)

compute_uv:取值是为0或者1,默认值为1,表示计算u,s,v。为0的时候只计算s


# 返回值: 总共有三个返回值u,s,v
其中s是对矩阵a的奇异值分解。s除了对角元素不为0,其他元素都为0,并且对角元素从大到小排列。s中有n个奇异值,一般排在后面的比较接近0,所以仅保留比较大的r个奇异值

从上面不难发现这种传统的SVD分解方式要求 A必须是稠密的,但是在推荐领域数据更多的是稀疏数据,如果用奇异值分解就必须将缺失值填充,而一旦补全, 空间复杂度就会非常高。 同时SVD分解计算复杂度非常高, 用户-物品矩阵非常大,这个开销是非常大的。

所以我们需要更好的分解方式,接下来我们介绍 隐因子模型(LFM)及其变型

1.1 LFM

2006年的Netflix Prize之后, Simon Funk公布了一个矩阵分解算法叫做Funk-SVD, 后来被Netflix Prize的冠军Koren称为Latent Factor Model(LFM)Basic SVD 也是它

LFM(Latent Factor Model) 是在用户和物品的共现矩阵上,引入隐向量,用隐向量表示用户和物品,增强模型表征稀疏数据的能力,本质仍然是 矩阵分解算法,用一个图来表示:

在这里插入图片描述

A m × n = X m × k Y k × n A_{m \times n} = X_{m\times k}Y_{k\times n} Am×n=Xm×kYk×n

其将 m × n 的共现矩阵(m个用户;n个物品) 分解为:

  • m × k用户向量矩阵
  • k × n物品向量矩阵

k 表示隐向量的长度

  • k 越小,隐向量越短,其包含的信息越少,模型的泛化能力越强
  • k 越大,隐向量越长,其包含的信息越多,模型的泛化能力越弱
  • k 的取值,还是要考量计算复杂度(长度约长,复杂度越大)以及实际场景中模型的效果

我们现在为什么把LFM及其变型当做ALS呢?

主要因为 我们 把求解上面两个矩阵的参数问题转换成一个最优化问题, 可以通过训练集里面的观察值利用最小化来学习用户矩阵和物品矩阵

直观案例展示

在这里插入图片描述

公式推导

表示形式 以上面 用户-物品为例
P L F M ( u , i ) = ∑ k = 1 k p u k q i k P^{LFM}(u,i) = \sum_{k=1}^kp_{uk}q_{ik} PLFM(u,i)=k=1kpukqik

LFM损失函数

显然我们预测的值和真实值是有误差的,那我们就要最小化这个误差
KaTeX parse error: No such environment: split at position 8: \begin{̲s̲p̲l̲i̲t̲}̲Loss &= \sum_{u…

加入L2正则化:
L o s s = ∑ u , i ∈ R ( r u i − ∑ k = 1 k p u k q i k ) 2 + λ ( ∑ U p u k 2 + ∑ I q i k 2 ) Loss = \sum_{u,i\in R} (r_{ui}-{\sum_{k=1}}^k p_{uk}q_{ik})^2 + \lambda(\sum_U{p_{uk}}^2+\sum_I{q_{ik}}^2) Loss=u,iR(ruik=1kpukqik)2+λ(Upuk2+Iqik2)
对损失函数求偏导:
KaTeX parse error: No such environment: split at position 8: \begin{̲s̲p̲l̲i̲t̲}̲ \cfrac {\parti…

梯度下降更新参数 p u k p_{uk} puk:(梯度下降比较好理解,其他优化算法同理)
KaTeX parse error: No such environment: split at position 8: \begin{̲s̲p̲l̲i̲t̲}̲ p_{uk}&:=p_{uk…
同理:
KaTeX parse error: No such environment: split at position 8: \begin{̲s̲p̲l̲i̲t̲}̲ q_{ik}&:=q_{ik…
随机梯度下降: 向量乘法 每一个分量相乘 求和
KaTeX parse error: No such environment: split at position 8: \begin{̲s̲p̲l̲i̲t̲}̲ &p_{uk}:=p_{uk…
由于P矩阵和Q矩阵是两个不同的矩阵,通常分别采取不同的正则参数, λ 1 \lambda_1 λ1 λ 2 \lambda_2 λ2

不难看出 这就和训练模型的思路一致, 我们拿到了一个用户物品的评分矩阵, 而我们要去计算两个参数矩阵U和V

  1. 初始化这两个矩阵:用户-隐变量矩阵,物品-隐变量矩阵
  2. 把用户评分矩阵里面已经评过分的那些样本当做训练集的label, 把对应的用户和物品的隐向量当做features, 这样就会得到(features, label)相当于训练集
  3. 通过两个隐向量乘积得到预测值pred
  4. 根据label和pred计算损失
  5. 然后反向传播, 通过梯度下降的方式,更新两个隐向量的值
  6. 未评过分的那些样本当做测试集, 通过两个隐向量就可以得到测试集的label值
  7. 这样就填充完了矩阵, 下一步就可以进行推荐了

算法关键代码实现

'''
LFM Model  
'''
import pandas as pd
import numpy as np

class LFM():

    def __init__(self, alpha, reg_p, reg_q, k=10, epochs=10, columns=["uid", "iid", "rating"]):
        self.alpha = alpha # 学习率
        self.reg_p = reg_p    # P矩阵正则
        self.reg_q = reg_q    # Q矩阵正则
        self.k = k  # 隐式类别数量
        self.epochs = epochs    # 最大迭代次数
        self.columns = columns

    def fit(self, dataset):
        '''
        fit dataset
        :param dataset: uid, iid, rating
        :return:
        '''

        self.dataset = pd.DataFrame(dataset)

        self.users_ratings = dataset.groupby(self.columns[0]).agg([list])[[self.columns[1], self.columns[2]]]
        self.items_ratings = dataset.groupby(self.columns[1]).agg([list])[[self.columns[0], self.columns[2]]]

        self.globalMean = self.dataset[self.columns[2]].mean()

        self.P, self.Q = self.sgd()

    def _init_matrix(self):
        '''
        初始化P和Q矩阵,同时为设置0,1之间的随机值作为初始值
        :return:
        '''
        # User-LF
        P = dict(zip(
            self.users_ratings.index,
            np.random.rand(len(self.users_ratings), self.k).astype(np.float32)
        ))
        # Item-LF
        Q = dict(zip(
            self.items_ratings.index,
            np.random.rand(len(self.items_ratings), self.k).astype(np.float32)
        ))
        return P, Q

    def sgd(self):
        '''
        使用随机梯度下降,优化结果
        :return:
        '''
        P, Q = self._init_matrix()

        for i in range(self.number_epochs):
            print("iter%d"%i)
            error_list = []
            for uid, iid, r_ui in self.dataset.itertuples(index=False):
                v_pu = P[uid] #用户向量
                v_qi = Q[iid] #物品向量
                err = np.float32(r_ui - np.dot(v_pu, v_qi))

                v_pu += self.alpha * (err * v_qi - self.reg_p * v_pu)
                v_qi += self.alpha * (err * v_pu - self.reg_q * v_qi)
                
                P[uid] = v_pu 
                Q[iid] = v_qi


                error_list.append(err ** 2)
            print(np.sqrt(np.mean(error_list)))
        return P, Q
    
        def predict(self, uid, iid):
        # 如果uid或iid不在,我们使用平均分作为预测结果返回
        if uid not in self.users_ratings.index or iid not in self.items_ratings.index:
            return self.globalMean

        p_u = self.P[uid]
        q_i = self.Q[iid]

        return np.dot(p_u, q_i)

    def test(self,testset):
        '''预测测试集数据'''
        for uid, iid, real_rating in testset.itertuples(index=False):
            try:
                pred_rating = self.predict(uid, iid)
            except Exception as e:
                print(e)
            else:
                yield uid, iid, real_rating, pred_rating
if __name__ == '__main__':
    dtype = [("userId", np.int32), ("movieId", np.int32), ("rating", np.float32)]
    dataset = pd.read_csv("data.csv", usecols=range(3), dtype=dict(dtype))

    lfm = LFM(0.02, 0.01, 0.01, 10, 100, ["userId", "movieId", "rating"])
    lfm.fit(dataset)

    while True:
        uid = input("uid: ")
        iid = input("iid: ")
        print(lfm.predict(int(uid), int(iid)))

1.2 BiasSVD

在FunkSVD提出来之后,出现了很多变形版本,其中一个相对成功的方法是BiasSVD,顾名思义,即带有偏置项的SVD分解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QvNkt6Cq-1669452545098)(1. LFM算法.assets/矩阵分解4.jpg)]

它基于的假设和Baseline基准预测是一样的,但这里将Baseline的偏置引入到了矩阵分解中

1.3 SVD++

人们后来又提出了改进的BiasSVD,被称为SVD++,该算法是在BiasSVD的基础上添加了用户的隐式反馈信息:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HvVvjpfQ-1669452545099)(1. LFM算法.assets/矩阵分解5.jpg)]

显示反馈指的用户的评分这样的行为,隐式反馈指用户的浏览记录、购买记录、收听记录等。

SVD++是基于这样的假设:在BiasSVD基础上,认为用户对于项目的历史浏览记录、购买记录、收听记录等可以从侧面反映用户的偏好。

在参考5中实现了更多SVDs, 我也将会持续学习…更新会继续整理,最近整理一下数据,重新实现算法

参考

王喆 《深度学习推荐系统》

奇异值分解(SVD)原理与在降维中的应用 - 刘建平

ALS算法介绍(协同过滤算法介绍

隐语义模型(LFM)和矩阵分解(MF)

SVD在推荐系统中的应用详解以及算法推导

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

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

相关文章

Flink-窗口概念以及窗口API使用

6.3 窗口 6.3.1 窗口的概念 存储桶 水位线只是用来推动窗口的关闭,但不决定数据分到哪个窗口 6.3.2 窗口的分类 按照驱动类型分类 时间窗口计数窗口 按照窗口分配数据的规则分类 滚动窗口:参数为窗口的大小 滑动窗口:参数为窗口大小&am…

[CVPR2022] Debiased Learning from Naturally Imbalanced Pseudo-Labels

Debiased Learning from Naturally Imbalanced Pseudo-Labels 要点: 1、伪标签:由经过标记源数据训练的分类器,对未标记目标数据做出的置信预测,被广泛应用于使模型适应未标记数据,例如半监督学习 2、由于固有的数据…

bat批处理脚本大全

目录 1、echo 2、注释 3、常见cmd命令 4、参数与变量 5、for循环 6、函数 7、数组 在windows上编程或者制作一些小工具,少不了使用批处理脚本,而且在各种开发环境搭建中我们经常会看到批处理脚本。批处理脚本以cmd命令为基础,增加一些变量和参…

【学生毕业设计】基于web学生信息管理系统网站的设计与实现(13个页面)

🎉精彩专栏推荐 💭文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业: 【📚毕设项目精品实战案例 (10…

【计算机毕业设计】50.课程设计管理系统

一、系统截图(需要演示视频可以私聊) 摘 要 网络的广泛应用给生活带来了十分的便利。所以把课程设计管理与现在网络相结合,利用JSP技术建设课程设计管理系统,实现课程设计管理的信息化。则对于进一步提高课程设计管理发展&#x…

【图像分割】基于神经气体网络 (NGN)实现图像分割附matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法 …

华为开源自研AI框架昇思MindSpore应用实践:DCGAN生成漫画头像

目录一、原理说明1.GAN基础原理2.DCGAN原理二、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例三、数据准备与处理1.数据处理四、创建网络1.生成器2.判别器3.损失和优化器4.优化器五、训练模型六、结果展示本教程是通过示例代码说明DCGAN网络如何设置网络、优化器、…

Pytorch学习笔记 (参考官方教程)

参考: pytorch官网教程 文章目录一、快速开始(Quick Start)数据处理(Working with data)创建模型(Creating Models)优化模型参数(Optimizing the Model Parameters)保存模…

光环:研发云搭建及人才梯队建设——姚冬

摘要:文章内容主要来源于光环国际2022年第三届中国科创者大会姚冬老师的分享,原分享名称为"数字化时代的研发效能建设"。讲述了华为在研发上整套流程规范,通过云的方式去实现人机协同,保持人去做创新型工作。对人才梯队…

方形平板振动克拉尼图形可视化计算MATLAB程序(Chladni Patterns)

方形平板振动克拉尼图形可视化计算MATLAB程序(Chladni Patterns)0前言1 数值时域求解1.1 方程建立1.2 数值差分方程建立1.3 计算结果2 简单的波动解3 理论求解惯例声明:本人没有相关的工程应用经验,只是纯粹对相关算法感兴趣才写此…

云计算技术架构-云计算四种模式(公有云、私有云、混合云、行业云)

接下来几篇主要从技术角度介绍云计算的架构:  云计算四种模式:公有云、私有云、混合云和行业云(本文讲述) 云计算架构:基础架构层、云平台层、业务应用层和业务管理层  云计算服务模式:IaaS、PaaS和…

Python按单元格读取复杂电子表格(Excel)数据实践

Python读取电子表格方法 本文所使用电子表格的目标是读取、解析来自Excel编制的数据报表,或者软件界面导出的数据报表,这类电子表格报表显著特点是有一定的格式,且数据位置不连续,而非标准二维数据表。 关于电子表格&#xff0c…

基于粒子群算法的配电网重构研究matlab程序

基于粒子群算法的配电网重构研究matlab程序 参考文献:基于改进灰狼算法的含分布式电源配电网重构研究 (本文未考虑分布式电源) 摘要:使用基本环矩阵编码的智能优化算法在处理配电网重构问题中,通常使用无序的解空间&a…

机械硬盘,Win10系统,磁盘100%

问题描述 使用机械硬盘,装了Win10系统,打开文件夹或程序,非常的慢,通过任务管理器查看性能,显示磁盘一直处于100%的状态。电脑概览如下: 电脑型号 技嘉 B460MAORUSPRO 操作系统 Microsoft Windows 10 专业…

PyQt5学习笔记--多线程处理、数据交互

目录 1--引入多线程的原因 2--PyQt多线程的基本知识 3--多线程登录程序的实例 4--参考 1--引入多线程的原因 ① 如果Qt只采用单线程任务的方式,当遇到数据处理慢的情形时,会出现GUI卡死的情况。 ② 使用下述例子展示单线程任务的缺陷: …

Java学习之继承的本质(重要)

目录 目录 一、一个继承的代码案例 二、子类创建的内存布局 三、查找顺序 一、son.name的输出结果 二、son.age的输出结果 三、son.hobby的输出结果 一、一个继承的代码案例 package com.hspedu.entends_;/*** 讲解继承的本质*/ public class ExtendsTheory {public sta…

Spring Boot 项目的创建和简单使用

目录 1. 什么是 Spring Boot, Spring Boot 框架有什么优点 2. Spring Boot 项目的创建 2.1 在 IDEA 下安装 Spring Boot Helper 插件: 2.2 创建 Spring Boot 项目: 2.3 网页版创建 Spring Boot 项目 3. Spring Boot 通过路由映射到本地程序 1. 什么是 Spring Boot, Spring …

MFC编辑框控件属性和用法

目录 一、编辑框的属性 1.want return 2.Multiline 3.滚动条 4.添加完效果 二、初始化编辑框内容 三、复制与退出 四、edit control的值类型 五、思维拓展 一、编辑框的属性 默认情况下编辑框edit control 是可以横向无限输入的 1.want return 支持换行,…

dreamweaver作业静态HTML网页设计模板——迪士尼影视电影(6页)带音乐

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置,有div的样式格局,这个实例比较全面,有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 文章目录一、网页介绍一…

Private Execution on Blockchain

1.Alan Szepieniec: Ghost-Queen Chess——复杂金融合约 Alan Szepieniec为Neptune合伙人。 为何需关注decentralized Finance? 1)从学术角度来看:是 密码学 ∩\cap∩ 分布式系统 ∩\cap∩ 经济学 ∩\cap∩ …的集合。2)从工程…