1 Star 2 Fork 4

meta-soul / MetaSpore

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README-CN.md 8.04 KB
一键复制 编辑 原始数据 按行查看 历史

MovieLens Demo-离线模型训练

一般来说,一个典型的推荐系统正如下图所描述的那样,主要由数据预处理、召回模型开发和优化、排序模型开发和优化等等。举例来说,在召回阶段,一般会使用协同过滤,基于图的方法,甚至是基于神经网络的方法来做用户和商品的匹配;而在排序和重排阶段,一些业务指标,比如CTR、CVR、Novelty等,会被机器学习模型来直接建模。对于一个算法工程师来说,日常优化工作的重点基本都集中在离线数据和模型上面。在这里,我们会使用 MetaSpore 来介绍基本的数据预处理、召回、排序等模块,来展示利用我们的系统如何快速构建一个工业级推荐系统。

image

在这个Demo的项目里,我们使用 MoiveLens-1M 这个数据集来演示。此外,为了给每个电影一个真实的IMDB超链接,我们使用了另外一个 github项目 中处理好的数据 ml-25m-imdb 。您可以从上面提供的网址中下载项目所需要的数据,并存储在您的云端 S3 存储上。

1. 初始化模型配置文件

在我们深入到具体的数据和模型开发工作之前,我们需要通过给出的 YAML 配置模版对不同阶段的配置文件进行初始化,主要是替换模版中一些需要定制的变量。举例来说,我们需要替换自己具体的 S3 路径 MY_S3_BUCKET:

export MY_S3_BUCKET='your S3 bucket directory'
envsubst < template.yaml > output.yaml 

在后面我们运行 python 脚本之前,我们假设大家已经完成了初始化模型配置文件的工作。

2. 数据预处理和特征生成

在这个阶段,我们主要做 4 件事情,分别是:训练集和测试集的划分,组织训练样本,生成模型训练需要的离散特征和连续特征,初始化用户特征、电影特征以便于存储与 MongoDB 中。

python fg_movielens.py --conf fg.yaml 

当我们执行完以上脚本之后,我们需要使用 Spark 用户和电影特征灌到 MongoDB 中:

spark-submit \
    --master local \
    --name write_mongo \
    --packages org.mongodb.spark:mongo-spark-connector_2.12:3.0.1 \
    dump/write_mongo.py --origin items --dest item --queryid movie_id

spark-submit \
    --master local \
    --name write_mongo \
    --packages org.mongodb.spark:mongo-spark-connector_2.12:3.0.1 \
    dump/write_mongo.py --origin users --dest user --queryid user_id
    
spark-submit \
    --master local \
    --name write_mongo \
    --packages org.mongodb.spark:mongo-spark-connector_2.12:3.0.1 \
    dump/write_mongo.py --origin item_feature --dest item_feature --queryid movie_id

当然,我们可以根据自己场景的需要,来更改这些输入、输出路径。

3. 召回算法

在这个阶段,我们主要介绍 3 中召回算法,包括 Item CF, Swing, Two-Twoer,这些算法的执行过程会在接下来进行详细的说明。

3.1 Item CF

首先,我们运行 Item CF 的训练脚本:

python item_cf.py --conf item_cf.yaml 

这条命令执行结束之后,我们算法中计算的相似度 I2I 矩阵会被保存到 item_cf_out_path 这个路径下,其中 item_cf_out_pathitem_cf.yaml 中到配置项。现在我们可以像之前的步骤那样,将我们计算的结果灌到 MongoDB 中。

spark-submit \
    --master local \
    --name write_mongo \
    --packages org.mongodb.spark:mongo-spark-connector_2.12:3.0.1 \
    dump/write_mongo.py --origin itemcf --dest itemcf --queryid key 

3.2 Swing

首先,我们可以运行Swing的训练脚本:

python swing.py --conf swing.yaml 

在这条命令执行结束之后,我们算法中计算的相似度 I2I 矩阵会被保存到 item_cf_out_path 这个路径下,其中 item_cf_out_pathitem_cf.yaml 中到配置项。现在我们可以像之前的步骤那样,将我们计算的结果灌到 MongoDB 中。

