Помогают защитить Большой Барьерный Риф с TensorFlow на Kaggle Присоединяйтесь вызов

Эффективный Tensorflow 2

Посмотреть на TensorFlow.org Запустить в Google Colab Посмотреть на GitHub Скачать блокнот

Обзор

В этом руководстве представлен список лучших практик написания кода с использованием TensorFlow 2 (TF2). Обратитесь к Migrate разделу руководства для получения дополнительной информации о переносе кода TF1.x в TF2.

Настраивать

Импортируйте TensorFlow и другие зависимости для примеров в этом руководстве.

import tensorflow as tf
import tensorflow_datasets as tfds

Рекомендации для идиоматического TensorFlow 2

Реорганизуйте код на более мелкие модули

Хорошей практикой является рефакторинг вашего кода на более мелкие функции, которые вызываются по мере необходимости. Для лучшей производительности, вы должны попробовать , чтобы украсить самые большие блоки вычислений , что вы можете в tf.function (обратите внимание , что вложенные функции питона Вызывается tf.function не требуют , чтобы их собственных отдельных украшений, если вы не хотите использовать различный jit_compile настройки для tf.function ). В зависимости от вашего варианта использования это может быть несколько шагов обучения или даже весь цикл обучения. Для случаев использования вывода это может быть прямой проход одной модели.

Отрегулировать скорость обучения по умолчанию для некоторых tf.keras.optimizer с

Некоторые оптимизаторы Keras имеют разную скорость обучения в TF2. Если вы видите изменение поведения сходимости для своих моделей, проверьте скорость обучения по умолчанию.

Там нет никаких изменений для optimizers.SGD , optimizers.Adam или optimizers.RMSprop .

Изменились следующие скорости обучения по умолчанию:

Используйте tf.Module s и Keras слои для управления переменными

tf.Module s и tf.keras.layers.Layer сек предлагают удобные variables и trainable_variables свойства, которые рекурсивно собрать все зависимые переменные. Это упрощает локальное управление переменными там, где они используются.

Keras слои / модели наследуют от tf.train.Checkpointable и интегрированы с @tf.function , что позволяет непосредственно контрольной точке или экспортировать SavedModels из объектов Keras. Вы не обязательно должны использовать Keras' Model.fit API , чтобы воспользоваться преимуществами этих интеграций.

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

Объединить tf.data.Dataset s и tf.function

TensorFlow Datasets пакет ( tfds ) содержит утилиты для загрузки предопределенных наборов данных в качестве tf.data.Dataset объектов. Для этого примера, вы можете загрузить MNIST набора данных с помощью tfds :

datasets, info = tfds.load(name='mnist', with_info=True, as_supervised=True)
mnist_train, mnist_test = datasets['train'], datasets['test']

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

  • Измените масштаб каждого изображения.
  • Перемешайте примеры.
  • Собирайте партии изображений и этикеток.
BUFFER_SIZE = 10 # Use a much larger value for real code
BATCH_SIZE = 64
NUM_EPOCHS = 5


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

  return image, label

Чтобы пример был кратким, обрежьте набор данных, чтобы получить только 5 пакетов:

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

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))
2021-09-22 22:13:17.284138: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.

Используйте обычную итерацию Python для перебора обучающих данных, которые умещаются в памяти. В противном случае, tf.data.Dataset это лучший способ для потоковой подготовки данных с диска. Datasets являются итерируемыми (не итераторы) , и работают так же , как и другие итерируемый Python в нетерпеливом исполнении. Вы можете в полной мере использовать набор данных асинхронной предварительной загрузки / потоковой функции, окружив свой код в tf.function , который заменяет Python итерации с аналогичными операциями графа с использованием Autograph.

@tf.function
def train(model, dataset, optimizer):
  for x, y in dataset:
    with tf.GradientTape() as tape:
      # training=True is only needed if there are layers with different
      # behavior during training versus inference (e.g. Dropout).
      prediction = model(x, training=True)
      loss = loss_fn(prediction, y)
    gradients = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))

Если вы используете Keras Model.fit API, вам не придется беспокоиться о наборе данных итерации.

model.compile(optimizer=optimizer, loss=loss_fn)
model.fit(dataset)

Используйте обучающие циклы Keras

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

К преимуществам этих методов можно отнести:

  • Они принимают 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)
])

# Model is the full model w/o custom layers
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              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 [==============================] - 9s 9ms/step - loss: 1.5774 - accuracy: 0.5063
Epoch 2/5
2021-09-22 22:13:26.932626: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
5/5 [==============================] - 0s 5ms/step - loss: 0.4498 - accuracy: 0.9125
Epoch 3/5
2021-09-22 22:13:27.323101: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
5/5 [==============================] - 0s 5ms/step - loss: 0.2929 - accuracy: 0.9563
Epoch 4/5
2021-09-22 22:13:27.717803: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
5/5 [==============================] - 0s 5ms/step - loss: 0.2055 - accuracy: 0.9875
Epoch 5/5
2021-09-22 22:13:28.088985: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
5/5 [==============================] - 0s 5ms/step - loss: 0.1669 - accuracy: 0.9937
2021-09-22 22:13:28.458529: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
5/5 [==============================] - 0s 3ms/step - loss: 1.6056 - accuracy: 0.6500
Loss 1.6056102514266968, Accuracy 0.6499999761581421
2021-09-22 22:13:28.956635: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.

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

