当前位置: 首页 > news >正文

推荐系统-ALS协同过滤算法实现

从协同过滤的分类来说,ALS(Alternating Least Squares,交替最小二乘)算法属于User-Item CF,也叫做混合CF,它同时考虑了User和Item两个方面,通过数量相对少的未被观察到的隐藏因子,来解释大量用户和物品之间潜在联系。ALS基于矩阵分解通过降维的方法来补全用户-物品矩阵,对矩阵中没有出现的值进行估计。

用户和物品的关系,可以抽象为如下的三元组:<User,Item,Rating>。其中,Rating是用户对商品的评分,表征用户对该商品的喜好程度。

ALS基本假设:任何一个评分矩阵均可近似分解成两个低维的用户特征矩阵和物品特征矩阵。矩阵分解过程可理解成将用户和物品均抽象的映射到相同的低维潜在特征空间中。因此其基本思想是对稀疏矩阵进行模型分解,评估出缺失项的值,以此来得到一个基本的训练模型,然后依照此模型可以针对新的用户和物品数据进行评估。ALS是采用交替的最小二乘法来算出缺失项,交替最小二乘法是在最小二乘法的基础上发展而来的。

1、spark代码实现

1.1 数据入口

case class ProductRating(userId:Int, productId:Int, score:Double)

/** 训练最好模型输出

  • @param bestModel 模型
  • @param bestRanks 隐含因子
  • @param bestIters 迭代次数
  • @param bestLambdas 惩罚值
  • @param bestRmse 最佳方差值**/
    case class BestModel(bestModel:Option[MatrixFactorizationModel], bestRanks:Int, bestIters:Int, bestLambdas:Double, bestRmse:Double)

