Конвертируйте ваш существующий код в TensorFlow 2.0

Смотрите на TensorFlow.org Запустите в Google Colab Изучайте код на GitHub Скачайте ноутбук

В TensorFlow 2.0 все еще возможно исполнить 1.X код без изменений (за исключением contrib):

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

Однако, это не дает вам воспользоваться преимуществами многих улучшений сделанных в TensorFlow 2.0. Это руководство поможет вам обновить ваш код, сделав его проще, производительнее и легче в поддержке.

Скрипт автоматической конвертации

Первым шагом вы можете попробовать запустить скрипт обновления.

Он выполнит начальный этап обновления вашего кода до TensorFlow 2.0. Но это не может сделать ваш код идиоматичным TensorFlowF 2.0. Ваш код все еще может использовать tf.compat.v1 для доступа к плейсхолдерам, сессиям, коллекциям, и другой функциональности в стиле 1.x.

Сделайте код 2.0-нативным

В этом руководстве рассматриваются несколько примеров преобразования кода TensorFlow 1.x в TensorFlow 2.0. Эти изменения позволят вашему коду воспользоваться преимуществами оптимизации производительности и упрощенных вызовов API.

В каждом случае паттерн следующий:

1. Заменить вызовы tf.Session.run

Каждый вызов tf.Session.run нужо заменить функцией Python.

  • feed_dict и tf.placeholders становятся аргументами функции.
  • fetches становится возвращаемым значением функции.

Вы можете пройти пошагово и отладить функцию, используя стандартные инструменты Python, такие как pdb.

Когда вы убедитесь, что функция работает, добавьте декораторtf.function чтобы она работала эффективно в режиме графа. Смотри Руководство Autograph чтобы узнать больше о том, как это работает.

2. Используйте объекты python для отслеживания переменных и значений потерь

Используйте tf.Variable вместо tf.get_variable.

Каждый variable_scope может быть сконвертирован в объект Python. Как правило это будет что-то из:

Если вам нужны свести списки переменных (как например tf.Graph.get_collection(tf.GraphKeys.VARIABLES)), используйте аттрибуты .variables и .trainable_variables объектов Layer и Model.

Эти классы Layer и Model реализуют несколько других свойств которые устраняют необходимость глобальных коллекций.

Смотри руководства keras для подробностей.

Предупреждение: Многие символы tf.compat.v1 неявно используют глобальные коллекции.

3. Обновите ваши обучающие циклы

Используйте API наиболее высокого уровня который работает в вашем случае. Предпочтите tf.keras.Model.fit построению своего собственного обучающего цикла.

Эти высокоуровневые функции управляют большим количеством низкоуровневых деталей которые могут быть легко упущены если вы пишете собственный обучающий цикл. Например, они автоматически собирают потери регуляризации и устанавливают аргумент training = True при вызове модели.

4. Обновите ваши конвейеры ввода данных

Используйте наборы данных tf.data для входных данных. Эти объекты эффективны, выразительны и хорошо интегрированы с tensorflow.

Их можно передать напрямую в метод tf.keras.Model.fit.

model.fit(dataset, epochs=5)

Их можно напрямую итерировать в стандартном Python:

for example_batch, label_batch in dataset:
    break

Конвертация моделей

Установка

from __future__ import absolute_import, division, print_function, unicode_literals
try:
  # %tensorflow_version only exists in Colab.
  import tensorflow.compat.v2 as tf
except Exception:
  pass
tf.enable_v2_behavior()


import tensorflow_datasets as tfds

Низкоуровневые переменные и исполнение оператора

Примеры использования низкоуровневого API включают:

  • использование областей видимости переменных для управления повторным использованием
  • создание переменных с tf.get_variable.
  • явный доступ к коллекциям
  • неявный доступ к коллекциям с такими методами, как:

    • tf.global_variables
    • tf.losses.get_regularization_loss
  • использование tf.placeholder для установления входных данных графа

  • выполнение графа с session.run

  • ручная инициализация переменных

Перед конвертацией

Здесь как могут выглядеть эти паттерны в коде использующем TensorFlow 1.x.

in_a = tf.placeholder(dtype=tf.float32, shape=(2))
in_b = tf.placeholder(dtype=tf.float32, shape=(2))

def forward(x):
  with tf.variable_scope("matmul", reuse=tf.AUTO_REUSE):
    W = tf.get_variable("W", initializer=tf.ones(shape=(2,2)),
                        regularizer=tf.contrib.layers.l2_regularizer(0.04))
    b = tf.get_variable("b", initializer=tf.zeros(shape=(2)))
    return W * x + b

out_a = forward(in_a)
out_b = forward(in_b)

reg_loss = tf.losses.get_regularization_loss(scope="matmul")

with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  outs = sess.run([out_a, out_b, reg_loss],
                feed_dict={in_a: [1, 0], in_b: [0, 1]})

После конвертации

В сконвертированном коде:

  • Переменные являются локальными объектами Python.
  • Функция forward все еще определяет вычисления.
  • Вызов sess.run заменен вызовом forward
  • Опциональный декоратор tf.function может быть добавлен для производительности.
  • Регуляризации вычисляются вручную без ссылок на глобальные коллекции.
  • Нет сессий и плейсхолдеров.
W = tf.Variable(tf.ones(shape=(2,2)), name="W")
b = tf.Variable(tf.zeros(shape=(2)), name="b")

