推荐算法——ALS模型算法分析、LFM算法_蒋含竹的博客-程序员宅基地

技术标签: AlgoAndDataStructure  机器学习  ALS  算法分析  MachineLearning  大数据  Python  推荐算法  

推荐算法——ALS模型算法分析、LFM算法

简介

  • ALS(Alternating Least Squares),即交替最小二乘法,因利用两个矩阵进行交替优化而得名。求解大致步骤如下:
    • 定义原始矩阵 A m , n = U m , k ∗ V k , n A_{m,n} = U_{m,k} * V_{k,n} Am,n=Um,kVk,n
    • U m , k U_{m,k} Um,k随机取值,固定 U m , k U_{m,k} Um,k,利用最小二乘法求出 V k , n V_{k,n} Vk,n
    • 固定 V k , n V_{k,n} Vk,n,利用最小二乘法求出 U m , k U_{m,k} Um,k
    • 持续交替进行求解,直到损失达到阈值(即新矩阵近似于原始矩阵)
  • 比较经典的应用则是隐语义分析-推荐算法:原始矩阵为稀疏矩阵,通过ALS计算出的新矩阵则拥有原始矩阵缺失的值,即预测值。

ALS算法流程分析

  • 数据(矩阵 A m n A_{mn} Amn

    user/item 商品1 商品2 商品3 商品4
    用户1 9 - 6 8
    用户2 3 9 - 4
    用户3 - - 6 8
    用户4 9 8 5 9
    用户5 8 7 6 -
    • 我们的原始数据是不同用户对于不同商品的评分或喜好程度。因为用户不可能买过每样商品,因此会存在部分商品未评分的情况。
  • 算法目标:挖掘出用户对未购买过的商品的喜好程度,也就是说要分析出原始稀疏矩阵 A m , n A_{m,n} Am,n中的缺失值。

  • 利用ALS算法,将稀疏矩阵 A m , n A_{m,n} Am,n拆解为两个矩阵 U m , k U_{m,k} Um,k V k , n V_{k,n} Vk,n,即 A m , n = U m , k ∗ V k , n A_{m,n} = U_{m,k} * V_{k,n} Am,n=Um,kVk,n

    • k代表了用户与商品的隐含关联特征个数,需要使用者指定
    • U m , k U_{m,k} Um,k代表了用户与k个隐含特征的值
    • V k , n V_{k,n} Vk,n代表了商品与k个隐含特征的值(不过是逆矩阵形式)
  • 按照ALS算法的流程,需要先固定矩阵 U m , k U_{m,k} Um,k

    • 此处数据中:m=5,n=4。我们假定 k=3,并随机充填矩阵 U 5 , 3 U_{5,3} U5,3
    • 得到的矩阵 U 5 , 3 U_{5,3} U5,3,如下
      user/k k1 k2 k3
      用户1 3 5 6
      用户2 4 3 3
      用户3 2 5 3
      用户4 6 2 2
      用户5 5 3 4
  • 此时,已知矩阵 A 5 , 4 A_{5,4} A5,4部分值(稀疏)、矩阵 U 5 , 3 U_{5,3} U5,3所有值,需要求解矩阵 V 3 , 4 V_{3,4} V3,4

    • 未知矩阵 V 3 , 4 V_{3,4} V3,4,如下
      k/item 商品1 商品2 商品3 商品4
      k1 w11 w12 w13 w14
      k2 w21 w22 w23 w24
      k3 w31 w32 w33 w34
  • 那么该如何求解呢?不急,我们先看看矩阵乘法计算公式, U 5 , 3 ∗ V 3 , 4 = A 5 , 4 U_{5,3} * V_{3,4} = A_{5,4} U5,3V3,4=A5,4的示例如下

    • 商品1与所有用户的计算,如下
      • 3 ∗ w 11 + 5 ∗ w 21 + 6 ∗ w 31 = 9 3 * w_{11} + 5 * w_{21} + 6 * w_{31} = 9 3w11+5w21+6w31=9
      • 4 ∗ w 11 + 3 ∗ w 21 + 3 ∗ w 31 = 3 4 * w_{11} + 3 * w_{21} + 3 * w_{31} = 3 4w11+3w21+3w31=3
      • 2 ∗ w 11 + 5 ∗ w 21 + 3 ∗ w 31 = 缺 失 值 2 * w_{11} + 5 * w_{21} + 3 * w_{31} = 缺失值 2w11+5w21+3w31=
      • 6 ∗ w 11 + 2 ∗ w 21 + 2 ∗ w 31 = 9 6 * w_{11} + 2 * w_{21} + 2 * w_{31} = 9 6w11+2w21+2w31=9
      • 5 ∗ w 11 + 3 ∗ w 21 + 4 ∗ w 31 = 8 5 * w_{11} + 3 * w_{21} + 4 * w_{31} = 8 5w11+3w21+4w31=8
    • 商品2与所有用户的计算,如下
      • 3 ∗ w 12 + 5 ∗ w 22 + 6 ∗ w 32 = 缺 失 值 3 * w_{12} + 5 * w_{22} + 6 * w_{32} = 缺失值 3w12+5w22+6w32=
      • 4 ∗ w 12 + 3 ∗ w 22 + 3 ∗ w 32 = 9 4 * w_{12} + 3 * w_{22} + 3 * w_{32} = 9 4w12+3w22+3w32=9
      • 2 ∗ w 12 + 5 ∗ w 22 + 3 ∗ w 32 = 缺 失 值 2 * w_{12} + 5 * w_{22} + 3 * w_{32} = 缺失值 2w12+5w22+3w32=
      • 6 ∗ w 12 + 2 ∗ w 22 + 2 ∗ w 32 = 8 6 * w_{12} + 2 * w_{22} + 2 * w_{32} = 8 6w12+2w22+2w32=8
      • 5 ∗ w 12 + 3 ∗ w 22 + 4 ∗ w 32 = 7 5 * w_{12} + 3 * w_{22} + 4 * w_{32} = 7 5w12+3w22+4w32=7
    • 其他同理…
  • 从每个商品与所有用户的计算公式中,不难发现一个商品的所有w值与其他商品的w值无关!因此,不同商品的w值计算,我们可以分开来做。

  • 回想一下,机器学习中的线性回归!同理,我们可以将求一个商品的多个w值看作多元线性回归:

    • 例如求商品1的多个w值
      • 矩阵 V 3 , 4 V_{3,4} V3,4中的第一列的 w 11 w_{11} w11 w 21 w_{21} w21 w 31 w_{31} w31是待求的系数
      • 矩阵 U 5 , 3 U_{5,3} U5,3中的所有行的值是用于训练的数据
      • 矩阵 A 5 , 4 A_{5,4} A5,4中第一列的9、3、缺失值、9、8是标签数据
      • 注意:标签为缺失值的部分,即待预测的值,不参与计算
    • 其他商品同理
  • 因此,我们可以利用线性回归(ALS中是最小二乘法)求出所有商品的w值,即得到矩阵 V 3 , 4 V_{3,4} V3,4

  • 接着,固定矩阵 V 3 , 4 V_{3,4} V3,4,反过来求解矩阵 U 5 , 3 U_{5,3} U5,3

  • 如此反复的进行多次求值

  • 直到 U 5 , 3 ∗ V 3 , 4 U_{5,3} * V_{3,4} U5,3V3,4得到得矩阵与矩阵 A 5 , 4 A_{5,4} A5,4的损失小于某个阈值(或是达到一定次数),既可完成求解

  • 最终,推荐算法使用时,利用求得的矩阵 U 5 , 3 ∗ V 3 , 4 U_{5,3} * V_{3,4} U5,3V3,4,可以预测出用户对未购买过的商品的喜好程度,从而进行推荐!

  • Spark ALS模型使用示例:《Spark高级数据分析》——音乐推荐(ALS算法)

LFM梯度下降算法-示例

  • 导包
    import numpy as np
    import pandas as pd
    
  • 准备User-Item数据
    # 定义User-Item稀疏矩阵
    # 0代表矩阵的缺失值
    R = np.array(
        [[8, 9, 2, 2,0, 1],
        [3, 2, 5, 6, 0, 0],
        [8, 8, 0, 3, 7, 2],
        [3, 3, 0, 8, 8, 1],
        [7, 0, 3, 2, 5, 9],
        [0, 2, 2, 6, 7, 1],
        [8, 0, 3, 0, 4, 0],
        [3, 9, 0, 8, 6, 8],
        [3, 2, 5, 0, 8, 0],
        [6, 2, 3, 8, 0, 7]]
    )
    
  • LFM梯度下降算法
    def lfm_gradient_descent(R, k=3, steps=1000, alpha=0.001, lam=0.0001):
        """
        LFM梯度下降算法
        
        :param R: 原始稀疏矩阵 User-Item
        :param k: User与Item之间的隐含特征个数
        :param steps: 最大迭代次数
        :param alpha: 学习曲率
        :param lam: 正则化系数
        """
        
        m = len(R)
        n = len(R[0])
        
        # 随机初始化矩阵U,V
        P = np.random.rand(m, k)
        Q =  np.random.rand(k, n)
        
        # 最大迭代steps次
        for step in range(steps):
            # 修正矩阵P、Q
            for user in range(m):
                for item in range(n):
                    # 跳过稀疏矩阵A的缺失值部分
                    if R[user][item] > 0:
                        # 误差
                        error = np.dot(P[user,:], Q[:, item]) - R[user][item]
                        # 利用误差error更新矩阵P、Q
                        for i in range(k):
                            P[user][i] -= alpha * (2 * error * Q[i][item] + 2 * lam * P[user][i])
                            Q[i][item] -= alpha * (2 * error * P[user][i] + 2 * lam * Q[i][item])
            # 计算新矩阵与原始稀疏矩阵的损失
            # newR = np.dot(P, Q)
            cost = 0
            for user in range(m):
                for item in range(n):
                    if R[user][item] > 0:
                   		# 损失
                        cost += (np.dot(P[user,:], Q[:,item]) - R[user][item]) ** 2
                        # 正则化
                        cost += lam * sum(P[user,:]**2) + lam * sum(Q[:,item]**2)
                               
            # 达到阈值,跳出迭代
            if cost < 0.5:
                break;
                
        return P,Q
    
  • 调用算法与结果展示
    P,Q = lfm_gradient_descent(R, 4, 10000, 0.005, 0.0005)
    
    print("--------- 矩阵P ---------")
    print(P)
    print("--------- 矩阵Q ---------")
    print(Q)
    print("--------- 新矩阵P*Q ---------")
    print(np.dot(P, Q))
    print("--------- 原始稀疏矩阵R ---------")
    print(R)
    
  • 打印结果展示
    --------- 矩阵P ---------
    [[ 2.47101945 -0.09314859  1.38122566  0.23276072]
     [-0.4175392   0.88409428  0.62463847  2.39820982]
     [ 2.10106116  0.1731982   1.56076663  0.37699979]
     [ 0.98266167  2.10821349  0.74604873  0.13698655]
     [ 0.46591391 -0.45260323  1.54408459  1.95285085]
     [ 0.62855731  1.56571349  1.05862982  0.00706062]
     [ 0.95726687 -1.11403965  1.48064885  2.10244858]
     [ 1.97143103  1.32056111 -0.72112522  2.56245347]
     [ 0.07027225  2.03254073  0.78322988  1.50645914]
     [-0.04846877  1.64219853  2.02188288  1.15083635]]
     --------- 矩阵Q ---------
    [[ 1.58242819  3.19303543  0.95667258  0.48655993  1.21054208 -0.6060828 ]
     [-0.35870851 -0.34836087  1.15881715  3.27881658  2.32052529  0.09664613]
     [ 2.78744452  0.53842092 -0.49708206  0.58858015  2.40623536  1.15769018]
     [ 0.92791198  1.38316166  1.951467    1.22337834  0.88932108  3.86373607]]
     --------- 新矩阵P*Q ---------
    [[ 8.00969538  8.98812847  2.02365673  1.99459832  6.30567239  0.99171252]
     [ 2.98861476  2.01222899  4.99458605  5.99719289  5.1819201  10.32769524]
     [ 7.96302376  8.0102283   2.17060619  2.97002692  7.03617947  2.0068338 ]
     [ 3.0054383   2.99441722  3.2795967   7.99726497  7.99870986  1.00114949]
     [ 7.01575177  5.17782475  2.96462993  2.04058504  4.96587355  9.00674711]
     [ 3.39043557  2.04132685  1.90325185  6.07124444  6.94776448  1.02320811]
     [ 7.99253533  7.14991343  2.99167776  0.2566066   4.00619612  9.14958844]
     [ 3.01358624  8.99083579  8.77530468  7.99950709  5.99454255  7.99858102]
     [ 2.96318244  2.02170798  4.97304635  9.00248294  8.02599098  6.88114446]
     [ 6.03799225  1.95357653  3.09741652  7.9588332   9.64067885  6.97533011]]
     --------- 原始稀疏矩阵R ---------
    [[8 9 2 2 0 1]
     [3 2 5 6 0 0]
     [8 8 0 3 7 2]
     [3 3 0 8 8 1]
     [7 0 3 2 5 9]
     [0 2 2 6 7 1]
     [8 0 3 0 4 0]
     [3 9 0 8 6 8]
     [3 2 5 0 8 0]
     [6 2 3 8 0 7]]
    
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/alionsss/article/details/104302010

智能推荐

文盘 Rust -- struct 中的生命周期_rust struct-程序员宅基地

在开发中,不免要定义 struct 中的某些元素为 trait object,从而带来一些 rust 语言中的生命周期问题。接下来,定义一个 struct 包含两个 Base trait 的 trait object ,然后实现一个函数是 say 函数输出的字符串的拼接结果。编译器给出的提示很明确,要在 trait object 上添加生命周期参数,确保 struct 和他的 trait object 元素在同一生命周期,避免悬垂指针。很遗憾,以上代码是不能编译通过的,编译时报如下错误。_rust struct

关于win10开启/关闭开机密码and设置开机启动项and开启/禁止win10后台自动更新-程序员宅基地

一.win10开启/关闭开机密码1.右键点击windows;2.点击运行; 3.输入netplwiz,点击确定; 4.当需要开启开机密码时,勾选下图选项,反之不勾选。 二.如何设置开机启动项1.在下栏任意空白位置点击鼠标右键,打开任务管理器; 2.点击菜单栏中的启动,然后在状态栏下方点击鼠标右键,即可启动/禁用项目。(启动...

【Win10】Hexo 搭建个人主页 (十一)添加网易云音乐_hexo liveforcode主题设置背景音乐-程序员宅基地

前言本篇博文是关于。如果对于搭建等其它方面有需要了解的,读者可以阅读前几篇比较优质的文章:推荐阅读:【Win10】搭建个人博客 Hexo框架 (自制)推荐阅读:【Win10】搭建个人博客 Hexo框架(部署到 github 上并 导入美化样式 )推荐阅读:【Win10】Hexo 搭建个人主页 (一)解决所有文章,缺失模块问题推荐阅读:【Win10】Hexo 搭建个人主页 (二)配置图..._hexo liveforcode主题设置背景音乐

Java.io----Input/Output_java 日曜日转换-程序员宅基地

InputStream字节输入流(抽象类)字节输入类的父类AudioInputStream(高级流):音频数据的字节流ByteArrayInputStream:从字节数组中按字节读取数据FileInputStream:从文件中按字节读取数据FilterInputStream:BufferedInputStream(高级流):当获取到低级字节输入流可以转换为高级数..._java 日曜日转换

MySQL中InnoDB页结构和索引的存储_索引存的是页还是id-程序员宅基地

局部性原理:OS虽然IO操作只读取一部分数据,但是OS每次IO操作取值都是以页为单位,一页=4kb。1.InnoDB数据页结构页是InnoDB管理存储空间的基本单位:1页=16kb = 16384查看数据库页的大小SQL:show global status like ‘Innodb_page_size’;一个InnoDB数据页的存储结构:名称占用空间大小简单描述..._索引存的是页还是id

还是被拒绝了_hf您的开始请求被拒绝-程序员宅基地

HF已经尽了她最大的努力,笔试过了,面试也过了,但还是在审核的时候被拒了,非常非常地可惜,但现实就是如此残酷,没办法。一个很好的机会就这样失去了,无话可说,已经尽了一切能尽的最大努力。现在想回来,其实应该去省教育厅问一下,提前将教师资格证要下来,或者直接给个电话,让管事的人去处理,但这一步没走,因为当时没有想到。HF为此回清远拿了证明,而且在4号下午已经上车的情况下又下车了,搞到晚上还_hf您的开始请求被拒绝

随便推点

SSL证书详解和CFSSL工具使用-程序员宅基地

SSL证书详解和CFSSL工具使用1.公钥基础设施PKI基础概念CA(Certification Authority)证书,指的是权威机构给我们颁发的证书。密钥就是用来加解密用的文件或者字符串。密钥在非对称加密的领域里,指的是私钥和公钥,他们总是成对出现,其主要作用是加密和解密。常用的加密强度是2048bit。RSA即非对称加密算法。非对称加密有两个不一样的密码,一个叫私钥,另一个叫公钥,用其中一个加密的数据只能用另一个密码解开,用自己的都解不了,也就是说用公钥加密的数据只能由私钥解开。证书的编码_cfssl

Windows_Reverse1-程序员宅基地

目录0x0 题目涉及知识点0x1 查壳脱壳0x2 反汇编分析0x3写脚本0x0 题目涉及知识点简单脱壳指针运算位移量字符串查询0x1 查壳脱壳使用 UPX 工具脱壳0x2 反汇编分析初步了解程序执行流程,sub_401000(&v6) 为加密过程,&v4中存放了flag。 char v4; // [esp+4h] [ebp-804h] char v5; // [esp+5h] [ebp-803h] char v6; // [esp+404h] [ebp_windows_reverse1

[ORA-01450] maximum key length (3215) exceeded_oracle主键maximum key length6394-程序员宅基地

背景:在进行索引在线表空间迁移的时候报出的错误,具体命令alter index index_name rebuild online tablespace tablespace_name;问题分析:9i之后每个index key最大可以为block size的80%。所以理论上来说,是可以创建最大长度为block size=8096*80%约为6400左右长度的index。但_oracle主键maximum key length6394

计算机网络对我们思维的影响,计算机网络教学中学生计算思维的培养_观察社的博客-程序员宅基地

一、引言近年来,美国卡内基·梅隆大学周以真教授对计算思维的系统阐述,引起了国内计算机学者的关注,在计算机基础课中进行计算思维培养的教学改革也迅速开展起来。计算机网络是高校的一门重要课程,也是计算机应用和信息技术类专业必修的基础课程。在这门课程的教学过程中加强计算思维的培养非常重要,它对于提升计算机网络课程教学水平、提高学生的学习能力乃至推动网络技术的发展都具有重要意义。二、计算思维的概念1996 ...

Max Script 入门教程_maxscript-程序员宅基地

启用max脚本数据类型基本使用基本数学操作建模操作语法函数导入导出应用实例总结 MAXscript是3ds Max内置脚本语言,Max2.0及以后加入的功能。也能使用在与3ds Max相关的产品中如Autodesk VIZ,character studio,Plasma和GMax;脚本可使用于建模,动画,材质,渲染等等。它是专门为3D Studio Max设计的。 – 摘_maxscript

用批处理文件改文件名-程序员宅基地

问题:我现在需要把一个文件夹里的几十个文件改名为对应的文件名,对应关系已经有了。 比如说 原来的文件名 需要改为的文件名 北京.txt 01.txt 天津.txt 02.txt 河北.txt 03.txt 我想写一个bat文件一次执行所有的修改,请问这个批处理文件该怎么写?原来dos时代的东西学的不好。谢谢各位了 解决方法:

推荐文章

热门文章

相关标签