spark-submit \
    --master local \
    --name write_mongo \
    --packages org.mongodb.spark:mongo-spark-connector_2.12:3.0.1 \
    dump/write_mongo.py --origin swing --dest swing --queryid key

3.3 Two-Tower

SimpleX 算法是一种简单并鲁棒的双塔模型的实现,我们可以运行 SimpleX 训练脚本:

python simplex.py --conf simplex.yaml 

在执行完这条命令之后,我们电影的 embedding 向量会被自动输出到 Milvus 到数据库中,其中有关 Milvus 服务的配置,比如域名、端口等详细的配置在 simplex.yaml 文件中。

4. 排序算法

在排序阶段,我们把个性化排序问题建模成 CTR 预估 问题,这种建模方法已经在业界被广泛采用。这里我们展示两种模型,如何在 MetaSpore 中使用:第一种是经典的树模型,我们以LightGBM 为例,第二种是是神经网络模型,我们以 Wide & Deep 为例。

4.1 树模型

如前文所述,我们这里使用 LightGBM 模型来解决排序问题,我们可以使用一下训练脚本:

python lgbm_model_train.py --conf lgbm.yaml

这里需要注意的是,当我们树模型训练完成之后,我们使用一下代码转化成 ONNX 格式,以便于 MetaSpore Serving 加载并进行线上预测。

def convert_model(lgbm_model: LGBMClassifier or Booster, input_size: int) -> bytes:
    initial_types = [("input", FloatTensorType([-1, input_size]))]
    onnx_model = convert_lightgbm(lgbm_model, initial_types=initial_types, target_opset = 9)
    return onnx_model

4.2 神经网络模型

如前文所述,我们这里使用 Wide & Deep 模型 来演示在 MetaSpore 平台进行分布式训练的能力,我们可以运行一下训练脚本:

python widedeep.py --conf widedeep.yaml

在上面脚本执行结束之后,ONNX 格式的模型文件已经被自动导出到 S3 的路径: model_export_path,而这个路径变量在 widedeep.yaml 文件中配置。

5. Tuner

最后,对于 MetaSpore 中开发的模型,如 Item CFSwingWide & Deep 等,我们实现了一个轻量级的超参数搜索工具,我们这里以 Wide & Deep tuner 配置来说明如何使用:

app_name: Wide&Deep CTR Model Tuner
num_experiment: 3
model_name: widedeep
result_path: ${MY_S3_DIR}/tuner/model/movielens/widedeep/

dataset:
    train: ${MY_S3_DIR}/movielens/rank/train.parquet
    test: ${MY_S3_DIR}/movielens/rank/test.parquet

common_param:
    local: False
    column_name_path: ${MY_S3_DIR}/movielens/schema/widedeep/column_schema
    combine_schema_path: ${MY_S3_DIR}/movielens/schema/widedeep/combine_column_schema
    ...

hyper_param:
    use_wide: [True, False]
    embedding_size: [10, 20]
    deep_hidden_units: [[1024, 512, 256, 128, 1], [1024, 512, 1]]
    adam_learning_rate: [0.00001, 0.0001, 0.001]
    ...
  1. 我们在配置文件中需要对一些基本的配置项进行定义,包括 app_name, num_expriment等;
  2. 我们在配置文件中需要对 dataset 的路径进行定义;
  3. 我们在配置文件中需要对 common_param 来配置哪些模型参数是不希望在本次实验中进行搜索;
  4. 我们在配置文件中需要对 hyper_param 来配置哪写模型参数是希望在在本次实验中进行搜索的。

在以上 YAML 文件被完善的配置之后,我们可以运行:

python widedeep_tuner.py --conf widedeep_tuner.yaml

当这条命令运行完成之后,超参数寻优的结果被保存在 YAML 文件中定义的 result_path 路径中。

C++
1
https://gitee.com/meta-soul/MetaSpore.git
git@gitee.com:meta-soul/MetaSpore.git
meta-soul
MetaSpore
MetaSpore
main

搜索帮助