@tf.function
def forward(x):
  return W * x + b

out_a = forward([1,0])
print(out_a)
tf.Tensor(
[[1. 0.]
 [1. 0.]], shape=(2, 2), dtype=float32)

out_b = forward([0,1])

regularizer = tf.keras.regularizers.l2(0.04)
reg_loss = regularizer(W)

Модели основанные на tf.layers

Модуль tf.layers используется для содержания layer-функций использующих tf.variable_scope для определения и переиспользования переменных.

До конвертации

def model(x, training, scope='model'):
  with tf.variable_scope(scope, reuse=tf.AUTO_REUSE):
    x = tf.layers.conv2d(x, 32, 3, activation=tf.nn.relu,
          kernel_regularizer=tf.contrib.layers.l2_regularizer(0.04))
    x = tf.layers.max_pooling2d(x, (2, 2), 1)
    x = tf.layers.flatten(x)
    x = tf.layers.dropout(x, 0.1, training=training)
    x = tf.layers.dense(x, 64, activation=tf.nn.relu)
    x = tf.layers.batch_normalization(x, training=training)
    x = tf.layers.dense(x, 10, activation=tf.nn.softmax)
    return x

train_out = model(train_data, training=True)
test_out = model(test_data, training=False)

После конвертации

Большинство аргументов остались прежними. Но обратите внимание на различия:

  • Аргумент training передается моделью каждому слою при его запуске.
  • Первого аргумента исходной функции model (вводный x) больше нет. Это связано с тем, что слои объекта отделяют построение модели от вызова модели.

Также заметьте что:

  • Если вы использовали регуляризаторы инициализаторов из tf.contrib, у них больше изменений аргументов чем у остальных.
  • Код больше не записывает в коллекции, так что функции наподобие tf.losses.get_regularization_loss больше не возращают эти значения, что может нарушить ваши циклы обучения.
model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, 3, activation='relu',
                           kernel_regularizer=tf.keras.regularizers.l2(0.04),
                           input_shape=(28, 28, 1)),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.1),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dense(10, activation='softmax')
])

train_data = tf.ones(shape=(1, 28, 28, 1))
test_data = tf.ones(shape=(1, 28, 28, 1))
train_out = model(train_data, training=True)
print(train_out)
tf.Tensor([[0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]], shape=(1, 10), dtype=float32)

test_out = model(test_data, training=False)
print(test_out)
tf.Tensor(
[[0.1364518  0.09528389 0.03826673 0.09252873 0.0725314  0.1685419
  0.05575869 0.10597001 0.11369339 0.12097348]], shape=(1, 10), dtype=float32)

# Здесь все обучаемые переменные.
len(model.trainable_variables)
8
# Здесь потери регуляризации.
model.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=0.07590298>]

Смесь переменных и tf.layers

Существующий код часто смешивает низкоуровневые TF 1.x переменные и операции с высокоуровневыми tf.layers.

До конвертации

def model(x, training, scope='model'):
  with tf.variable_scope(scope, reuse=tf.AUTO_REUSE):
    W = tf.get_variable(
      "W", dtype=tf.float32,
      initializer=tf.ones(shape=x.shape),
      regularizer=tf.contrib.layers.l2_regularizer(0.04),
      trainable=True)
    if training:
      x = x + W
    else:
      x = x + W * 0.5
    x = tf.layers.conv2d(x, 32, 3, activation=tf.nn.relu)
    x = tf.layers.max_pooling2d(x, (2, 2), 1)
    x = tf.layers.flatten(x)
    return x

train_out = model(train_data, training=True)
test_out = model(test_data, training=False)

После конвертации

Для конвертации этого кода следуйте паттерну отображения слоев в слои как и в предыдущем примере.

tf.variable_scope фактически является слоем сам по себе. Поэтому перепишите его как tf.keras.layers.Layer. См. руководство для подробностей.

В общем паттерн следующий:

  • Собрать параметры слоев в __init__.
  • Создать переменные в build.
  • Выполнить вычисления в call и вернуть результат.

tf.variable_scope по сути является собственным слоем. Поэтому перепишите его как tf.keras.layers.Layer. Смотрите руководство для деталей.

# Создайте пользовательский слой для части модели
class CustomLayer(tf.keras.layers.Layer):
  def __init__(self, *args, **kwargs):
    super(CustomLayer, self).__init__(*args, **kwargs)

  def build(self, input_shape):
    self.w = self.add_weight(
        shape=input_shape[1:],
        dtype=tf.float32,
        initializer=tf.keras.initializers.ones(),
        regularizer=tf.keras.regularizers.l2(0.02),
        trainable=True)

  # Метод call будет иногда использоваться в режиме графа,
  # training превратится в тензор
  @tf.function
  def call(self, inputs, training=None):
    if training:
      return inputs + self.w
    else:
      return inputs + self.w * 0.5
custom_layer = CustomLayer()
print(custom_layer([1]).numpy())
print(custom_layer([1], training=True).numpy())
[1.5]
[2.]

train_data = tf.ones(shape=(1, 28, 28, 1))
test_data = tf.ones(shape=(1, 28, 28, 1))