def main(args: Array[String]): Unit = {val sparkConf = new SparkConf().setMaster(config("spark.cores")).setAppName("ALSTrainer")//创建sparkSessionval spark = SparkSession.builder().config(sparkConf).getOrCreate()//加载数据,作为rating, rdd需要应用aslval ratingRDD = getDFFromCass(spark, "cdp", "t_user_item_rating").as[ProductRating].rdd.map(rating => Rating(rating.userId, rating.productId, rating.score))//数据切分为训练集合测试集val splits = ratingRDD.randomSplit(Array(0.8, 0.2))val trainingRDD = splits(0)val testingRDD = splits(1)//核心实现,输出最优参数val bestModel = RmseUtil.predictBestRmse(trainingRDD, testingRDD)println("bestModel" + bestModel.bestRmse)val itemRecs = recommender(spark, ratingRDD, 10)//output result to cassandrasaveToCass(itemRecs.toDF(), "cdp", "t_user_recs")spark.stop()}

1.2 数据加载

我们使用cassandra大数据库,实现数据的输入与存储;

 def saveToCass(saveDF: DataFrame, keyspace: String, tableName: String): Unit = {saveDF.write.format("org.apache.spark.sql.cassandra").options(Map("keyspace" -> keyspace, "table" -> tableName)).mode(SaveMode.Append).option("spark.cassandra.output.consistency.level", "ONE").save()}def getDFFromCass(spark: SparkSession, keyspace: String, tableName: String): DataFrame = {val userItemDF = spark.read.format("org.apache.spark.sql.cassandra").options(Map("keyspace" -> keyspace, "table" -> tableName)).load().toDF("userId", "itemId", "rating")userItemDF}

1.3 基于spark mllib物品推荐

建立ALS算法模型,设置模型参数(通过模型参数评估获得最优解),调用recommendProductsForUsers方法为用户推荐指定数量的物品。

  def recommender(spark: SparkSession, ratingRDD: RDD[Rating],  recommendNum: Int): DataFrame={val splits = ratingRDD.randomSplit(Array(0.8, 0.2))val trainRDD= splits(0)val testRDD = splits(1)//建立ALS推荐模型val model = new ALS().setRank(5).setIterations(20).setLambda(0.01).setImplicitPrefs(false).setUserBlocks(-1).setProductBlocks(-1)//设置ratingRDD为所有用户推荐.run(trainRDD)val testUsersProductRDD = testRDD.map { case Rating(user, product, rate) => (user, product) }//得到预测评分的数据集val predictionRDD = model.predict(testUsersProductRDD).map {case Rating(user, product, rate) => ((user, product), rate)}//真实评分数据集与预测评分数据集进行合并val ratesAndPreds = testRDD.map { case Rating(user, product, rate) => ((user, product), rate) }.join(predictionRDD)//计算RMSE,这里的r1就是真实结果,r2就是预测结果val MSE = ratesAndPreds.map {case ((user, product), (r1, r2)) =>val err = (r1 - r2)err * err}.mean()println("Mean Squared Error = " + MSE)//用户推荐recommendNum个商品val userSubsetRecs = model.recommendProductsForUsers(recommendNum)//推荐商品列表val itemRecDF = userSubsetRecs.toDF("userId", "recommends")itemRecDF.show(5)itemRecDF}

1.4 模型参数评估

预测模型评估,预测出最好的模型参数BestModel

object RmseUtil {/*** 训练集合* @param trainingData 训练集合* @param testingData 测试集合* @return*/def predictBestRmse(trainingData:RDD[Rating], testingData:RDD[Rating]): BestModel = {var bestModel: Option[MatrixFactorizationModel] = Nonevar bestRanks = -1var bestIters = 0var bestLambdas = -1.0var bestRmse = Double.MaxValue//多重迭代法求最佳参数模型//迭代次数val numIters = List(5, 10, 20)//隐含因子val numRanks = List(8, 10, 12)//惩罚值(正则化值)val numLambdas = List(0.01, 0.1, 1)//共3*3*3种组合,每种组合迭代次数又不一样,在此会消耗大量时间for (rank <- numRanks; iter <- numIters; lambdas <- numLambdas) {//als参数为 训练集合 隐含因子 迭代次数 惩罚因子val model = ALS.train(trainingData, rank, iter, lambdas)val validationRmse = rmseComputer(model, testingData)//逐步迭代if (validationRmse < bestRmse) {bestModel = Some(model)bestRmse = validationRmsebestIters = iterbestLambdas = lambdasbestRanks = rank}}BestModel(bestModel, bestRanks, bestIters, bestLambdas, bestRmse)}
}/**** @param model       训练模型* @param dataOfTest  用于测试数据集合(一般是笛卡尔积)* @return*/def rmseComputer(model: MatrixFactorizationModel, dataOfTest: RDD[Rating]):Double= {//预测评分矩阵:预测返回结果<user product rating>val predictResult = model.predict(dataOfTest.map(item => (item.user, item.product)))//将预测值和测试值组成一个map然后比较预测的评分值和实际值val predict = predictResult.map(item => ((item.user, item.product), item.rating))val actual = dataOfTest.map(item => ((item.user, item.product), item.rating))val predJoinPrevActual = predict.join(actual).values//直接调用回归库函数需要传入一个(prediction,actualValue)val evaluator = new RegressionMetrics(predJoinPrevActual)evaluator.meanAbsoluteError}

相关文章:

推荐系统-ALS协同过滤算法实现

从协同过滤的分类来说&#xff0c;ALS&#xff08;Alternating Least Squares&#xff0c;交替最小二乘&#xff09;算法属于User-Item CF&#xff0c;也叫做混合CF&#xff0c;它同时考虑了User和Item两个方面&#xff0c;通过数量相对少的未被观察到的隐藏因子&#xff0c;来…...

QT第三讲

思维导图 蜡笔小新闹钟 需求&#xff1a; 实现 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QTime> //时间类 #include<QTimerEvent> //事件处理类 #include<QtTextToSpeech> //文本转语音类 #include<QMessageBo…...

Linux内核的I2C驱动框架详解------这应该是我目前600多篇博客中耗时最长的一篇博客

目录 1 I2C驱动整体框架图 2 I2C控制器 2.1 I2C控制器设备--I2C控制器在内核中也被看做一个设备 2.2 i2c控制器驱动程序 2.3 platform_driver结构体中的probe函数做了什么 2.3.1 疑问&#xff1a; i2cdev_notifier_call函数哪里来的 2.3.2 疑问&#xff1a;为什么有两…...

【点云处理教程】05-Python 中的点云分割

一、说明 这是我的“点云处理”教程的第 5 篇文章。“点云处理”教程对初学者友好&#xff0c;我们将在其中简单地介绍从数据准备到数据分割和分类的点云处理管道。 在上一教程中&#xff0c;我们看到了如何过滤点云以减少噪声或其密度。在本教程中&#xff0c;我们将应用一些聚…...

代码随想录算法训练营之JAVA|第十七天| 654. 最大二叉树

今天是第17天刷leetcode&#xff0c;立个flag&#xff0c;打卡60天。 算法挑战链接 654. 最大二叉树https://leetcode.cn/problems/maximum-binary-tree/description/ 第一想法 错误的想法&#xff0c;就不说了。 看完代码随想录之后的想法 用递归模拟真实的过程 如果我…...

C++重写函数、隐藏函数、重载函数的区别对比

目录 1.函数重载 1.1定义 1.2函数重载的规则&#xff1a; 1.3函数重载的作用&#xff1a; 2.函数重写&#xff1a; 2.1定义 2.2例子&#xff1a; 3.函数隐藏 3.1定义 3.2举个例子&#xff1a; 1.函数重载 1.1定义 我们在学类和对象的封装特性时学过一个词叫重载&#xff0c…...

15.python设计模式【函数工厂模式】

1.知识讲解 内容&#xff1a;定义一个字典&#xff0c;在python中一切皆对象&#xff0c;将所有的函数进行封装&#xff0c;然后定一个分发函数进行分发&#xff0c;将原来if…else全部干掉。角色&#xff1a; 函数&#xff08;function&#xff09;函数工厂&#xff08;funct…...

Redis主从复制、哨兵、cluster集群原理+实验

目录 一、Redis 主从复制 1、主从复制的作用 2、主从复制流程 3、搭建Redis 主从复制 安装Redis&#xff08;所有主机) 修改Master节点Redis配置文件 修改Slave节点Redis配置文件 验证主从效果 一、Redis 主从复制 主从复制&#xff0c;是指将一台Redis服务器的数据&am…...

微信小程序如何实现页面传参?

前言 只要你的小程序超过一个页面那么可能会需要涉及到页面参数的传递&#xff0c;下面我总结了 4 种页面方法。 路径传递 通过在url后面拼接参数&#xff0c;参数与路径之间使用 ? 分隔&#xff0c;参数键与参数值用 相连&#xff0c;不同参数用 & 分隔&#xff1b;如…...

OPC DA 客户端与服务器的那点事

C#开发OPC客户端&#xff0c;使用OPCDAAuto.dll。在开发过程中偶遇小坎坷&#xff0c;主要记录一下问题解决办法。 1、建立客户端&#xff0c;参考链接。建立WinFrom工程&#xff0c;将博客中代码全部复制即可运行&#xff1a; https://www.cnblogs.com/kjgagaga/p/17011730.…...

Java 错误异常介绍(Exceptions)

1、异常介绍 异常是程序执行期间发生的意外事件。它影响程序指令流&#xff0c;从而导致程序异常终止。 发生异常的原因有很多。其中包括&#xff1a; 无效的用户输入 设备故障 网络连接丢失 物理限制&#xff08;磁盘内存不足&#xff09; 代码错误 打开一个不可用的文…...

每日一题——旋转数组的最小数字

题目 有一个长度为 n 的非降序数组&#xff0c;比如[1,2,3,4,5]&#xff0c;将它进行旋转&#xff0c;即把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;变成一个旋转数组&#xff0c;比如变成了[3,4,5,1,2]&#xff0c;或者[4,5,1,2,3]这样的。请问&#xff0c;给定这…...

SpringBoot Jackson 日期格式化统一配置

目录 1.在全局配置文件配置 2.通过JavaBean方式配置 1.在全局配置文件配置 spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT8 该配置方式仅支持 Date 类型的日期格式化&#xff0c;不支持LocalDate 及 LocalDateTime 的格式化。 2.通过JavaBean方式配置 …...

剑指 Offer 38. 字符串的排列 / LeetCode 47. 全排列 II(回溯法)

题目&#xff1a; 链接&#xff1a;剑指 Offer 38. 字符串的排列 难度&#xff1a;中等 输入一个字符串&#xff0c;打印出该字符串中字符的所有排列。 你可以以任意顺序返回这个字符串数组&#xff0c;但里面不能有重复元素。 示例: 输入&#xff1a;s “abc” 输出&…...

【前端知识】React 基础巩固(四十三)——Effect Hook

React 基础巩固(四十三)——Effect Hook 一、Effect Hook的基本使用 Effect Hook 用来完成一些类似class中生命周期的功能。 在使用类组件时&#xff0c;不管是渲染、网路请求还是操作DOM&#xff0c;其逻辑和代码是杂糅在一起的。例如我们希望把计数器结果显示在标签上&…...

一百三十八、ClickHouse——使用clickhouse-backup备份ClickHouse库表

一、目标 使用clickhouse-backup在本地全库备份ClickHouse的数据库 二、前提 已经安装好clickhouse-backup 注意&#xff1a;由于之前同事已经按照好clickhouse-backup&#xff0c;所以我就没有安装 如有需要请参考其他人的博客安装一下&#xff0c;下面是我认为比较好的一…...

【无标题】使用Debate Dynamics在知识图谱上进行推理(2020)7.31

使用Debate Dynamics在知识图谱上进行推理 摘要介绍背景与相关工作我们的方法 摘要 我们提出了一种新的基于 Debate Dynamics 的知识图谱自动推理方法。 其主要思想是将三重分类任务定义为两个强化学习主体之间的辩论游戏&#xff0c;这两个主体提取论点&#xff08;知识图中…...

windows下若依vue项目部署

下载若依项目&#xff0c;前端后端项目本地启动前端打包&#xff0c;后端打包配置nginx.conf 需要注意的是&#xff1a;路径别用中文&#xff0c;要不然报错 #前台访问地址及端口80&#xff0c;在vue.config.js中可查看server {listen 80;server_name localhost; #后台…...

【目标检测】基于yolov5的水下垃圾检测(附代码和数据集,7684张图片)

写在前面: 首先感谢兄弟们的订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 路虽远,行则将至;事虽难,做则必成。只要有愚公移山的志气、滴水穿石的毅力,脚踏实地,埋头苦干,积跬步以至千里,就…...

P1734 最大约数和

题目描述 选取和不超过 S 的若干个不同的正整数&#xff0c;使得所有数的约数&#xff08;不含它本身&#xff09;之和最大。 输入格式 输入一个正整数 S。 输出格式 输出最大的约数之和。 输入输出样例 输入 11 输出 9 说明/提示 【样例说明】 取数字 4 和 6&a…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...