Если модели Keras работают на вас, но вам нужно больше гибкости и контроля над этапом обучения или внешними циклами обучения, вы можете реализовать свои собственные этапы обучения или даже целые циклы обучения. Смотрите руководство Keras по настройке fit , чтобы узнать больше.

Вы также можете реализовать многие вещи , как tf.keras.callbacks.Callback .

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

Стандартный цикл обучения состоит из трех шагов:

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

Помнить:

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

Нет необходимости запускать инициализаторы переменных или добавлять зависимости ручного управления. tf.function обрабатывает автоматические зависимости управления и инициализации переменных на создание для вас.

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)
])

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

@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)
2021-09-22 22:13:29.878252: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
Finished epoch 0
2021-09-22 22:13:30.266807: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
Finished epoch 1
2021-09-22 22:13:30.626589: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
Finished epoch 2
2021-09-22 22:13:31.040058: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
Finished epoch 3
Finished epoch 4
2021-09-22 22:13:31.417637: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.

Воспользуйтесь tf.function с потоком управления Python

tf.function обеспечивает способ преобразования управляющего потоком данных-зависимые в графе-режиме , как эквиваленты tf.cond и tf.while_loop .

Одно обычное место, где появляется поток управления, зависящий от данных, - это модели последовательности. tf.keras.layers.RNN обертывания клетки РНН, что позволяет вам статически или динамически развертываться повторения. В качестве примера вы можете повторно реализовать динамическую развертку следующим образом.

class DynamicRNN(tf.keras.Model):

  def __init__(self, rnn_cell):
    super(DynamicRNN, self).__init__(self)
    self.cell = rnn_cell

  @tf.function(input_signature=[tf.TensorSpec(dtype=tf.float32, shape=[None, None, 3])])
  def call(self, input_data):

    # [batch, time, features] -> [time, batch, features]
    input_data = tf.transpose(input_data, [1, 0, 2])
    timesteps =  tf.shape(input_data)[0]
    batch_size = tf.shape(input_data)[1]
    outputs = tf.TensorArray(tf.float32, timesteps)
    state = self.cell.get_initial_state(batch_size = batch_size, dtype=tf.float32)
    for i in tf.range(timesteps):
      output, state = self.cell(input_data[i], state)
      outputs = outputs.write(i, output)
    return tf.transpose(outputs.stack(), [1, 0, 2]), state
lstm_cell = tf.keras.layers.LSTMCell(units = 13)

my_rnn = DynamicRNN(lstm_cell)
outputs, state = my_rnn(tf.random.normal(shape=[10,20,3]))
print(outputs.shape)
(10, 20, 13)

Прочитайте tf.function руководство для получения дополнительной информации.

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

Метрики и потери являются объекты , которые работают охотно и в tf.function s.

Объект потери вызываемый, и ожидает ( y_true , y_pred ) в качестве аргументов:

cce = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
cce([[1, 0]], [[-1.0,3.0]]).numpy()
4.01815

Используйте метрики для сбора и отображения данных

Вы можете использовать tf.metrics агрегировать данные и tf.summary для входа резюме и перенаправить его к писателю , используя менеджер контекста. Резюме выбрасываются непосредственно к писателю , который означает , что вы должны обеспечить step значение в callsite.

summary_writer = tf.summary.create_file_writer('/tmp/summaries')
with summary_writer.as_default():
  tf.summary.scalar('loss', 0.1, step=42)

Используйте tf.metrics для агрегированных данных до их регистрации в качестве резюме. Показатели с отслеживанием состояния; они накапливают значения и возвращают совокупный результат при вызове result методы (например, Mean.result ). Очистить накопила значение с Model.reset_states .

def train(model, optimizer, dataset, log_freq=10):
  avg_loss = tf.keras.metrics.Mean(name='loss', dtype=tf.float32)
  for images, labels in dataset:
    loss = train_step(model, optimizer, images, labels)
    avg_loss.update_state(loss)
    if tf.equal(optimizer.iterations % log_freq, 0):
      tf.summary.scalar('loss', avg_loss.result(), step=optimizer.iterations)
      avg_loss.reset_states()

def test(model, test_x, test_y, step_num):
  # training=False is only needed if there are layers with different
  # behavior during training versus inference (e.g. Dropout).
  loss = loss_fn(model(test_x, training=False), test_y)
  tf.summary.scalar('loss', loss, step=step_num)