# Build the model including the custom layer
model = tf.keras.Sequential([
    CustomLayer(input_shape=(28, 28, 1)),
    tf.keras.layers.Conv2D(32, 3, activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
])

train_out = model(train_data, training=True)
test_out = model(test_data, training=False)

Некоторые вещи на заметку:

  • Подклассы моделей и слоев Keras нужно запускать и в v1 графах (без автоматического контроля зависимостей) и в режиме eager mode

    • Оберните call() в tf.function() чтобы получить autograph и автоматический контроль зависимостей
  • Не забудьте принять аргумент training в call.

    • Иногда это tf.Tensor
    • Иногда это булеан Python.
  • Создайте переменные модели в конструкторе или def build() используя self.add_weight().

    • В build у вас есть доступ к размерности входных данных, так что создайте веса с совпадающими размерностями.
    • Использование tf.keras.layers.Layer.add_weight позволяет Keras отслеживать переменные и потери регуляризации.
  • Не храните tf.Tensors в своих объектах.

    • Они могут быть созданы либо в tf.function либо в контексте eager, и эти тензоры ведут себя по-другому.
    • Используйте tf.Variables для состояния, их всегда можно использовать из обеих контекстов
    • tf.Tensors это только промежуточные значения.

Замечание о Slim и contrib.layers

Большое количество старого TensorFlow 1.x кода использует библиотеку Slim которая входит в пакет TensorFlow 1.x в качестве tf.contrib.layers. В качестве модуля contrib она более не доступна в TensorFlow 2.0, даже в tf.compat.v1. Конвертация кода использовавшего Slim в TF 2.0 запутаннее чем конвертация репозиториев использующих tf.layers. Имеет смысл сперва сконвертировать ваш Slim код сперва вtf.layers, а затем конвертировать в Keras.

  • Уберите arg_scopes, все аргументы должны быть явными
  • Если вы используете их, поделите normalizer_fn и activation_fn каждый в свой собственный слой
  • Separable сверточные слои отображаются в один или более различных слоев Keras (по глубине, поточечно, и separable слои Keras)
  • Slim и tf.layers имеют разные имена аргументов и значения по умолчанию
  • Некоторые аргументы имеют разные размерности
  • Если вы используете предобученные модели Slim, попробуйте tf.keras.applications или TFHub

Некоторые слои tf.contrib возможно не были перемещены в ядро TensorFlow, а вместо этого были перемещены в пакет TF add-ons.

Обучение

Существует много способов подачи данных в модели tf.keras. Они допускают генераторы Python и массивы Numpy в качестве входных данных.

Рекомендуемы способ подачи данных в модель это - использовать пакет tf.data, который содержит набор высокопроизводительных классов для манипуляций с данными.

Если вы все еще используете tf.queue, они поддерживаются только как структуры данных, а не как входные конвейеры.

Использование наборов данных

Пакет TensorFlow Datasets (tfds) содержит утилиты для загрузки предопределенных баз данных как объектов tf.data.Dataset.

Например, загрузим MNISTdataset, используя tfds:

datasets, info = tfds.load(name='mnist', with_info=True, as_supervised=True)
mnist_train, mnist_test = datasets['train'], datasets['test']
Downloading and preparing dataset mnist/3.0.1 (download: 11.06 MiB, generated: 21.00 MiB, total: 32.06 MiB) to /home/kbuilder/tensorflow_datasets/mnist/3.0.1...

Warning:absl:Dataset mnist is hosted on GCS. It will automatically be downloaded to your
local data directory. If you'd instead prefer to read directly from our public
GCS bucket (recommended if you're running on GCP), you can instead set
data_dir=gs://tfds-data/datasets.


HBox(children=(FloatProgress(value=0.0, description='Dl Completed...', max=4.0, style=ProgressStyle(descriptio…


Dataset mnist downloaded and prepared to /home/kbuilder/tensorflow_datasets/mnist/3.0.1. Subsequent calls will reuse this data.

Затем приготовим данные для обучения:

  • Изменим размер каждого изображения.
  • Перемешаем порядок примеров.
  • Соберем batches изображений и меток.
BUFFER_SIZE = 10 # Используйте намного большее значение для настоящего кода.
BATCH_SIZE = 64
NUM_EPOCHS = 5


def scale(image, label):
  image = tf.cast(image, tf.float32)
  image /= 255

  return image, label

Чтобы пример оставался коротким обрежем данные, чтобы он возвращал только 5 batches:

train_data = mnist_train.map(scale).shuffle(BUFFER_SIZE).batch(BATCH_SIZE).take(5)
test_data = mnist_test.map(scale).batch(BATCH_SIZE).take(5)

STEPS_PER_EPOCH = 5

train_data = train_data.take(STEPS_PER_EPOCH)
test_data = test_data.take(STEPS_PER_EPOCH)
image_batch, label_batch = next(iter(train_data))

Использование обучающик циклов Keras

Если вам не нужен низкоуровневый коноль процесса обучения модели, рекомендуется использовать встроенные в Keras методы fit, evaluate и predict. Эти методы обеспечивают единый интерфейс обучения модели независимо от реализации (sequential, functional или sub-classed).

Преимущества этих методов включают:

  • Они допускают массивы Numpy, генераторы Python и tf.data.Datasets
  • Они применяют регуляризационные и активационные потери автоматически.
  • Они поддерживают tf.distribute для обучения на нескольких устройствах.
  • Они поддерживают произвольные вызываемые объекты как потери и метрики.
  • Они поддерживают коллбеки такие как tf.keras.callbacks.TensorBoard и пользовательские коллбеки.
  • Они производительны, автоматически используя графы TensorFlow.

Приведем пример обучения модели с ипользованием Dataset. (Подробнее о том как это работает смотри тьюториалы.)

model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, 3, activation='relu',
                           kernel_regularizer=tf.keras.regularizers.l2(0.02),
                           input_shape=(28, 28, 1)),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.1),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dense(10, activation='softmax')
])

# Model is the full model w/o custom layers
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(train_data, epochs=NUM_EPOCHS)
loss, acc = model.evaluate(test_data)

print("Loss {}, Accuracy {}".format(loss, acc))
Epoch 1/5
5/5 [==============================] - 1s 135ms/step - loss: 1.5386 - accuracy: 0.5344
Epoch 2/5
5/5 [==============================] - 0s 19ms/step - loss: 0.5153 - accuracy: 0.9031
Epoch 3/5
5/5 [==============================] - 0s 20ms/step - loss: 0.3273 - accuracy: 0.9469
Epoch 4/5
5/5 [==============================] - 0s 19ms/step - loss: 0.2370 - accuracy: 0.9781
Epoch 5/5
5/5 [==============================] - 0s 19ms/step - loss: 0.1765 - accuracy: 0.9875
      5/Unknown - 0s 27ms/step - loss: 1.6907 - accuracy: 0.7250Loss 1.6907326221466064, Accuracy 0.7250000238418579

Напишите свой собственный цикл

Если обучающий шаг модели Keras подходит вам, но вне шага вам нужет больший контроль, рассмотрите использование tf.keras.model.train_on_batch method, в вашем собтвенном цикле итерации данных.

Запомните: Многие вещи могут быть реализованы как tf.keras.Callback.

Этот метод имеет много преимуществ перед методами, упомянутыми в предыдущем разделе, но он дает пользователю контроль над внешним циклом.

Вы также можете использовать tf.keras.model.test_on_batch или tf.keras.Model.evaluate чтобы проверить производительность во время обучения.

Примечание: train_on_batch и test_on_batch по умолчанию возвращают потерю и метрики для одного batch. Если вы передаете reset_metrics=False они возвращают накопленные метрики и вы должны помнить своевременно сбрасывать накопители метрик. Таже помните, что некоторые метрики, такие как AUC требуют reset_metrics=False для корректного вычисления.

Чтобы продолжить обучение вышеуказанной модели:

# Model это полная модель без пользовательских слоев
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

metrics_names = model.metrics_names

for epoch in range(NUM_EPOCHS):
  #Reset the metric accumulators
  model.reset_metrics()

  for image_batch, label_batch in train_data:
    result = model.train_on_batch(image_batch, label_batch)
    print("train: ",
          "{}: {:.3f}".format(metrics_names[0], result[0]),
          "{}: {:.3f}".format(metrics_names[1], result[1]))
  for image_batch, label_batch in test_data:
    result = model.test_on_batch(image_batch, label_batch,
                                 # return accumulated metrics
                                 reset_metrics=False)
  print("\neval: ",
        "{}: {:.3f}".format(metrics_names[0], result[0]),
        "{}: {:.3f}".format(metrics_names[1], result[1]))


train:  loss: 0.161 accuracy: 1.000
train:  loss: 0.146 accuracy: 0.984
train:  loss: 0.185 accuracy: 0.969
train:  loss: 0.191 accuracy: 0.984
train:  loss: 0.223 accuracy: 0.938

eval:  loss: 1.702 accuracy: 0.775
train:  loss: 0.102 accuracy: 1.000
train:  loss: 0.086 accuracy: 1.000
train:  loss: 0.087 accuracy: 1.000
train:  loss: 0.120 accuracy: 0.984
train:  loss: 0.140 accuracy: 0.984

eval:  loss: 1.663 accuracy: 0.788
train:  loss: 0.074 accuracy: 1.000
train:  loss: 0.071 accuracy: 1.000
train:  loss: 0.069 accuracy: 1.000
train:  loss: 0.079 accuracy: 1.000
train:  loss: 0.069 accuracy: 1.000

eval:  loss: 1.644 accuracy: 0.797
train:  loss: 0.061 accuracy: 1.000
train:  loss: 0.068 accuracy: 1.000
train:  loss: 0.059 accuracy: 1.000
train:  loss: 0.056 accuracy: 1.000
train:  loss: 0.071 accuracy: 1.000

eval:  loss: 1.614 accuracy: 0.837
train:  loss: 0.052 accuracy: 1.000
train:  loss: 0.058 accuracy: 1.000
train:  loss: 0.047 accuracy: 1.000
train:  loss: 0.051 accuracy: 1.000
train:  loss: 0.047 accuracy: 1.000

eval:  loss: 1.584 accuracy: 0.866

Настройте шаг обучения

Если вам нужны большая гибкость и контроль, вы можете получить их реализовав собственный цикл обучения. Есть три шага:

  1. Проитерируйте генератор Python или tf.data.Dataset чтобы получить пакеты примеров.
  2. Используйте tf.GradientTape чтобы собрать градиенты.
  3. Используйте tf.keras.optimizer чтобы применить обновления весов к переменным модели.

Помните:

  • Всегда включайте аргумент training в метод call подклассов слоев и моделей.
  • Убедитесь что вызываете модель с корректно установленным аргументом training.
  • В зависимости от использования, переменные модели могут не существовать, пока модель не будет запущена на пакете данных.
  • Вам нужно вручную обрабатывать такие вещи, как потери регуляризации для модели.

Обратите внимание на упрощения относительно v1:

  • Нет необходимости запускать инициализаторы переменных. Переменные инициализируются при создании.
  • Нет необходимости добавлять зависимости ручного управления. Даже в операциях tf.function действующих как в eager mode.
model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, 3, activation='relu',
                           kernel_regularizer=tf.keras.regularizers.l2(0.02),
                           input_shape=(28, 28, 1)),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.1),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dense(10, activation='softmax')
])

