创新实训(39)——学习基于Spark MLlib包的ALS推荐算法

前言

项目的后端工作已经差不多基本完成,这几天主要的工作都是在修复之前遗留下来的bug,并且优化代码的设计,在项目开始的时候,就想着基于Spark来进行推荐系统的设计,后来在项目开展的过程中,发现了Mohout这个推荐引擎,这个引擎的调用非常简单,可以自动的构建模型,计算相似度,然后进行推荐,也可以方面的扩展到Hadoop集群上,所以开始就是用Mohout实现了基于用户的协同过滤推荐,和基于物品的协同过滤推荐,今天想着来用Spark的MLlib库的ALS推荐算法训练模型,然后实现推荐。

Spark简介

大数据的计算引擎,基于hadoop的计算框架,与mapreduce类似,也是并行计算框架,优点是Spark的Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的MapReduce的算法。
他底层使用Scala实现,Scala可以像操作本地集合对象一样轻松地操作分布式数据集。
Spark提供了各种机器学习的算法,可以进行分布式的计算,并且基于hadoop动态扩展,运算效率很高。

Spark Mllib介绍

Spark 机器学习库从 1.2 版本以后被分为两个包:
(1)spark.mllib包含基于RDD的原始算法API。Spark MLlib 历史比较长,在1.0 以前的版本即已经包含了,提供的算法实现都是基于原始的 RDD。
(2)spark.ml 则提供了基于DataFrames 高层次的API,可以用来构建机器学习工作流(PipeLine)。ML Pipeline 弥补了原始 MLlib 库的不足,向用户提供了一个基于 DataFrame 的机器学习工作流式 API 套件。
一个典型的机器学习过程从数据收集开始,要经历多个步骤,才能得到需要的输出。这非常类似于流水线式工作,即通常会包含源数据ETL(抽取、转化、加载),数据预处理,指标提取,模型训练与交叉验证,新数据预测等步骤。
spark Mllib也一样是基于这个流程,它会将数据从数据源进行抽取,序列化之后,加载到集群中,然后进行模型的训练。

使用Spark Mllib的ALS算法进行协同过滤

Spark.ml目前支持基于模型的协同过滤,其中用户和商品以少量的潜在因子来描述,用以预测缺失项。Spark.ml使用交替最小二乘(ALS)算法来学习这些潜在因子。
显式与隐式反馈
基于矩阵分解的协同过滤的标准方法中,
“用户-商品”矩阵中的条目是用户给予商品的显式偏好,
例如,用户给电影评级。然而在现实世界中使用时,我们常常只能访问隐式反馈(如意见、点击、购买、喜欢以及分享等),在spark.ml中我们使用“隐式反馈数据集的协同过滤“来处理这类数据。本质上来说它不是直接对评分矩阵进行建模,而是将数据当作数值来看待,这些数值代表用户行为的观察值(如点击次数,用户观看一部电影的持续时间)。这些数值被用来衡量用户偏好观察值的置信水平,而不是显式地给商品一个评分。然后,模型用来寻找可以用来预测用户对商品预期偏好的潜在因子。

ALS算法的了解

学习于其他博客
https://blog.csdn.net/hellozhxy/article/details/82390162?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-1

(1)含义
在现实中用户-物品-评分矩阵是及其大的,用户消费有限,对单个用户来说,消费的物品的非常有限的,产生的评分也是比较少的,这样就造成了用户-物品矩阵有大量的空值。
假定用户的兴趣只受少数因素的影响,所以用户-物品矩阵可以分解为用户的特征向量矩阵和物品的特征向量矩阵(降维了)。用户的特征向量距离表示用户的兴趣(U),物品的特征向量矩阵代表用户的特点(V),合起来(内积)表示用户对物品的特点的兴趣,也就是喜好程度。
M=U*V

(2)协同过滤矩阵分解算法
2.1奇异值分解(SVD)
矩阵的奇异值分解是最简单的一种矩阵分解算法,主要是在UV中间加了个一个奇异值矩阵,公式如下:
M=U
(奇异值矩阵)*(V的共轭)
奇异值矩阵是对角矩阵,奇异值分解的缺点:1不允许分解矩阵有null值,需要进行填分,2如果填分,又有两个问题:1增加数据量,增加算法复杂度,2简单粗暴的填分方式会导致数据失真,如果将null值设置为0,那么会导致过度学习问题。

2.2正则化矩阵分解
加入正则化是为了解决稀疏矩阵可能过学习问题,评价矩阵分解是RMSE,通过最小化RMSE来学习用户特征矩阵U和物品特征矩阵V,在RMSE函数中加入了正则化项减少过拟合,公式如下,:
在这里插入图片描述
Spark使用的是带正则化矩阵分解,优化函数的方式选用的是交叉最小二乘法ALS

有关方法的学习

