TensorFlow 中的推荐:在 AI Platform 上训练和调整

本文是由多篇文章组成的系列教程中的第 2 篇,该系列教程介绍如何使用 TensorFlowAI Platform 实现机器学习 (ML) 推荐系统。在本部分中,您将学习如何使用 Google Cloud Platform (GCP) 中的 AI Platform 训练推荐系统和调整超参数。

该系列包含以下部分:

本教程假定您已学完本系列中的前一个教程。

目标

  • 了解如何在 AI Platform 上运行训练作业以执行 MovieLens 数据集推荐。
  • 针对 MovieLens 数据集调整 AI Platform 超参数并优化 TensorFlow WALS 推荐模型。

费用

本教程使用收费服务 Cloud StorageAI Platform。您可以使用价格计算器来估算预计使用量的费用。本教程的预计费用为 0.20 美元。如果您是 GCP 新用户,可能有资格申请免费试用

准备工作

按照第 1 部分中的说明设置 GCP 项目。

训练模型

此系列教程中的第一个教程回顾了 TensorFlow 中 WALS 算法的实现。本教程将介绍如何使用 AI Platform 训练模型。在此上下文中,“训练模型”意味着将稀疏评分矩阵 R 分解成用户因子矩阵 X 和推荐项因子矩阵 Y。生成的用户因子可用作推荐系统的基础模型。

第 4 部分中,您将在 GCP上部署推荐系统。

在 AI Platform 上训练作业

使用 AI Platform 训练模型需要指定作业目录,即 Cloud Storage 存储分区文件夹。要执行训练作业,请按照以下步骤操作:

  1. 在项目中创建新的 Cloud Storage 存储分区,或使用现有存储分区。

    如需创建新存储分区,请在 Cloud Console 中选择 Cloud Storage > 浏览器,然后点击创建存储分区

    请记住您为此存储分区指定的名称。最好将存储分区放在 Compute Engine 实例所在的区域中。

  2. 在 Shell 中,将环境变量 BUCKET 设置为您使用的 Cloud Storage 存储分区的网址。

    BUCKET=gs://[YOUR_BUCKET_NAME]
  3. 使用 gsutil 工具将 MovieLens 数据集复制到此存储分区:

    gsutil cp -r data/u.data $BUCKET/data/u.data
    gsutil cp -r data/ratings.dat $BUCKET/data/ratings.dat
    gsutil cp -r data/ratings.csv $BUCKET/data/ratings.csv
  4. 如需运行作业,请执行 wals_ml_engine 目录中的训练脚本、设置 train 选项、指定 Cloud Storage 存储分区网址以及该存储分区内数据文件的路径。

    您使用的数据集取决于您决定在第 1 部分中使用的数据集。 设置适合数据文件的其他选项,例如分隔符或标题:

    cd wals_ml_engine
    • 对于 MovieLens 100k 数据集,请指定 100k 数据文件的路径:

      ./mltrain.sh train ${BUCKET} data/u.data
    • 对于 1m 数据集,请添加 --delimiter 选项并指定 1m 数据文件的路径:

      ./mltrain.sh train ${BUCKET} data/ratings.dat --delimiter ::
    • 对于 20m 数据集,请使用 --delimiter--headers 选项:

      ./mltrain.sh train ${BUCKET} data/ratings.csv --delimiter , --headers

    您可以在 Cloud Console 的 AI Platform 部分的作业页面上监控作业的状态和输出。点击日志以查看作业输出。结果记录为测试集上的均方根误差 (RMSE)。RMSE 表示整个评分测试集中预测用户评分模型的平均误差。

保存模型

因式分解后,因子矩阵以 numpy 格式保存在五个单独的文件中,因此可用于执行推荐。 本系列教程的第 3 部分介绍了模型文件,以及如何使用它们生成推荐。第 4 部分介绍如何部署生产系统以执行推荐。在本地训练模型时,文件将保存在代码包内的 jobs 文件夹中。在 AI Platform 上训练模型时,文件将保存在上一部分所述的 AI Platform 作业的 job-dir 参数提供的 Cloud Storage 存储分区中。

MovieLens 数据集结果