optimizer = tf.keras.optimizers.Adam(0.001)
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy()

@tf.function
def train_step(inputs, labels):
  with tf.GradientTape() as tape:
    predictions = model(inputs, training=True)
    regularization_loss = tf.math.add_n(model.losses)
    pred_loss = loss_fn(labels, predictions)
    total_loss = pred_loss + regularization_loss

  gradients = tape.gradient(total_loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

for epoch in range(NUM_EPOCHS):
  for inputs, labels in train_data:
    train_step(inputs, labels)
  print("Finished epoch", epoch)

Finished epoch 0
Finished epoch 1
Finished epoch 2
Finished epoch 3
Finished epoch 4

Метрики в новом стиле

В TensorFlow 2.0, метрики являются объектами. Метрики работают и eagerly и в tf.function. Объекты-метрики обладают следующими методами:

  • update_state() — добавить новые наблюдения
  • result() — получить текущий результат метрики при данных наблюдаемых значениях
  • reset_states() — очистить все наблюдения.

Объект сам является вызываемым. Вызов обновляет состояние новыми наблюдениями, как и с update_state, и возвращает новый результат метрики

Вам не нужно вручную инициализировать переменные метрики, и, поскольку у TensorFlow 2.0 автоматическое управление зависимостями, вам не нужно беспокоиться и об этом.

В приведенном ниже коде используется метрика для отслеживания среднего значения потерь, наблюдаемых в пользовательском цикле обучения.

# Создайте метрики
loss_metric = tf.keras.metrics.Mean(name='train_loss')
accuracy_metric = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')

@tf.function
def train_step(inputs, labels):
  with tf.GradientTape() as tape:
    predictions = model(inputs, training=True)
    regularization_loss = tf.math.add_n(model.losses)
    pred_loss = loss_fn(labels, predictions)
    total_loss = pred_loss + regularization_loss

  gradients = tape.gradient(total_loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))
  # Обновите метрики
  loss_metric.update_state(total_loss)
  accuracy_metric.update_state(labels, predictions)