(1)SparkSession
这里我使用了Spark2.0中的新方法,SparkSession是spark2.0的全新切入点,以前都是sparkcontext创建RDD的,StreamingContext,sqlContext,HiveContext。
DataDrame提供的API慢慢的成为新的标准API,我们需要1个新的切入点来构建他,这个就是SparkSession,他可以进行Spark集群的链接
(2)JavaRdd
RDD,全称Resilient Distributed Datasets(弹性分布式数据集),是Spark最为核心的概念,是Spark对数据的抽象。RDD是分布式的元素集合,每个RDD只支持读操作,且每个RDD都被分为多个分区存储到集群的不同节点上。除此之外,RDD还允许用户显示的指定数据存储到内存和磁盘中,掌握了RDD编程是SPARK开发的第一步。

2.1创建操作

创建RDD有两种方式: 1 读取一个数据集(SparkContext.textFile()) :

JavaDStreamlines=jssc.textFileStream("/Users/huipeizhu/Documents/sparkdata/input/");
JavaReceiverInputDStreamlines = jssc.socketTextStream(“localhost”,
9999);

2 读取一个集合(SparkContext.parallelize()) :

Listlist = Arrays.asList(5, 4, 3, 2, 1); JavaRDDrdd =
sc.parallelize(list);

2.2转换操作
1:单个RDD转换操作
map() : 对每个元素进行操作,返回一个新的RDD
System.out.println(“RDD每个元素乘10:” + rdd.map(v -> v * 10)

filter() : 最每个元素进行筛选,返回符合条件的元素组成的一个新RDD
System.out.println(“RDD去掉1的元素:” + rdd.filter(v -> v != 1));

flatMap() : 对每个元素进行操作,将返回的迭代器的所有元素组成一个新的RDD返回
r.dd.flatMap(x -> x.to(3)).collect()

distinct():去重操作
System.out.println(“RDD去重操作:” + rdd.distinct());

rdd最大和最小值

Integer max= rdd.reduce((v1, v2) -> Math.max(v1, v2));

Integer min= rdd.reduce((v1, v2) -> Math.min(v1, v2))

2.2两个RDD的转化操作:

在这里插入图片描述

2.3行动操作
在这里插入图片描述
2.4
在这里插入图片描述

参考资料:https://www.cnblogs.com/diaozhaojian/p/9152530.html

(3) Dataset
在这里插入图片描述
在这里插入图片描述

参考资料:https://blog.csdn.net/gdkyxy2013/article/details/89513268

(4)Transformer:
翻译成转换器,是一种可以将一个DataFrame转换为另一个DataFrame的算法。比如一个模型就是一个 Transformer。它可以把 一个不包含预测标签的测试数据集 DataFrame 打上标签,转化成另一个包含预测标签的 DataFrame。技术上,Transformer实现了一个方法transform(),它通过附加一个或多个列将一个DataFrame转换为另一个DataFrame。

(5)Estimator:
翻译成估计器或评估器,它是学习算法或在训练数据上的训练方法的概念抽象。在 Pipeline 里通常是被用来操作 DataFrame 数据并生产一个 Transformer。从技术上讲,Estimator实现了一个方法fit(),它接受一个DataFrame并产生一个转换器。如一个随机森林算法就是一个 Estimator,它可以调用fit(),通过训练特征数据而得到一个随机森林模型。

(6)Parameter:
Parameter 被用来设置 Transformer 或者 Estimator 的参数。现在,所有转换器和估计器可共享用于指定参数的公共API。ParamMap是一组(参数,值)对。

(7)PipeLine:
翻译为工作流或者管道。工作流将多个工作流阶段(转换器和估计器)连接在一起,形成机器学习的工作流,并获得结果输出。

参考资料:https://blog.csdn.net/liulingyuan6/article/details/53489390
alpha:

类型:双精度型。

含义:隐式偏好中的alpha参数(非负)。

checkpointInterval:

类型:整数型。

含义:设置检查点间隔(>=1),或不设置检查点(-1)。

implicitPrefs:

类型:布尔型。

含义:特征列名。

itemCol:

类型:字符串型。

含义:商品编号列名。

maxIter:

类型:整数型。

含义:迭代次数(>=0)。

nonnegative:

类型:布尔型。

含义:是否需要非负约束。

numItemBlocks:

类型:整数型。

含义:商品数目(正数)。

numUserBlocks:

类型:整数型。

含义:用户数目(正数)。

predictionCol:

类型:字符串型。

含义:预测结果列名。

rank:

类型:整数型。

含义:分解矩阵的排名(正数)。

ratingCol:

类型:字符串型。

含义:评分列名。

regParam:

类型:双精度型。

含义:正则化参数(>=0)。

seed:

类型:长整型。

含义:随机种子。

userCol:

类型:字符串型。

含义:用户列名。

结束

在对Spark MLIib有一定了解之后,就可以使用java的api进行算法的设计与实现了。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值