一、Oryx2介绍
Oryx2是基于Apache Spark和Apache Kafka的lambda架构的实现,提供了专业的大规模机器学习的算法实现,它不仅是一个方便我们来构建应用程序的框架,而且还提供了协同过滤,分类,聚类和回归机器学习算法实现的应用程序供我们直接使用。
Oryx2主要由以下三个部分构成:
1. 通用的lambda架构,提供batch、speed和serving三个层级,这三个层级与机器学习没有直接的关系;
2. 专业化的机器学习抽象层,基于Spark MLlib实现,提供机器学习算法参数的可配置化和自动求解最优模型;
3. 可直接进行交互的应用程序接口,对应不同的机器学习算法的实现。
由这三个部分构成的整个Oryx2框架如图:
Oryx2工作流程描述(使用机器学习的情况下):
1. 将固定格式的输入数据写入到kafka的input topic中;
2. BatchLayer一方面会定期的从input topic中读取最新一批的输入数据,另一方面会从hdfs上读取历史数据,整合这两个方面的数据进行处理,生成机器学习算法model写入到update topic中,最后将本次从inputtopic中读取到的新数据写入到hdfs;
3. SpeedLayer从updatetopic中读取BatchLayer训练好的机器学习算法model,根据从inputtopic中读取到的最新一批数据来对model进行增量更新(更新依赖于model本身),并将增量更新写入到update topic中;
4. ServingLayer从updatetopic中读取BatchLayer训练好的机器学习算法model和SpeedLayer处理得到的model增量更新,然后将他们整合到一起得到一个最新的model;
5. Applications基于ServingLayer整合的最新model来处理用户请求。
二、Oryx2 部署
(一)、Oryx2依赖的服务
HDFS,YARN,Zookeeper,Kafka,Spark
(二)、版本的选择
Oryx2版本与依赖服务的版本对应如下:
Oryx | Java | Scala | Spark | Kafka | CDH |
2.4.x | 8 | 2.11 | 2.1.x | 0.10.0 | 5.11 |
2.3.x | 8 | 2.11 | 2.0.x | 0.9.x | 5.10 |
2.2.x | 8 | 2.10 | 1.6.x | 0.9.x | 5.7 |
2.1.x | 7 | 2.10 | 1.5.x | 0.8.x | 5.5 |
2.0.x | 7 | 2.10 | 1.3.x | 0.8.x | 5.4 |
根据现有集群上各个服务的版本,这里选择安装Oryx2.2.2版本
(三)、安装Oryx2.2.2
根据官网的介绍,Oryx的安装可通过自行编译源码和直接下载已经编译好的文件这两种方式进行安装,这里先选用下载jar包的形式进行安装。
从官网上下载已经编译好的文件,上传至服务器,下载地址:https://github.com/OryxProject/oryx/releases
下载配置文件并重命名为oryx.conf,修改配置文件中的关键参数,关于参数的含义在下面的内容中会有详细介绍。
修改可执行文件的权限:
安装完成
三、Oryx2 配置文件
Oryx2在启动时,默认加载工作路径下名为oryx.conf的配置文件,也可以使用命令行参数指定配置文件或指定一些具体的参数,在后面的内容中会介绍Oryx2的启动命令。Oryx2的配置文件按照层级可以划分为两个方面:框架方面和算法方面。配置文件的格式层级使用.表示。
(一)、框架方面的关键配置
配置名称 | 功能 |
oryx.input-topic.broker | Input topic Kafka服务端口 |
oryx.input-topic.message.topic | Input topic的名称 |
oryx.update-topic.borker | Update topic kafka服务端口 |
oryx.update-topic.message.topic | Update topic的名称 |
oryx .batch.streaming. generation-interval-sec | Batch streaming执行的周期 |
oryx .batch.streaming. num-executors | Batch streaming executor数量 |
oryx .batch.streaming.executor-cores | Batch streaming 每个excutor核心数量 |
oryx .batch.streaming.executor-memory | Batch streaming 每个excutor使用的内存 |
oryx.batch.update-class | BatchLayer中处理逻辑的具体实现类,这个类需要实现BatchLayerUpdate接口 |
oryx .speed.streaming. generation-interval-sec | Speed streaming执行的周期 |
oryx . speed.streaming. num-executors | Speed streaming executor数量 |
oryx . speed.streaming.executor-cores | Speed streaming 每个excutor核心数量 |
oryx . speed.streaming.executor-memory | Speed streaming 每个excutor使用的内存 |
oryx.speed.model-manager-class | SpeedLayer中处理逻辑的具体实现类,这个类需要实现SpeedModelManager接口 |
oryx.serving.model-manager-class | ServingLayer中处理逻辑的具体实现类,这个类需要实现ServingModelManager接口 |
oryx.serving.application-resources | ServingLayer应用程序类所在的包路径,这些应用程序类需要实现OryxResource接口 |
oryx.serving.rescore-provider-class | 重新打分器,在ALS算法实现的应用程序中有用,可以根据个性化需求对结果进行重新打分,这个类需要实现RescorerProvider接口 |
oryx.ml.eval.candidates | 模型候选人数量,在所有候选人中选择最优模型作为最终的模型 |
(二)、算法方面的关键配置
这里的算法方面的配置,指的是在Oryx2中基于Spark MLlib三个算法实现的应用程序中的算法关键配置,在后面的内容中会介绍到相关的算法,这里的参数需要结合对应的算法原理使用。
配置名称 | 默认值 | 功能 |
orxy.als.iterations | 10 | 模型训练的迭代次数 |
orxy.als.implicit | true | 输入数据是否考虑了隐式反馈数据 |
orxy.als.logStrength | false | 在合并所有评分数据时,是否对最终结果进行Log strength转换 |
orxy.als.hyperparams.features | 10 | 矩阵分解中隐式特征数量 |
orxy.als. hyperparams.lambda | 0.001 | 正则化系数,正则化项用于避免模型合 |
orxy.als.hyperparams.alpha | 1.0 | 置信度系数,考虑了隐式反馈数据时,置信度系数才有用 |
orxy.als.hyperparams.epsilon | 0.00001 | orxy.als.logStrength开启时有用 |
orxy.als.no-known-items | false | 是否跟踪已知item,为false表示跟踪 |
orxy.als.decay.factor | 1.0 | 时间衰减因子 |
orxy.als.smaple-rate | 0.1 | 抽样比例, 在分离训练样本和测试样本时使用 |
oryx.rdf.num-trees | 20 | 森林中决策树的数量 |
oryx.rdf. hyperparams.max-split-candidates | 100 | 跟训练单棵树时样本的抽样比例有关 |
oryx.rdf. hyperparams.max-depth | 8 | 没棵树的深度 |
oryx.rdf. hyperparams.impurity | entropy | 纯度度量算法,确定一个内节点是否能成为叶子 |
orxy.input-schema.num-features | 0 | 输入数据中特征的个数,当feature-names没有指定时使用 |
orxy.input-schema.numeric-features |
| 数字类型的特征 |
orxy.input-schema.feature-names |
| 所有特征的名字 |
orxy.input-schema.categorical-features |
| 分类特征名字 |
orxy.input-schema.target-feature |
| 目标特征名字 |
oryx.kmeans.iterations | 30 | 在训练模型过程中的最大迭代次数 |
oryx.kmeans.initialization-strategy | k-means|| | k-means的初始化策略 |
oryx.kmeans.evaluation-strategy | SILHOUETTE | 算法模型的评估策略 |
oryx.kmeans.runs | 3 | 模型选择的运行并行度 |
oryx.kmeans.hyperparams.k | 10 | 聚类的数量 |
四、Oryx2启动命令
Oryx2只有一个命令脚本:oryx-run.sh,所有启动的操作都通过这个命令完成,启动后的一些操作也由这个命令完成。
命令格式: oryx-run.sh commend [--option value]
这个命令脚本的参数分为两个类型:指令和选项
名称 | 类型 | 功能 |
batch | 指令 | 启动BatchLayer |
speed | 指令 | 启动SpeedLayer |
serving | 指令 | 启动ServingLayer |
kafka-setup | 指令 | 配置使用到的kafka topic |
kafka-tail | 指令 | 跟踪kafka topic内容 |
kafka-input | 指令 | 写入数据到input topic中 |
--layer-jar | 选项 | 指定oryx jar包 |
--conf | 选项 | 指定配置文件 |
--jvm-args | 选项 | 虚拟机参数选项 |
--deployment | 选项 | 部署方式,这个选项只对ServingLayer有用,可以是yarn或者local;batch和speed的部署方式可以在配置文件中指定 |
--app-jar | 选项 | 应用程序jar包 |
--input-file | 选项 | 输入数据文件,在kafka-input指令时使用 |
自动命令应用示例:
oryx-run.sh batch 启动BatchLayer
oryx-run.sh kafka-setup 初始化用到的input topic和update topic
oryx-run.sh kafka-input –input-file<file-path> 将file-path文件的内容写入到input topic中去。
五、Oryx2中实现的应用程序的使用
Oryx2中基于ALS(交替最小二乘法)、RDF(随机决策森林)和K-means(K均值)三个基础算法实现了涵盖了推荐、分类、聚类和回归等方面的多个应用程序,下面在每个算法中选取一个比较具有代表性应用程序,对其原理和使用说明进行介绍。
(一)、基于ALS的推荐系统
实现原理
Oryx2的推荐系统是一种基于矩阵分解的协同过滤推荐系统,矩阵分解的过程依赖于ALS。
基于矩阵分解的推荐系统的思路大致是将用户(user)对商品(item)的偏好矩阵分解为两个矩阵:一个是用户对商品隐含特征的偏好矩阵,另一个是商品所包含的隐含特征的矩阵。在这个分解的过程中,原矩阵中的偏好缺失项得到了填充,也就是说我们可以基于这个填充的评分来给用户推荐商品。
由于偏好矩阵中含有大量的缺失项,ALS能够很好的解决这个问题。对于R(m * n)的矩阵,ALS旨在找到两个低维矩阵X(m * k)和矩阵Y(n * k),来近似逼近R(m * n),即:
为了找到使低秩矩阵X和Y尽可能地逼近R,需要最小化平方误差损失函数,损失函数中加入正则化项(右边部分)来避免过拟合问题,由此得到目标函数:
其中λ是正则化系数,对应于配置文件中orxy.als. hyperparams.lambda配置。
最小化目标函数,就可以找到最逼近的低秩矩阵X和Y,这里就可以使用ALS算法来求解。
在输入数据中考虑到了隐式反馈(用户主动进行评分等动作以外的数据)的情况下,需要将置信度权重考虑进来,对于更确信用户偏好的项赋以较大的权重,对于没有反馈的项,赋以较小的权重,也就是ALS-WR模型,此模型的目标函数如下:
其中α是置信度系数,对应于配置文件中orxy.als. hyperparams.alpha配置。
配置参数补充说明
在配置文件中orxy.als. hyperparams下的各个参数,根据参数的类型不同,每个参数可以配置多个可选值,用一个列表的形式表示,如:
orxy.als. hyperparams.features = [10,11,12]
orxy.als. hyperparams.lambda = [0.001,0.002]
在训练算法模型的过程中,会对这些参数进行组合,训练出不同的模型作为候选者,最终从所有候选者中选择最优的模型作为最终模型,候选者的数量不仅跟可供选择的参数数量有关,还跟参数oryx.ml.eval.candidates有关。
算法模型评估
使用测试集数据,根据输入数据中是否考虑了隐式反馈数据,分别对应两种评估方式:
1. 考虑了隐式反馈数据:AUC(ROC曲线下面积)
2. 没考虑隐式反馈数据:RMSE(均方根误差)
推荐系统使用
1.配置文件
下载官方提供的als示例配置文件:https://github.com/OryxProject/oryx/blob/master/app/conf/als-example.conf
修改配置:
kafka-brokers= 集群kafka broker服务端口
zk-servers= 集群zookeeper Server服务端口
hdfs-base= hdfs上存放数据的基础路径
其他配置均使用默认配置即可,如果集群资源有限,可以适当调整关于spark streaming方面的配置。
2.启动
将配置文件上传到工作路径下,重命名为oryx.conf,或者在命令行中指定,这里使用重命名的方式。
配置kafka topic:./oryx-run.sh kafka-setup
启动BatchLayer:./oryx-run.sh batch
启动SpeedLayer:./oryx-run.sh speed
启动ServingLayer:./oryx-run.sh serving
启动后,可以在yarn上查看对应的应用
3.输入数据到input topic中
实验数据格式:UserID,ItemID,Preference,Time
./oryx-run.sh kafka-input –input-file<file_path>
4.查询某个UserID的推荐结果
(二、)基于RDF的分类器
实现原理
随机森林就是通过集成学习的思想将多棵树集成的一种算法,它的基本单元是决策树,而它的本质属于机器学习的一大分支—集成学习方法。从直观角度来解释,每棵决策树都是一个分类器,那么对于一个输入样本,N棵树会有N个分类结果,而随机森林集成了所有的分类投票结果,将投票次数最多的类别指定为最终的输出。
随机森林的特点:
1. 在当前的算法中,准确率较好
2. 能够处理具有高维特征的输入样本,而且不需要降维
3. 能够评估各个特征在分类问题上的重要性
决策树的概念:
分类决策树模型是一种描述对实例进行分类的树形结构。决策树由节点和有向边组成。节点有两种类型:内部节点和叶节点(通过算法判定),内部节点表示一个特征或树形,叶节点表示一个类。分类的时候,从根节点开始,对实例中的某一个特征(这里会有一个最优特征的选择)进行测试,根据测试结果,将实例分配到其子节点;此时,每一个子节点对应着该特征的一个取值,如此递归向下移动,直至达到叶节点,最后将实例分配到叶节点的类中。
在随机森林中,对森林中每棵决策数的生成策略与单独的决策树有一些区别,在随机森林中,用来训练每棵单独的决策树的数据样本是有放回的随机抽样,每棵树所用到的样本的特征也是随机选择的,而不是所有的树都使用所有的样本特征,这样的做法赋予了随机深林良好的泛化能力和抗噪性能。
配置文件参数说明
同样的,在配置文件中oryx.rdf. hyperparams下的参数可以用列表的形式指定多个值或者范围值,在训练模型的过程中会使用不同的参数组合训练出不同的模型,最终选择最优的模型。
使用RDF实现应用时,修改配置文件中的orxy.input-schema下的多个配置来指定输入样本的数据格式,比如说哪些字段作为分类特征,哪个字段作为目标特征,如:
orxy.input-schema.feature-names = ["SepalLength","SepalWidth", "PetalLength", "PetalWidth","Species"]
categorical-features = ["Species"]
target-feature = "Species"
分类器的使用
1. 配置文件
下载官方提供的分类器配置文件:https://github.com/OryxProject/oryx/blob/master/app/conf/rdf-classification-example.conf
修改配置:
kafka-brokers = 集群kafka broker服务端口
zk-servers= 集群zookeeper Server服务端口
hdfs-base= hdfs上存放数据的基础路径
orxy.input-schema.feature-names = 样本格式
orxy.input-schema.categorical-features= 分类特征
orxy.input-schema.target-feature= 目标特征
…
关于格式输入数据格式方面的配置,需要根据实际的输入数据情况来指定。
2. 启动
将配置文件上传到工作路径下,重命名为oryx.conf,或者在命令行中指定,这里使用重命名的方式。
配置kafka topic:./oryx-run.sh kafka-setup
启动BatchLayer:./oryx-run.sh batch
启动SpeedLayer:./oryx-run.sh speed
启动ServingLayer:./oryx-run.sh serving
启动后,可以在yarn上查看对应的应用
3. 输入数据input topic中
实验数据格式:SepalLength,SepalWidth, PetalLength, PetalWidth, Species
./oryx-run.sh kafka-input –input-file<file_path>
4. 使用分类器预测分类结果
(三)、基于K-means的聚类器
实现原理
这个聚类器聚类器的实现在算法上是选择是K-means,K-means是非监督学习中的一种聚类算法,聚类是数据挖掘中一种非常重要的学习流派,指将未标注的样本数据中相似的分为同一类。K-means是聚类算法中最为简单、高效的一种算法,其核心思想是:由用户指定K个初始质心(initialcentroids),以最为聚类的类别(cluster),重复迭代直至算法收敛。
基本的K-means算法流程:
选取K个初始质心(作为初始cluster);
Repeat:
对每个样本点,计算得到距离其最近的质心,将其类别标为该质心所对应的cluster;
重新计算K个cluster对应的质心;
Until:
质心不再发生变化或者已经达到最大迭代次数;
在这个聚类器中,样本到质心的距离是使用欧式距离来衡量的,以平方误差和作为聚类的目标函数:
配置文件参数说明
同样的,在配置文件中oryx.kmeans.hyperparams下的参数可以用列表的形式指定多个值或者范围值,在训练模型的过程中会使用不同的参数组合训练出不同的模型,最终选择最优的模型。
在K-means实现应用时,也需要使用配置文件中input-schema下的多个配置来指定输入数据的信息,如特征的数量等。
可以使用配置:orxy.kmeans.initialization-strategy来指定K-means算法初始化的方式,这里配置的不同的方式会决定上文中在实现原理中提到的K-means算法基本流程中的选取K个质心的过程。
可以使用配置:orxy.kmeans.evaluation-strategy来指定K-means模型的评估策略, 这个策略用来评估模型的准确度,在训练模型的中,选取不同参数组合模型中的最优模型。
算法模型评估
默认使用SILHOUETTE(轮廓系数)来对模型进行评估。
聚类器的使用
1. 配置文件
下载官方提供的聚类器配置文件:
https://github.com/OryxProject/oryx/blob/master/app/conf/kmeans-example.conf
修改配置:
kafka-brokers = 集群kafka broker服务端口
zk-servers= 集群zookeeper Server服务端口
hdfs-base= hdfs上存放数据的基础路径
oryx.input-schema.num-features= 特征数量
oryx.input-schema.ignored-features= 输入数据中需要忽略的特征
…
关于格式输入数据格式方面的配置,需要根据实际的输入数据情况来指定。
2. 启动
将配置文件上传到工作路径下,重命名为oryx.conf,或者在命令行中指定,这里使用重命名的方式。
配置kafka topic:./oryx-run.sh kafka-setup
启动BatchLayer:./oryx-run.sh batch
启动SpeedLayer:./oryx-run.sh speed
启动ServingLayer:./oryx-run.sh serving
启动后,可以在yarn上查看对应的应用
3. 输入数据到input topic中
KDD Cup 99 data set比赛的数据
在这个数据中,每个样本有42个特征,其中第1,2,3,41(索引从0开始)个特征为字符串类型,需要忽略掉 ,所以在配置文件中关于输入格式的配置需要配置为:
oryx.input-schema.num-features = 42
oryx.input-schema.ignored-features =[ "1", "2", "3", "41" ]
./oryx-run.shkafka-input –input-file <file_path>
4. 使用聚类器
六、 Oryx2提供给开发者的API
Oryx2除了提供多种已经实现好应用程序外,还为开发者基于Oryx2实现自己应用程序的API,API分为两个方面,分别对应于用户应用程序定制化和基于Oryx2已实现的应用程序的定制化。
(一)、应用程序定制化API
Oryx2提供的应用程序定制化API,用户可以定制BatchLayer,SpeedLayer,ServingLayer以及应用程序交互窗口的实现细节,其应用方式就类似于源码中给出的例子:Wordcount。
Maven dependency:
<dependencies>
<dependency>
<groupId>com.cloudera.oryx</groupId>
<artifactId>oryx-api</artifactId>
<scope>provided</scope>
<version>2.x.x</version>
</dependency>
</dependencies>
修改配置文件,指定每一个Layer中实现细节的类
Layer | 配置 |
BatchLayer | oryx.batch.update-class |
SpeedLayer | oryx.speed.model-manager-class |
ServingLayer | oryx.serving.model-manager-class |
WebUI | oryx.serving.application-resources |
(二)、基于已实现的应用程序的定制化API
这里所说的已实现的应用程序的定制化API指的是开发者可以通过实现指定的接口来改变应用程序的结果。在Oryx2已实现的多个应用程序中,只有部分基于ALS是实现的应用程序提供了这样的接口,如Recommend。
Maven dependency:
<dependencies>
<dependency>
<groupId>com.cloudera.oryx</groupId>
<artifactId>oryx-app-api</artifactId>
<scope>provided</scope>
<version>2.x.x</version>
</dependency>
</dependencies>
自定义这个接口需要实现:com.cloudera.oryx.app.als.RescorerProvider
在配置文件中通过oryx.serving.rescore-provider-class来指定。