for epoch in range(NUM_EPOCHS):
  # Сбросьте метрики
  loss_metric.reset_states()
  accuracy_metric.reset_states()

  for inputs, labels in train_data:
    train_step(inputs, labels)
  # Получите результаты метрики
  mean_loss = loss_metric.result()
  mean_accuracy = accuracy_metric.result()

  print('Epoch: ', epoch)
  print('  loss:     {:.3f}'.format(mean_loss))
  print('  accuracy: {:.3f}'.format(mean_accuracy))

Epoch:  0
  loss:     0.132
  accuracy: 0.997
Epoch:  1
  loss:     0.104
  accuracy: 0.997
Epoch:  2
  loss:     0.089
  accuracy: 1.000
Epoch:  3
  loss:     0.078
  accuracy: 1.000
Epoch:  4
  loss:     0.069
  accuracy: 1.000

Сохранение и загрузка

Совместимость контрольных точек

TensorFlow 2.0 использует контрольные точки основанные на объектах.

Контрольные точки в старом стиле основанные на именах по-прежнему могут быть загружены, если вы осторожны с ними. В процессе конвертации кода могут измениться имена переменных, но есть обходные пути.

Самый простой подход - согласовать имена новой модели с именами в контрольной точке.:

  • У переменных все еще есть аргумент name который вы можете установить.
  • Модели Keras также используют аргумент name, который они устанавливают в качестве префикса для своих переменных.
  • Функция tf.name_scope может использоваться для установки префиксов имен переменных. Это сильно отличается от tf.variable_scope. Он влияет только на имена и не отслеживает переменные и их переиспользование.

Если это не работает для вашего случая, попробуйте функцию tf.compat.v1.train.init_from_checkpoint. Она принимает аргумент assignment_map, который определяет соответствие старых и новых имен.

Примечание: В отличие от основанных на объектах контрольных точек, которые могут отложить загрузку, основанные на именах контрольных точек требуют, чтобы при вызове функции были созданы все переменные. Некоторые модели откладывают создание переменных до тех пор, пока вы не вызовете build или не запустите модель на пакете данных.

Совместимость сохраненных моделей

У совместимости для сохраненных моделей нет существенных проблем.

  • TensorFlow 1.x saved_models работают TensorFlow 2.0.
  • TensorFlow 2.0 saved_models даже загруженные работают в TensorFlow 1.x если все операции поддерживаются.

Estimators

Обучение с оценщиками

Оценщики поддерживаются TensorFlow 2.0.

Когда вы используете оценщики, вы можете использовать input_fn(), tf.estimator.TrainSpec, и tf.estimator.EvalSpec из TensorFlow 1.x.

Здесь пример использующий input_fn с train and evaluate specs.

Создание input_fn и train/eval specs