矩阵因式分解的近似结果基于测试集的预测评分。测试集是在预处理期间从评分矩阵中提取的。如需计算预测评分与用户提供的实际测试集评分之间的差值,请使用第 1 部分中概述的损失公式:

$$ L = \sum_{u,i}(r_{ui} - x^{T}_{u} \cdot y_{i})^{2} $$

此处,\(r_{ui}\) 是测试集评分,\(x_{u}\) 和 \(y_{i}\) 是通过对训练集应用 WALS 因式分解计算出的行和列因子。

矩阵因式分解的性能高度依赖于几个超参数,这些参数将在本文档的下一部分中详细介绍。使用表 1 中列出的 1m MovieLens 数据集和默认的超参数集,在测试集上实现了 1.06 的 RMSE。RMSE 对应于测试集内的预测评分的平均误差。平均而言,该算法生成的每个评分均在 1m 数据集的测试集中实际用户评分的 ±1.06 范围内。用户定义的评分 3 可能会生成 2 到 4 之间的预测评分,但不太可能生成 1 或 5 预测评分。这不是一个糟糕的结果,但是该数据集的已发布结果实现了小于 1.0 的 RMSE。

要改善结果,必须调整表 1 中列出的超参数。

超参数名称和说明 默认值 扩缩
latent_factors
潜在因子数 K
5 UNIT_REVERSE_LOG_SCALE
regularization
L2 正则化常量
0.07 UNIT_REVERSE_LOG_SCALE
unobs_weight
未观察到的评分矩阵条目的权重
0.01 UNIT_REVERSE_LOG_SCALE
feature_wt_factor
观察到的条目的权重
130 UNIT_LINEAR_SCALE
feature_wt_exp
特征权重指数
1 UNIT_LOG_SCALE
num_iters
交替最小二乘迭代次数
20 UNIT_LINEAR_SCALE

表格 1.模板中使用的超参数名称和默认值

调整超参数

找到最佳的超参数集对于机器学习模型的性能至关重要。遗憾的是,理论提供的指导非常有限。 数据科学家被迫在合理范围内使用各种值进行实验,测试模型的最终性能,然后选择性能最佳的参数组合,从而进行优化。就工时和计算资源而言,这可能是一个耗时且费用高昂的过程。可能的超参数组合的空间基于模型中的不同参数的数量呈指数增长。搜索整个空间是不可行的。这会迫使您根据启发法、先前经验以及每个参数的数学特性知识,对影响模型的因素做出假设。

AI Platform 包含一个超参数调整功能,可自动搜索最佳超参数集。要使用调整功能,您需要提供要调整的超参数列表,以及这些参数的预期范围或值。AI Platform 在超参数空间上执行搜索,运行您指定次数的不同试验,并返回所有试验中找到的性能最佳的超参数的排序结果列表。您可以提供假定的参数比例(对数或线性),作为搜索过程的附加提示。

如需详细了解超参数调整,请参阅 AI Platform 文档。如需详细了解用于超参数调整的底层算法,请参阅使用贝叶斯优化在 Cloud Machine Learning Engine 中调整超参数博文。

超参数配置文件

AI Platform 的超参数列表可以在 JSON 或 YAML 配置文件中提供。在本教程的示例代码中,超参数调整配置由 config/config_tune.json 定义。此文件中列出了本教程中调整的每个超参数,以及最小范围、最大范围和比例。如需了解有效的参数比例值,请参阅超参数调整概览

standard_gpu 机器类型在 scaleTier 参数中指定,因此在已预配 GPU 的机器上进行调整。配置文件如下所示:

{
  "trainingInput":{
    "scaleTier":"CUSTOM",
    "masterType":"standard_gpu",
    "hyperparameters":{
      "goal":"MINIMIZE",
      "params":[
        {
          "parameterName":"regularization",
          "type":"DOUBLE",
          "minValue":"0.001",
          "maxValue":"10.0",
          "scaleType":"UNIT_REVERSE_LOG_SCALE"
        },
        {
          "parameterName":"latent_factors",
          "type":"INTEGER",
          "minValue":"5",
          "maxValue":"50",
          "scaleType":"UNIT_REVERSE_LOG_SCALE"
        },
        {
          "parameterName":"unobs_weight",
          "type":"DOUBLE",
          "minValue":"0.001",
          "maxValue":"5.0",
          "scaleType":"UNIT_REVERSE_LOG_SCALE"
        },
        {
          "parameterName":"feature_wt_factor",
          "type":"DOUBLE",
          "minValue":"1",
          "maxValue":"200",
          "scaleType":"UNIT_LOG_SCALE"
        }
      ],
      "maxTrials":500
    }
  }
}