train_summary_writer = tf.summary.create_file_writer('/tmp/summaries/train')
test_summary_writer = tf.summary.create_file_writer('/tmp/summaries/test')

with train_summary_writer.as_default():
  train(model, optimizer, dataset)

with test_summary_writer.as_default():
  test(model, test_x, test_y, optimizer.iterations)

Визуализируйте сгенерированные сводки, указав TensorBoard на каталог сводных журналов:

tensorboard --logdir /tmp/summaries

Используйте tf.summary API для записи кратких данных для визуализации в TensorBoard. Для получения дополнительной информации, прочитайте tf.summary руководства .

# Create the metrics
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))
  # Update the metrics
  loss_metric.update_state(total_loss)
  accuracy_metric.update_state(labels, predictions)


for epoch in range(NUM_EPOCHS):
  # Reset the metrics
  loss_metric.reset_states()
  accuracy_metric.reset_states()

  for inputs, labels in train_data:
    train_step(inputs, labels)
  # Get the metric results
  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))
2021-09-22 22:13:32.370558: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
Epoch:  0
  loss:     0.143
  accuracy: 0.997
2021-09-22 22:13:32.752675: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
Epoch:  1
  loss:     0.119
  accuracy: 0.997
2021-09-22 22:13:33.122889: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
Epoch:  2
  loss:     0.106
  accuracy: 0.997
2021-09-22 22:13:33.522935: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
Epoch:  3
  loss:     0.089
  accuracy: 1.000
Epoch:  4
  loss:     0.079
  accuracy: 1.000
2021-09-22 22:13:33.899024: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.

Названия метрик Keras

Модели Keras единообразны в обращении с названиями метрик. Когда вы передаете строку в списке показателей, что точная строка используется в качестве метрики - й name . Эти имена отображаются в объекте истории возвращенного model.fit , и в журналах передаются keras.callbacks . устанавливается в строку, которую вы передали в списке показателей.

model.compile(
    optimizer = tf.keras.optimizers.Adam(0.001),
    loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics = ['acc', 'accuracy', tf.keras.metrics.SparseCategoricalAccuracy(name="my_accuracy")])
history = model.fit(train_data)
5/5 [==============================] - 1s 5ms/step - loss: 0.0962 - acc: 0.9969 - accuracy: 0.9969 - my_accuracy: 0.9969
2021-09-22 22:13:34.802566: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset  will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
history.history.keys()
dict_keys(['loss', 'acc', 'accuracy', 'my_accuracy'])

Отладка

Используйте активное выполнение для пошагового выполнения кода для проверки форм, типов данных и значений. Некоторые API - интерфейсы, такие как tf.function , tf.keras и т.д. предназначены для использования в выполнение графика, производительности и портативности. При отладке, использование tf.config.run_functions_eagerly(True) , чтобы использовать нетерпеливое выполнение внутри этого кода.

Например:

@tf.function
def f(x):
  if x > 0:
    import pdb
    pdb.set_trace()
    x = x + 1
  return x

tf.config.run_functions_eagerly(True)
f(tf.constant(1))
f()
-> x = x + 1
(Pdb) l
  6     @tf.function
  7     def f(x):
  8       if x > 0:
  9         import pdb
 10         pdb.set_trace()
 11  ->     x = x + 1
 12       return x
 13
 14     tf.config.run_functions_eagerly(True)
 15     f(tf.constant(1))
[EOF]

Это также работает в моделях Keras и других API, которые поддерживают активное выполнение:

class CustomModel(tf.keras.models.Model):

  @tf.function
  def call(self, input_data):
    if tf.reduce_mean(input_data) > 0:
      return input_data
    else:
      import pdb
      pdb.set_trace()
      return input_data // 2


tf.config.run_functions_eagerly(True)
model = CustomModel()
model(tf.constant([-2, -4]))
call()
-> return input_data // 2
(Pdb) l
 10         if tf.reduce_mean(input_data) > 0:
 11           return input_data
 12         else:
 13           import pdb
 14           pdb.set_trace()
 15  ->       return input_data // 2
 16
 17
 18     tf.config.run_functions_eagerly(True)
 19     model = CustomModel()
 20     model(tf.constant([-2, -4]))

Примечания:

Не держите tf.Tensors в ваших объектах

Эти тензорные объекты могут создаваться либо получить в tf.function или в нетерпеливом контексте, и эти тензоры ведут себя по- разному. Всегда используйте tf.Tensor с только для промежуточных значений.

Для отслеживания состояния, используйте tf.Variable s , поскольку они всегда пригодные для использования обоих контекстов. Прочитайте tf.Variable руководство , чтобы узнать больше.

Ресурсы и дополнительная литература

  • Прочитайте TF2 руководства и учебники , чтобы узнать больше о том , как использовать TF2.

  • Если вы ранее использовали TF1.x, настоятельно рекомендуется перенести свой код на TF2. Прочитайте руководства по миграции , чтобы узнать больше.