# Определим input_fn оценщика 
def input_fn():
  datasets, info = tfds.load(name='mnist', with_info=True, as_supervised=True)
  mnist_train, mnist_test = datasets['train'], datasets['test']

  BUFFER_SIZE = 10000
  BATCH_SIZE = 64

  def scale(image, label):
    image = tf.cast(image, tf.float32)
    image /= 255

    return image, label[..., tf.newaxis]

  train_data = mnist_train.map(scale).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
  return train_data.repeat()

# Define train & eval specs
train_spec = tf.estimator.TrainSpec(input_fn=input_fn,
                                    max_steps=STEPS_PER_EPOCH * NUM_EPOCHS)
eval_spec = tf.estimator.EvalSpec(input_fn=input_fn,
                                  steps=STEPS_PER_EPOCH)

Использование определения модели Keras

Есть некоторые отличия в том, как построить ваши оценщики в TensorFlow 2.0.

Мы рекомендуем вам определить модель используя Keras, потом используйте утилиту tf.keras.model_to_estimator для преобразования вашей модели в оценщика. Нижеприведенный код показывает как использовать эту утилиту когда создаешь и обучаешь оценщик.

def make_model():
  return tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, 3, activation='relu',
                           kernel_regularizer=tf.keras.regularizers.l2(0.02),
                           input_shape=(28, 28, 1)),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.1),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dense(10, activation='softmax')
  ])
model = make_model()

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

estimator = tf.keras.estimator.model_to_estimator(
  keras_model = model
)

tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
INFO:tensorflow:Using default config.

INFO:tensorflow:Using default config.

Warning:tensorflow:Using temporary folder as model directory: /tmp/tmpp9af7k51

Warning:tensorflow:Using temporary folder as model directory: /tmp/tmpp9af7k51

INFO:tensorflow:Using the Keras model provided.

INFO:tensorflow:Using the Keras model provided.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:1635: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:1635: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.

INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpp9af7k51', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpp9af7k51', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

INFO:tensorflow:Not using Distribute Coordinator.

INFO:tensorflow:Not using Distribute Coordinator.

INFO:tensorflow:Running training and evaluation locally (non-distributed).

INFO:tensorflow:Running training and evaluation locally (non-distributed).

INFO:tensorflow:Start train and evaluate loop. The evaluate will happen after every checkpoint. Checkpoint frequency is determined based on RunConfig arguments: save_checkpoints_steps None or save_checkpoints_secs 600.

INFO:tensorflow:Start train and evaluate loop. The evaluate will happen after every checkpoint. Checkpoint frequency is determined based on RunConfig arguments: save_checkpoints_steps None or save_checkpoints_secs 600.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_core/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_core/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Warm-starting with WarmStartSettings: WarmStartSettings(ckpt_to_initialize_from='/tmp/tmpp9af7k51/keras/keras_model.ckpt', vars_to_warm_start='.*', var_name_to_vocab_info={}, var_name_to_prev_var_name={})

INFO:tensorflow:Warm-starting with WarmStartSettings: WarmStartSettings(ckpt_to_initialize_from='/tmp/tmpp9af7k51/keras/keras_model.ckpt', vars_to_warm_start='.*', var_name_to_vocab_info={}, var_name_to_prev_var_name={})

INFO:tensorflow:Warm-starting from: /tmp/tmpp9af7k51/keras/keras_model.ckpt

INFO:tensorflow:Warm-starting from: /tmp/tmpp9af7k51/keras/keras_model.ckpt

INFO:tensorflow:Warm-starting variables only in TRAINABLE_VARIABLES.

INFO:tensorflow:Warm-starting variables only in TRAINABLE_VARIABLES.

INFO:tensorflow:Warm-started 8 variables.

INFO:tensorflow:Warm-started 8 variables.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpp9af7k51/model.ckpt.

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpp9af7k51/model.ckpt.

INFO:tensorflow:loss = 2.8284678, step = 0

INFO:tensorflow:loss = 2.8284678, step = 0

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tmpp9af7k51/model.ckpt.

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tmpp9af7k51/model.ckpt.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Starting evaluation at 2020-03-13T13:51:18Z

INFO:tensorflow:Starting evaluation at 2020-03-13T13:51:18Z

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Restoring parameters from /tmp/tmpp9af7k51/model.ckpt-25

INFO:tensorflow:Restoring parameters from /tmp/tmpp9af7k51/model.ckpt-25

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Evaluation [1/5]

INFO:tensorflow:Evaluation [1/5]

INFO:tensorflow:Evaluation [2/5]

INFO:tensorflow:Evaluation [2/5]

INFO:tensorflow:Evaluation [3/5]

INFO:tensorflow:Evaluation [3/5]

INFO:tensorflow:Evaluation [4/5]

INFO:tensorflow:Evaluation [4/5]

INFO:tensorflow:Evaluation [5/5]

INFO:tensorflow:Evaluation [5/5]

INFO:tensorflow:Inference Time : 0.79030s

INFO:tensorflow:Inference Time : 0.79030s

INFO:tensorflow:Finished evaluation at 2020-03-13-13:51:19

INFO:tensorflow:Finished evaluation at 2020-03-13-13:51:19

INFO:tensorflow:Saving dict for global step 25: accuracy = 0.6875, global_step = 25, loss = 1.5868708

INFO:tensorflow:Saving dict for global step 25: accuracy = 0.6875, global_step = 25, loss = 1.5868708

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tmpp9af7k51/model.ckpt-25

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tmpp9af7k51/model.ckpt-25

INFO:tensorflow:Loss for final step: 0.47693205.

