使用超参数调节

本页面介绍了如何在训练模型时使用 AI Platform Training 超参数调节。这种功能可优化您指定的目标变量,而这些目标变量称为超参数指标。使用超参数调节启动作业时,可以为超参数指标指定名称。这是您为添加到训练程序的标量摘要指定的名称。

超参数调节涉及的步骤

如需在训练作业中使用超参数调节,您必须执行以下步骤:

  1. 通过在 TrainingInput 对象中添加 HyperparameterSpec,为训练作业指定超参数调节配置。

  2. 在您的训练应用中添加以下代码:

    • 解析表示要调节的超参数的命令行参数,并使用这些值为训练试验设置超参数。
    • 将超参数指标添加到图的摘要中。

以下列出了每个步骤的更多详情。

为训练作业指定超参数调节配置

创建 HyperparameterSpec 对象以保存训练作业的超参数调节配置,并将 HyperparameterSpec 作为 hyperparameters 对象添加到 TrainingInput 对象中。

HyperparameterSpec 中,将 hyperparameterMetricTag 设置为表示所选指标的值。如果您未指定 hyperparameterMetricTag,AI Platform Training 会查找名为 training/hptuning/metric 的指标。以下示例展示了如何为名为 metric1 的指标创建配置:

gcloud

将超参数配置信息添加到配置 YAML 文件中。具体流程请参阅以下示例。如需了解有效的配置文件,请参阅人口普查 Estimator 示例中的 hptuning_config.yaml

trainingInput:
  scaleTier: CUSTOM
  masterType: complex_model_m
  workerType: complex_model_m
  parameterServerType: large_model
  workerCount: 9
  parameterServerCount: 3
  hyperparameters:
    goal: MAXIMIZE
    hyperparameterMetricTag: metric1
    maxTrials: 30
    maxParallelTrials: 1
    enableTrialEarlyStopping: True
    params:
    - parameterName: hidden1
      type: INTEGER
      minValue: 40
      maxValue: 400
      scaleType: UNIT_LINEAR_SCALE
    - parameterName: numRnnCells
      type: DISCRETE
      discreteValues:
      - 1
      - 2
      - 3
      - 4
    - parameterName: rnnCellType
      type: CATEGORICAL
      categoricalValues:
      - BasicLSTMCell
      - BasicRNNCell
      - GRUCell
      - LSTMCell
      - LayerNormBasicLSTMCell

Python

创建一个代表 HyperparameterSpec 的字典,并将其添加到您的训练输入中。以下示例假定您已经按照训练作业配置指南所示创建了 TrainingInput 字典(在本例中名为 training_inputs)。

# Add hyperparameter tuning to the job config.
hyperparams = {
    'goal': 'MAXIMIZE',
    'hyperparameterMetricTag': 'metric1',
    'maxTrials': 30,
    'maxParallelTrials': 1,
    'enableTrialEarlyStopping': True,
    'params': []}

hyperparams['params'].append({
    'parameterName':'hidden1',
    'type':'INTEGER',
    'minValue': 40,
    'maxValue': 400,
    'scaleType': 'UNIT_LINEAR_SCALE'})

hyperparams['params'].append({
    'parameterName':'numRnnCells',
    'type':'DISCRETE',
    'discreteValues': [1, 2, 3, 4]})

hyperparams['params'].append({
    'parameterName':'rnnCellType',
    'type': 'CATEGORICAL',
    'categoricalValues': [
        'BasicLSTMCell',
        'BasicRNNCell',
        'GRUCell',
        'LSTMCell',
        'LayerNormBasicLSTMCell'
    ]
})

# Add hyperparameter specification to the training inputs dictionary.
training_inputs['hyperparameters'] = hyperparams

# Build the job spec.
job_spec = {'jobId': my_job_name, 'trainingInput': training_inputs}

检查训练应用中的代码

在您的应用中,处理超参数的命令行参数,并向 AI Platform Training 报告超参数指标。

处理要调节的超参数的命令行参数

由于 AI Platform Training 在调用您的训练应用时设置命令行参数,因此请在代码中使用命令行参数:

  1. 为每个超参数定义一个名称,并使用您偏好的任何参数解析器(通常为 argparse)对其进行解析。参数名称必须与您在作业配置中指定的参数名称匹配,如上文所述。

  2. 将命令行参数中的值分配给训练代码中的超参数。

向 AI Platform Training 报告您的超参数指标

向 AI Platform Training 服务报告超参数指标的方式取决于您是否使用 TensorFlow 进行训练。这还取决于您是使用运行时版本还是自定义容器进行培训。

我们建议您的训练代码经常向 AI Platform Training 报告超参数指标,以便利用早停法

具有运行时版本的 TensorFlow

如果您使用的是 AI Platform Training 运行时版本并通过 TensorFlow 进行训练,您可以通过将指标写入 TensorFlow 摘要向 AI Platform Training 报告超参数指标。请使用以下某个函数:

如以下 Estimator 示例所示,使用调用上述函数之一的不同 TensorFlow API 也可向 AI Platform Training 报告超参数指标。

以下示例介绍了将超参数指标写入摘要的两种不同方法的基础知识。这两个示例均假定您正在训练回归模型,并将标准答案标签和评估预测之间的均方根误差写为名为 metric1 的超参数指标。

Keras

以下示例使用自定义 Keras 回调在每个训练周期末写入标量摘要:

class MyMetricCallback(tf.keras.callbacks.Callback):

    def on_epoch_end(self, epoch, logs=None):
        tf.summary.scalar('metric1', logs['RootMeanSquaredError'], epoch)

logdir = "logs/scalars/" + datetime.now().strftime("%Y%m%d-%H%M%S")
file_writer = tf.summary.create_file_writer(logdir + "/metrics")
file_writer.set_as_default()

model = tf.keras.Sequential(
    tf.keras.layers.Dense(1, activation='linear', input_dim=784))
model.compile(
    optimizer='rmsprop',
    loss='mean_squared_error',
    metrics=['RootMeanSquaredError'])

model.fit(
    x_train,
    y_train,
    batch_size=64,
    epochs=10,
    steps_per_epoch=5,
    verbose=0,
    callbacks=[MyMetricCallback()])

Estimator

以下示例使用 tf.estimator.add_metrics 将超参数指标添加到图表摘要中。

请注意,Estimator 每次运行 evaluate 方法时都会写入图表摘要。此示例使用 tf.estimator.EvalSpectf.estimator.train_and_evaluate 配置 Estimator,使其能在训练期间每 300 秒评估和写入一次摘要。

# Create metric for hyperparameter tuning
def my_metric(labels, predictions):
    # Note that different types of estimator provide different different
    # keys on the predictions Tensor. predictions['predictions'] is for
    # regression output.
    pred_values = predictions['predictions']
    return {'metric1': tf.compat.v1.metrics.root_mean_squared_error(labels, pred_values)}

# Create estimator to train and evaluate
def train_and_evaluate(output_dir):

    estimator = tf.estimator.DNNLinearCombinedRegressor(...)

    estimator = tf.estimator.add_metrics(estimator, my_metric)

    train_spec = ...
    eval_spec = tf.estimator.EvalSpec(
        start_delay_secs = 60, # start evaluating after 60 seconds
        throttle_secs = 300,  # evaluate every 300 seconds
        ...)
    tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)

其他机器学习框架或自定义容器

如果您要使用自定义容器进行训练,或者想使用非 TensorFlow 框架执行超参数调节,则必须使用 cloudml-hypertune Python 软件包来向 AI Platform Training 报告您的超参数指标。

请参阅使用 cloudml-hypertune 的示例

在运行时获取超参数调节作业的详细信息

您可以通过获取正在运行的训练作业的详细状态来监控超参数调节。

在具有超参数调节的训练作业期间,响应的作业资源中的 TrainingOutput 对象会设置以下值:

  • isHyperparameterTuningJob 设置为 True

  • 具有 trials,其中包含一个 HyperparameterOutput 对象列表,每个试验各一个。

此外,您还可以从 TF_CONFIG 环境变量中检索试验 ID。请参阅TF_CONFIG 获取详细信息的指南。

获取超参数调节结果

训练运行完成后,您可以在 Cloud Console 中查看每个试验的结果。或者,您也可以调用 projects.jobs.get 来获取结果。作业资源中的 TrainingOutput 对象包含所有运行的指标,并标出具有最佳调节结果的运行指标。

使用与处理期间用于监控作业相同的详细状态请求来获取此信息。

您可以在作业说明中查看每个试验的结果。在 Cloud Console 中,您可以按 rmselearning_ratetraining steps 过滤试验。然后从中找到为您的超参数指标产生最理想值的试验。如果该试验符合您的模型的成功标准,您可以在模型的后续运行中使用该试验给出的超参数值。

在某些情况下,会有多次试验提供完全相同的调节指标结果。在这种情况下,您应该使用其他方法确定哪些超参数值最有利。例如,如果要调节隐藏层中的节点数量,而当值设置为 8 和 20 时会得到相同的结果,则应使用 8,因为节点数量越多,处理耗费的资源越多且成本也越高,而模型却不会实现更大的改进。

HyperparameterOutput 中的 FAILED 试验状态可能表示训练在该试验中失败,或者试验未能报告超参数调节指标。在后一种情况下,即使试验失败,父作业也可以成功。您可以查看试验记录,了解训练在该试验中是否失败。

设置试验次数限制

您应该决定要允许服务运行的试验次数,并在 HyperparameterSpec 对象中设置 maxTrials 值。