超参数调整代码

模型代码包括以下功能,以允许调整超参数:

  • 每个超参数均作为参数传递给 AI Platform 上的超参数调整作业。在本示例中,task.py 文件(作为作业的入口点)处理超参数参数。您必须确保该参数的名称与超参数配置文件中列出的超参数名称匹配。
  • 该模型使用特殊标记 training/hptuning/metric 编写 TensorFlow 摘要,该标记设置为评估模型质量的指标。在本示例中,RMSE 是测试集指标。此摘要指标使 AI Platform 超参数调整服务的搜索过程能够对试验进行排序。summary 指标值在 util.py 中的效用函数中写出:

    summary = Summary(value=[Summary.Value(tag='training/hptuning/metric',
                                           simple_value=metric)])
    
    eval_path = os.path.join(args['output_dir'], 'eval')
    summary_writer = tf.summary.FileWriter(eval_path)
    
    # Note: adding the summary to the writer is enough for hyperparam tuning.
    # The ml engine system is looking for any summary added with the
    # hyperparam metric tag.
    summary_writer.add_summary(summary)
  • 请确保每个试验都有一个单独的输出目录。输出目录用于写入 TensorFlow 摘要和保存的模型。如果不针对每个试验创建不同的输出目录,则每个试验的结果将覆盖前一试验的结果。在 task.py 中通过 parse_arguments 方法中的此代码针对每个试验创建唯一的目录:

    if args.hypertune:
      # if tuning, join the trial number to the output path
      trial = json.loads(os.environ.get('TF_CONFIG', '{}')).get('task', {}).get('trial', '')
      output_dir = os.path.join(job_dir, trial)
    else:
      output_dir = os.path.join(job_dir, args.job_name)

    此处 parse_arguments 函数会区分调整和标准输出,并相应地更改 output_dir

运行超参数调整作业

以下命令会在 100k 数据集上运行调整作业:

./mltrain.sh tune $BUCKET data/u.data

确保将 BUCKET 变量设置为您之前创建的存储分区。小型 100k 数据集允许运行大量试验,在本示例中为 500。

调整结果

超参数调整的结果存储在 AI Platform 作业数据中,您可以在 Cloud Console 的 AI Platform 区域的作业页面中访问该结果。如图 1 所示,作业结果包括摘要指标的所有试验中的最佳 RMSE 分数。您可以在 100k MovieLens 数据集上查看 500 个试验超参数调整的结果。最佳结果出现在试验 384 中。

超参数调整作业结果,突出显示作业 384 的结果
图 1. 超参数调整作业结果

超参数调整可能会对最终结果产生很大影响。在本示例中,100k 测试集上的超参数调整实现了 0.98 的 RMSE。将这些参数应用于 1m20m 数据集,结果 RMSE 值分别为 0.90 和 0.88。表 2 中列出了最佳参数,表 3 中汇总了调整前后的 RMSE 值。

超参数名称 说明 调整的值
latent_factors 潜在因子 K 34
regularization L2 正则化常量 9.83
unobs_weight 未观察到的权重 0.001
feature_wt_factor 观察到的权重 189.8
feature_wt_exp 特征权重指数
num_iters 迭代次数

表 2.AI Platform 超参数调整发现的值

特征权重指数不是调整参数的一部分,因为对 MovieLens 数据集使用了线性观察权重。默认值用于 num_iters,即迭代次数参数。

数据集 使用默认超参数的 RMSE 超参数调整后的 RMSE
100k 1.06 0.98
1m 1.11 0.90
20m 1.30 0.88

表 3.在超参数调整之前和之后,不同 MovieLens 数据集的测试集中的 RMSE 值汇总

后续步骤

解决方案中的 TensorFlow 中的推荐:应用于 Google Analytics(分析)中的数据(第 3 部分)介绍了如何将推荐模型应用于 Google Analytics(分析)中的实时数据。