INFO:tensorflow:Loss for final step: 0.47693205.

({'accuracy': 0.6875, 'loss': 1.5868708, 'global_step': 25}, [])

Использование пользовательской model_fn

Если у вас есть существующий пользовательский оценщик model_fn, который вам нужно поддерживать, вы можете конвертировать свойmodel_fn чтобы использовать модель Keras.

Однако по соображениям совместимости пользовательский model_fn будет по-прежнему работать в стиле 1.x графа. Это означает, что нет будет eager execution и нет автоматического управления зависимостей.

Использование моделей Keras в пользовательском model_fn аналогично использованию в пользовательском цикле обучения:

  • Установите фазу training соответствующе, основываясь на аргументе mode.
  • Явно передайте trainable_variables модели оптимизатору.

Но есть важные различия отлосящиеся к пользовательскому циклу:

  • Вместо использования model.losses извлеките потери, используяtf.keras.Model.get_losses_for.
  • Извлеките обновления модели используя tf.keras.Model.get_updates_for

Примечание: "Updates" это изменения которые необходимо применить к модели после каждого пакета. Например, скользящие средние среднего и дисперсии в слое tf.keras.layers.BatchNormalization.

Следующий код создает оценщик из пользовательского model_fn, иллюстрируя все эти проблемы.

def my_model_fn(features, labels, mode):
  model = make_model()

  optimizer = tf.compat.v1.train.AdamOptimizer()
  loss_fn = tf.keras.losses.SparseCategoricalCrossentropy()

  training = (mode == tf.estimator.ModeKeys.TRAIN)
  predictions = model(features, training=training)

  reg_losses = model.get_losses_for(None) + model.get_losses_for(features)
  total_loss = loss_fn(labels, predictions) + tf.math.add_n(reg_losses)

  accuracy = tf.compat.v1.metrics.accuracy(labels=labels,
                                           predictions=tf.math.argmax(predictions, axis=1),
                                           name='acc_op')

  update_ops = model.get_updates_for(None) + model.get_updates_for(features)
  minimize_op = optimizer.minimize(
      total_loss,
      var_list=model.trainable_variables,
      global_step=tf.compat.v1.train.get_or_create_global_step())
  train_op = tf.group(minimize_op, update_ops)

  return tf.estimator.EstimatorSpec(
    mode=mode,
    predictions=predictions,
    loss=total_loss,
    train_op=train_op, eval_metric_ops={'accuracy': accuracy})

# Создайте оценщик и обучите
estimator = tf.estimator.Estimator(model_fn=my_model_fn)
tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
INFO:tensorflow:Using default config.

INFO:tensorflow:Using default config.

Warning:tensorflow:Using temporary folder as model directory: /tmp/tmpsw8lmz2z

Warning:tensorflow:Using temporary folder as model directory: /tmp/tmpsw8lmz2z

INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpsw8lmz2z', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpsw8lmz2z', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

INFO:tensorflow:Not using Distribute Coordinator.

INFO:tensorflow:Not using Distribute Coordinator.

INFO:tensorflow:Running training and evaluation locally (non-distributed).

INFO:tensorflow:Running training and evaluation locally (non-distributed).

INFO:tensorflow:Start train and evaluate loop. The evaluate will happen after every checkpoint. Checkpoint frequency is determined based on RunConfig arguments: save_checkpoints_steps None or save_checkpoints_secs 600.

INFO:tensorflow:Start train and evaluate loop. The evaluate will happen after every checkpoint. Checkpoint frequency is determined based on RunConfig arguments: save_checkpoints_steps None or save_checkpoints_secs 600.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpsw8lmz2z/model.ckpt.

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpsw8lmz2z/model.ckpt.

INFO:tensorflow:loss = 2.9860203, step = 0

INFO:tensorflow:loss = 2.9860203, step = 0

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tmpsw8lmz2z/model.ckpt.

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tmpsw8lmz2z/model.ckpt.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Starting evaluation at 2020-03-13T13:51:22Z

INFO:tensorflow:Starting evaluation at 2020-03-13T13:51:22Z

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Restoring parameters from /tmp/tmpsw8lmz2z/model.ckpt-25

INFO:tensorflow:Restoring parameters from /tmp/tmpsw8lmz2z/model.ckpt-25

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Evaluation [1/5]

INFO:tensorflow:Evaluation [1/5]

INFO:tensorflow:Evaluation [2/5]

INFO:tensorflow:Evaluation [2/5]

INFO:tensorflow:Evaluation [3/5]

INFO:tensorflow:Evaluation [3/5]

INFO:tensorflow:Evaluation [4/5]

INFO:tensorflow:Evaluation [4/5]

INFO:tensorflow:Evaluation [5/5]

INFO:tensorflow:Evaluation [5/5]

INFO:tensorflow:Inference Time : 0.92419s

INFO:tensorflow:Inference Time : 0.92419s

INFO:tensorflow:Finished evaluation at 2020-03-13-13:51:23

INFO:tensorflow:Finished evaluation at 2020-03-13-13:51:23

INFO:tensorflow:Saving dict for global step 25: accuracy = 0.79375, global_step = 25, loss = 1.613637

INFO:tensorflow:Saving dict for global step 25: accuracy = 0.79375, global_step = 25, loss = 1.613637

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tmpsw8lmz2z/model.ckpt-25

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tmpsw8lmz2z/model.ckpt-25

