In [ ]:
#@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.
|
|
|
Note: Вся информация в этом разделе переведена с помощью русскоговорящего Tensorflow сообщества на общественных началах. Поскольку этот перевод не является официальным, мы не гарантируем что он на 100% аккуратен и соответствует официальной документации на английском языке. Если у вас есть предложение как исправить этот перевод, мы будем очень рады увидеть pull request в tensorflow/docs репозиторий GitHub. Если вы хотите помочь сделать документацию по Tensorflow лучше (сделать сам перевод или проверить перевод подготовленный кем-то другим), напишите нам на docs-ru@tensorflow.org list.
В 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.
В этом руководстве рассматриваются несколько примеров преобразования кода TensorFlow 1.x в TensorFlow 2.0. Эти изменения позволят вашему коду воспользоваться преимуществами оптимизации производительности и упрощенных вызовов API.
В каждом случае паттерн следующий:
tf.Session.run
Каждый вызов tf.Session.run
нужо заменить функцией Python.
feed_dict
и tf.placeholder
s становятся аргументами функции.fetches
становится возвращаемым значением функции.Вы можете пройти пошагово и отладить функцию, используя стандартные инструменты Python, такие как pdb
.
Когда вы убедитесь, что функция работает, добавьте декораторtf.function
чтобы она работала эффективно в режиме графа. Смотри Руководство Autograph чтобы узнать больше о том, как это работает.
Используйте tf.Variable
вместо tf.get_variable
.
Каждый variable_scope
может быть сконвертирован в объект Python. Как правило это будет что-то из:
tf.keras.layers.Layer
tf.keras.Model
tf.Module
Если вам нужны свести списки переменных (как например tf.Graph.get_collection(tf.GraphKeys.VARIABLES)
), используйте аттрибуты .variables
и .trainable_variables
объектов Layer
и Model
.
Эти классы Layer
и Model
реализуют несколько других свойств которые устраняют необходимость глобальных коллекций.
Смотри руководства keras для подробностей.
Предупреждение: Многие символы tf.compat.v1
неявно используют глобальные коллекции.
Используйте API наиболее высокого уровня который работает в вашем случае. Предпочтите tf.keras.Model.fit
построению своего собственного обучающего цикла.
Эти высокоуровневые функции управляют большим количеством низкоуровневых деталей которые могут быть легко упущены если вы пишете собственный обучающий цикл. Например, они автоматически собирают потери регуляризации и устанавливают аргумент training = True
при вызове модели.
Используйте наборы данных tf.data
для входных данных. Эти объекты эффективны, выразительны и хорошо интегрированы с tensorflow.
Их можно передать напрямую в метод tf.keras.Model.fit
.
model.fit(dataset, epochs=5)
Их можно напрямую итерировать в стандартном Python:
for example_batch, label_batch in dataset:
break
In [ ]:
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]})
В сконвертированном коде:
forward
все еще определяет вычисления.sess.run
заменен вызовом forward
tf.function
может быть добавлен для производительности.
In [ ]:
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)
In [ ]:
out_b = forward([0,1])
regularizer = tf.keras.regularizers.l2(0.04)
reg_loss = regularizer(W)
Модуль 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)
tf.keras.Sequential
. (Для более сложных моделей см. пользовательские слои и модели, и функциональный API.)tf.layers
в tf.keras.layers
.Большинство аргументов остались прежними. Но обратите внимание на различия:
training
передается моделью каждому слою при его запуске.model
(вводный x
) больше нет. Это связано с тем, что слои объекта отделяют построение модели от вызова модели.Также заметьте что:
tf.contrib
, у них больше изменений аргументов чем у остальных.tf.losses.get_regularization_loss
больше не возращают эти значения, что может нарушить ваши циклы обучения.
In [ ]:
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))
In [ ]:
train_out = model(train_data, training=True)
print(train_out)
In [ ]:
test_out = model(test_data, training=False)
print(test_out)
In [ ]:
# Здесь все обучаемые переменные.
len(model.trainable_variables)
In [ ]:
# Здесь потери регуляризации.
model.losses
Существующий код часто смешивает низкоуровневые 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
. Смотрите руководство для деталей.
In [ ]:
# Создайте пользовательский слой для части модели
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
In [ ]:
custom_layer = CustomLayer()
print(custom_layer([1]).numpy())
print(custom_layer([1], training=True).numpy())
In [ ]:
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
Создайте переменные модели в конструкторе или def build()
используя self.add_weight()
.
build
у вас есть доступ к размерности входных данных, так что создайте веса с совпадающими размерностями.tf.keras.layers.Layer.add_weight
позволяет Keras отслеживать переменные и потери регуляризации.Не храните tf.Tensors
в своих объектах.
tf.function
либо в контексте eager, и эти тензоры ведут себя по-другому.tf.Variable
s для состояния, их всегда можно использовать из обеих контекстовtf.Tensors
это только промежуточные значения.Большое количество старого 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
каждый в свой собственный слойtf.layers
имеют разные имена аргументов и значения по умолчанию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
:
In [ ]:
datasets, info = tfds.load(name='mnist', with_info=True, as_supervised=True)
mnist_train, mnist_test = datasets['train'], datasets['test']
Затем приготовим данные для обучения:
In [ ]:
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:
In [ ]:
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)
In [ ]:
image_batch, label_batch = next(iter(train_data))
Если вам не нужен низкоуровневый коноль процесса обучения модели, рекомендуется использовать встроенные в Keras методы fit
, evaluate
и predict
. Эти методы обеспечивают единый интерфейс обучения модели независимо от реализации (sequential, functional или sub-classed).
Преимущества этих методов включают:
tf.data.Datasets
tf.distribute
для обучения на нескольких устройствах.tf.keras.callbacks.TensorBoard
и пользовательские коллбеки.Приведем пример обучения модели с ипользованием Dataset
. (Подробнее о том как это работает смотри тьюториалы.)
In [ ]:
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))
Если обучающий шаг модели 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
для корректного вычисления.
Чтобы продолжить обучение вышеуказанной модели:
In [ ]:
# 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]))
Если вам нужны большая гибкость и контроль, вы можете получить их реализовав собственный цикл обучения. Есть три шага:
tf.data.Dataset
чтобы получить пакеты примеров.tf.GradientTape
чтобы собрать градиенты.tf.keras.optimizer
чтобы применить обновления весов к переменным модели.Помните:
training
в метод call
подклассов слоев и моделей.training
.Обратите внимание на упрощения относительно v1:
tf.function
действующих как в eager mode.
In [ ]:
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)
В TensorFlow 2.0, метрики являются объектами. Метрики работают и eagerly и в tf.function
. Объекты-метрики обладают следующими методами:
update_state()
— добавить новые наблюденияresult()
— получить текущий результат метрики при данных наблюдаемых значенияхreset_states()
— очистить все наблюдения.Объект сам является вызываемым. Вызов обновляет состояние новыми наблюдениями, как и с update_state
, и возвращает новый результат метрики
Вам не нужно вручную инициализировать переменные метрики, и, поскольку у TensorFlow 2.0 автоматическое управление зависимостями, вам не нужно беспокоиться и об этом.
В приведенном ниже коде используется метрика для отслеживания среднего значения потерь, наблюдаемых в пользовательском цикле обучения.
In [ ]:
# Создайте метрики
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))
TensorFlow 2.0 использует контрольные точки основанные на объектах.
Контрольные точки в старом стиле основанные на именах по-прежнему могут быть загружены, если вы осторожны с ними. В процессе конвертации кода могут измениться имена переменных, но есть обходные пути.
Самый простой подход - согласовать имена новой модели с именами в контрольной точке.:
name
который вы можете установить.name
, который они устанавливают в качестве префикса для своих переменных.tf.name_scope
может использоваться для установки префиксов имен переменных. Это сильно отличается от tf.variable_scope
. Он влияет только на имена и не отслеживает переменные и их переиспользование.Если это не работает для вашего случая, попробуйте функцию tf.compat.v1.train.init_from_checkpoint
. Она принимает аргумент assignment_map
, который определяет соответствие старых и новых имен.
Примечание: В отличие от основанных на объектах контрольных точек, которые могут [отложить загрузку] (checkpoint.ipynb#loading_mechanics), основанные на именах контрольных точек требуют, чтобы при вызове функции были созданы все переменные. Некоторые модели откладывают создание переменных до тех пор, пока вы не вызовете build
или не запустите модель на пакете данных.
In [ ]:
# Определим 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)
Есть некоторые отличия в том, как построить ваши оценщики в TensorFlow 2.0.
Мы рекомендуем вам определить модель используя Keras, потом используйте утилиту tf.keras.model_to_estimator
для преобразования вашей модели в оценщика. Нижеприведенный код показывает как использовать эту утилиту когда создаешь и обучаешь оценщик.
In [ ]:
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')
])
In [ ]:
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)
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
, иллюстрируя все эти проблемы.
In [ ]:
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)
Готовые оценщики из семейств tf.estimator.DNN*
, tf.estimator.Linear*
и tf.estimator.DNNLinearCombined*
все еще поддерживаются в TensorFlow 2.0 API, однако, некоторые аргументы изменились:
input_layer_partitioner
: Убрано в 2.0.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
.optimizer
, dnn_optimizer
и linear_optimizer
: эти аргументы обновились до tf.keras.optimizers
вместо tf.compat.v1.train.Optimizer
. Для переноса вышеуказанных изменений:
input_layer_partitioner
миграция не требуется поскольку Стратегия распределения
обработает это автоматически в TF 2.0.loss_reduction
, проверьте tf.keras.losses.Reduction
для поддерживаемых опций.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.
Следующее демонстрирует отличия TensorFlow 1.x и TensorFlow 2.0.
In [ ]:
# Создайте shape и выберите index
i = 0
shape = tf.TensorShape([16, None, 256])
shape
Если у вас есть это в TF 1.x:
value = shape[i].value
Сделайте это в TF 2.0:
In [ ]:
value = shape[i]
value
Если у вас есть это в TF 1.x:
for dim in shape:
value = dim.value
print(value)
TСделайте это в TF 2.0:
In [ ]:
for value in shape:
print(value)
Если у вас есть это в 1.x (Или используется любой другой метод размерности):
dim = shape[i]
dim.assert_is_compatible_with(other_dim)
Сделайте это в TF 2.0:
In [ ]:
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) # или любой другой метод размерности
In [ ]:
shape = tf.TensorShape(None)
if shape:
dim = shape.dims[i]
dim.is_compatible_with(other_dim) # или любой другой метод размерности
Булево значение tf.TensorShape
является True
если ранг известен, False
в противном случае.
In [ ]:
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))) # Тензор неизвестного ранга.
В TensorFlow 2.0 есть несколько других поведенческих изменений, с которыми вы можете столкнуться.
TensorFlow 2.0 создает по умолчанию ResourceVariables
, а не RefVariables
.
ResourceVariables
закрыты для записи, и обеспечивают лучшие гарантии согласовенности.
use_resource = False
конструкторуtf.Variable
.Реализация control flow была упрощена, поэтому в TensorFlow 2.0 создаются другие графы.
Общий процесс следующий:
tf.keras
или tf.estimator
там где вы можете.Для преобразования кода в идиоматический TensorFlow 2.0 требуется небольшая работа, но каждое изменение приводит к: