##### Copyright 2021 The TensorFlow Authors.
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

迁移指标和优化器#

在 TensorFlow.org 上查看 在 Google Colab 运行 在 Github 上查看源代码 下载笔记本

在 TF1 中,tf.metrics 是所有指标函数的 API 命名空间。每个指标都是一个将 labelprediction 作为输入参数,并返回相应指标张量作为结果的函数。在 TF2 中,tf.keras.metrics 包含所有指标函数和对象。Metric 对象可以与 tf.keras.Modeltf.keras.layers.layer 一起使用来计算指标值。

安装#

从几个必要的 TensorFlow 导入开始:

import tensorflow as tf
import tensorflow.compat.v1 as tf1

然后,准备一个用于演示的简单数据:

features = [[1., 1.5], [2., 2.5], [3., 3.5]]
labels = [0, 0, 1]
eval_features = [[4., 4.5], [5., 5.5], [6., 6.5]]
eval_labels = [0, 1, 1]

TF1:具有 Estimator 的 tf.compat.v1.metrics#

在 TF1 中,指标可以作为 eval_metric_ops 添加到 EstimatorSpec 中,并且运算通过 tf.metrics 中定义的所有指标函数生成。可以按照示例了解如何使用 tf.metrics.accuracy

def _input_fn():
  return tf1.data.Dataset.from_tensor_slices((features, labels)).batch(1)

def _eval_input_fn():
  return tf1.data.Dataset.from_tensor_slices(
      (eval_features, eval_labels)).batch(1)

def _model_fn(features, labels, mode):
  logits = tf1.layers.Dense(2)(features)
  predictions = tf.math.argmax(input=logits, axis=1)
  loss = tf1.nn.sparse_softmax_cross_entropy_with_logits(labels=labels, logits=logits)
  optimizer = tf1.train.AdagradOptimizer(0.05)
  train_op = optimizer.minimize(loss, global_step=tf1.train.get_global_step())
  accuracy = tf1.metrics.accuracy(labels=labels, predictions=predictions)
  return tf1.estimator.EstimatorSpec(mode, 
                                     predictions=predictions,
                                     loss=loss, 
                                     train_op=train_op,
                                     eval_metric_ops={'accuracy': accuracy})

estimator = tf1.estimator.Estimator(model_fn=_model_fn)
estimator.train(_input_fn)
estimator.evaluate(_eval_input_fn)

此外,可以通过 tf.estimator.add_metrics() 直接将指标添加到 Estimator 中。

def mean_squared_error(labels, predictions):
  labels = tf.cast(labels, predictions.dtype)
  return {"mean_squared_error": 
          tf1.metrics.mean_squared_error(labels=labels, predictions=predictions)}

estimator = tf1.estimator.add_metrics(estimator, mean_squared_error)
estimator.evaluate(_eval_input_fn)

TF2:具有 tf.keras.Model 的 Keras Metrics API#

在 TF2 中,tf.keras.metrics 包含所有指标类和函数。它们以 OOP 风格设计,并与其他 tf.keras API 紧密集成。所有指标都可以在 tf.keras.metrics 命名空间中找到,并且 tf.compat.v1.metricstf.keras.metrics 之间通常存在直接映射。

在以下示例中,指标添加到 model.compile() 方法中。用户只需要创建指标实例,无需指定标签和预测张量。Keras 模型会将模型输出和标签发送到指标对象。

dataset = tf.data.Dataset.from_tensor_slices((features, labels)).batch(1)
eval_dataset = tf.data.Dataset.from_tensor_slices(
      (eval_features, eval_labels)).batch(1)

inputs = tf.keras.Input((2,))
logits = tf.keras.layers.Dense(2)(inputs)
predictions = tf.math.argmax(input=logits, axis=1)
model = tf.keras.models.Model(inputs, predictions)
optimizer = tf.keras.optimizers.Adagrad(learning_rate=0.05)

model.compile(optimizer, loss='mse', metrics=[tf.keras.metrics.Accuracy()])
model.evaluate(eval_dataset, return_dict=True)

启用 Eager Execution 后,tf.keras.metrics.Metric 实例可直接用于评估 numpy 数据或 Eager 张量。tf.keras.metrics.Metric 对象是有状态容器。指标值可以通过 metric.update_state(y_true, y_pred) 进行更新,结果可以通过 metrics.result() 进行检索。

accuracy = tf.keras.metrics.Accuracy()

accuracy.update_state(y_true=[0, 0, 1, 1], y_pred=[0, 0, 0, 1])
accuracy.result().numpy()
accuracy.update_state(y_true=[0, 0, 1, 1], y_pred=[0, 0, 0, 0])
accuracy.update_state(y_true=[0, 0, 1, 1], y_pred=[1, 1, 0, 0])
accuracy.result().numpy()

有关 tf.keras.metrics.Metric 的更多详情,请查看 tf.keras.metrics.Metric 下的 API 文档以及迁移指南

将 TF1.x 优化器迁移到 Keras 优化器#

tf.compat.v1.train 中的优化器(如 Adam 优化器梯度下降优化器)在 tf.keras.optimizers 中具有等效项。

下表总结了如何将这些旧版优化器转换为 Keras 等效项。除非需要额外的步骤(例如更新默认学习率),否则可以直接将 TF1.x 版本替换为 TF2 版本。

请注意,转换优化器可能会使旧的检查点不兼容

TF1.x TF2 额外步骤
`tf.v1.train.GradientDescentOptimizer` `tf.keras.optimizers.SGD`
`tf.v1.train.MomentumOptimizer` `tf.keras.optimizers.SGD` 包含 `momentum` 参数
`tf.v1.train.AdamOptimizer` `tf.keras.optimizers.Adam` 将 `beta1` 和 `beta2` 参数重命名为 `beta_1` 和 `beta_2`
`tf.v1.train.RMSPropOptimizer` `tf.keras.optimizers.RMSprop` 将 `decay` 参数重命名为 `rho`
`tf.v1.train.AdadeltaOptimizer` `tf.keras.optimizers.Adadelta`
`tf.v1.train.AdagradOptimizer` `tf.keras.optimizers.Adagrad`
`tf.v1.train.FtrlOptimizer` `tf.keras.optimizers.Ftrl` 移除 `accum_name` 和 `linear_name` 参数
`tf.contrib.AdamaxOptimizer` `tf.keras.optimizers.Adamax` 将 `beta1` 和 `beta2` 参数重命名为 `beta_1` 和 `beta_2`
`tf.contrib.Nadam` `tf.keras.optimizers.Nadam` 将 `beta1` 和 `beta2` 参数重命名为 `beta_1` 和 `beta_2`

注:在 TF2 中,所有 ε(数值稳定性常数)现在默认为 1e-7,而不是 1e-8。在大多数用例中,这种差异可以忽略不计。