在决定允许的试验次数时,需要作出以下权衡:

  • 时间(以及相应的成本)
  • 准确性

增加试验次数通常会产生更好的结果,但也有例外情况。在大多数情况下,会存在一个回报递减点,在此之后进行的试验几乎不会再提高准确性。因此,在开始大量试验工作之前,最好先执行其中的一小部分,以评估所选超参数对模型准确性的影响。

要充分利用超参数调节,切勿将最大值设置为低于您使用的超参数数量的十倍。

处理失败的试验

如果您的超参数调节试验由于出现错误而退出,您可能希望尽早结束训练作业。请将 HyperparameterSpec 中的 maxFailedTrials 字段设置为您要允许的失败试验次数。试验失败的次数达到此值后,AI Platform Training 便会结束训练作业。 maxFailedTrials 值必须小于或等于 maxTrials

如果您未设置 maxFailedTrials,或将其设置为 0,则 AI Platform Training 会使用以下规则处理失败的试验:

  • 如果作业的第一次试验失败,AI Platform Training 会立即结束作业。第一次试验失败表明训练代码存在问题,因此后续试验也可能会失败。结束作业让您可以诊断问题,而无需等待更多的试验,并且不会产生更高的费用。
  • 如果首次试验成功,AI Platform Training 可能会在后续试验失败时根据以下条件之一终止作业:
    • 失败的试验次数过多。
    • 失败的试验次数与成功的试验次数之比过高。

这些内部阈值可能会发生变化。为确保特定的行为,请设置 maxFailedTrials 字段。

运行并行试验

通过在 HyperparameterSpec 对象中设置 maxParallelTrials,您可以指定要并行运行的多个试验。

运行并行试验有利于减少训练作业所需的时间(实时 - 需要的总处理时间通常不会改变)。但是,并行运行试验会降低调节作业的整体效率。这是因为超参数调节使用先前试验的结果来获取应分配给后续试验的超参数的值。如果并行运行试验,则一些试验会在未知晓仍在运行试验的结果的情况下开始运行。

如果您使用并行试验,训练服务会提供多个培训处理集群(如果是单一流程培训程序,则提供多个单独的机器)。这些训练集群均会使用您为作业设置的调节方案。

提前停止试验

您可以指定 AI Platform Training 必须自动停止明显不会有较好结果的试验。这样可以为您节省继续进行不可能有用的试验的费用。

如需允许提前停止试验,请将 HyperparameterSpec 中的 enableTrialEarlyStopping 值设置为 TRUE

恢复已完成的超参数调节作业

您可以继续操作已完成的超参数调节作业,让其从部分优化的状态开始运行。这样一来,您就可以再次利用在先前的超参数调节作业中获得的知识。

如需恢复超参数调节作业,请使用以下配置提交新的超参数调节作业:

  • HyperparameterSpec 中的 resumePreviousJobId 值设置为上一次试验的作业 ID。
  • 指定 maxTrialsmaxParallelTrials 的值。

AI Platform Training 使用上一个作业 ID 查找并重复使用相同的 goalparamshyperparameterMetricTag 值,以继续运行超参数调节作业。

即使作业具有不同的参数,也请对类似的作业使用一致的 hyperparameterMetricTag 名称和 params。遵循这种做法,可以使 AI Platform Training 随着时间的推移而不断优化。

以下示例展示了 resumePreviousJobId 配置的使用:

gcloud

trainingInput:
  scaleTier: CUSTOM
  masterType: complex_model_m
  workerType: complex_model_m
  parameterServerType: large_model
  workerCount: 9
  parameterServerCount: 3
  hyperparameters:
    enableTrialEarlyStopping: TRUE
    maxTrials: 30
    maxParallelTrials: 1
    resumePreviousJobId: [PREVIOUS_JOB_IDENTIFIER]

Python

# Add hyperparameter tuning to the job config.
hyperparams = {
    'enableTrialEarlyStopping': True,
    'maxTrials': 30,
    'maxParallelTrials': 1,
    'resumePreviousJobId': [PREVIOUS_JOB_IDENTIFIER]}

# Add the hyperparameter specification to the training inputs dictionary.
training_inputs['hyperparameters'] = hyperparams

# Build the job spec.
job_spec = {'jobId': my_job_name, 'trainingInput': training_inputs}

使用 Cloud TPU 进行超参数调节

如果您在 AI Platform Training 上使用 Cloud TPU 运行超参数调节作业,最佳做法是使用 TPUEstimatorSpec 中的 eval_metrics 属性。

如需查看使用 Cloud TPU 进行超参数调节的有效示例,请参阅 ResNet-50 TPU 超参数调节示例

您也可以选择在 host_call 中调用 tf.summary(而不使用 eval_metrics 属性)来使用超参数调节服务。如需了解详情,请参阅 TPUEstimatorSpec

后续步骤