INFO:tensorflow:Loss for final step: 0.58073264.

INFO:tensorflow:Loss for final step: 0.58073264.

({'accuracy': 0.79375, 'loss': 1.613637, 'global_step': 25}, [])

Готовые оценщики

Готовые оценщики из семейств tf.estimator.DNN*, tf.estimator.Linear* и tf.estimator.DNNLinearCombined* все еще поддерживаются в TensorFlow 2.0 API, однако, некоторые аргументы изменились:

  1. input_layer_partitioner: Убрано в 2.0.
  2. loss_reduction: Обновлено до tf.keras.losses.Reduction вместо tf.compat.v1.losses.Reduction. Значение по умолчанию также изменилось и стало tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE вместо tf.compat.v1.losses.Reduction.SUM.
  3. optimizer, dnn_optimizer и linear_optimizer: эти аргументы обновились до tf.keras.optimizers вместо tf.compat.v1.train.Optimizer.

Для переноса вышеуказанных изменений:

  1. Для input_layer_partitioner миграция не требуется поскольку Стратегия распределения обработает это автоматически в TF 2.0.
  2. Для loss_reduction, проверьте tf.keras.losses.Reduction для поддерживаемых опций.
  3. Для аргументов optimizer args, если вы не передаете аргумента optimizer, dnn_optimizer или linear_optimizer, или если вы укажете в своем коде аргумент optimizer как string, вам не нужно ничего менять. tf.keras.optimizers используются по умолчанию. Иначе, вам нужно обновить его от tf.compat.v1.train.Optimizer до соответсвующей tf.keras.optimizers

Конвертер контрольных точек

Миграция optimizer повредит контрольные точки в TF 1.x, так какtf.keras.optimizer генерирует другой набор переменных для сохранения в контрольных точках. Чтобы сделать контрольную пригодной к использованию после перехода на TF 2.0, пожалуйста, посмотрите инструмент конвертации контрольных точек для оптимизаторов, чтобы преобразовать контрольные точки из TF 1.x в TF 2.0. Преобразованные контрольные точки можно использовать для восстановления предварительно обученных моделей в TF 2.0.

TensorShape

Этот класс был упрощен для хранения int вместо объектов tf.compat.v1.Dimension. Так что нет необходимости в вызове .value() чтобы получить int.

Отдельные объекты tf.compat.v1.Dimension по-прежнему доступны из tf.TensorShape.dims.

Следующее демонстрирует отличия TensorFlow 1.x и TensorFlow 2.0.

# Создайте shape и выберите index
i = 0
shape = tf.TensorShape([16, None, 256])
shape
TensorShape([16, None, 256])

Если у вас есть это в TF 1.x:

value = shape[i].value

Сделайте это в TF 2.0:

value = shape[i]
value
16

Если у вас есть это в TF 1.x:

for dim in shape:
    value = dim.value
    print(value)

TСделайте это в TF 2.0:

for value in shape:
  print(value)
16
None
256

Если у вас есть это в 1.x (Или используется любой другой метод размерности):

dim = shape[i]
dim.assert_is_compatible_with(other_dim)

Сделайте это в TF 2.0:

other_dim = 16
Dimension = tf.compat.v1.Dimension

if shape.rank is None:
  dim = Dimension(None)
else:
  dim = shape.dims[i]
dim.is_compatible_with(other_dim) # или любой другой метод размерности
True
shape = tf.TensorShape(None)

if shape:
  dim = shape.dims[i]
  dim.is_compatible_with(other_dim) # или любой другой метод размерности

Булево значение tf.TensorShape является True если ранг известен, False в противном случае.

print(bool(tf.TensorShape([])))      # Скаляр
print(bool(tf.TensorShape([0])))     # Вектор длины 0
print(bool(tf.TensorShape([1])))     # Вектор длины 1
print(bool(tf.TensorShape([None])))  # Вектор неизвестной длины
print(bool(tf.TensorShape([1, 10, 100])))       # 3D тензор
print(bool(tf.TensorShape([None, None, None]))) # 3D тензор с неизвестными размерностями
print()
print(bool(tf.TensorShape(None)))  # Тензор неизвестного ранга.
True
True
True
True
True
True

False

Другие поведенческие изменения

В TensorFlow 2.0 есть несколько других поведенческих изменений, с которыми вы можете столкнуться.

ResourceVariables

TensorFlow 2.0 создает по умолчанию ResourceVariables, а не RefVariables.

ResourceVariables закрыты для записи, и обеспечивают лучшие гарантии согласовенности.

  • Это может изменить поведение в граничных случаях.
  • Это может иногда создавать дополнительные копии и использовать большие объемы памяти
  • Это можно отключить, передав use_resource = False конструкторуtf.Variable.

Control Flow

Реализация control flow была упрощена, поэтому в TensorFlow 2.0 создаются другие графы.

Выводы

Общий процесс следующий:

  1. Запуститсе upgrade script.
  2. Удалите символы contrib.
  3. Переключите ваши модели в объектно ориентированный стиль (Keras).
  4. Используйте циклы обучения и оценки tf.keras или tf.estimator там где вы можете.
  5. Иначе используйте пользовательские циклы, но избегайте сессий и коллекций.

Для преобразования кода в идиоматический TensorFlow 2.0 требуется небольшая работа, но каждое изменение приводит к:

  • Меньшему количеству строк кода.
  • Увеличившейся понятности и простоте.
  • К более легкой отладке.