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.
Keras - это высокоуровневый API для создания моделей глубокого обучения. Он используется для быстрого создания прототипов, сложных исследований, а также для создания приложений. Три ключевые примущества Keras API:
tf.keras
- это реализация спецификации Keras API{:.external} в TensorFlow.
Это высокоуровневый API для построения
моделей глубокого обучения с первоклассной поддержкой
функционала TensorFlow, например eager execution,
конвееры tf.data
и алгоритмы оценки Estimators.
tf.keras
делает TensorFlow простым в использовании, не теряя в гибкости и производительности.
Чтобы начать, просто импортируй tf.keras
после TensorFlow в начале кода:
In [ ]:
# Используй pyyaml если будешь сохранять в формате YAML
!pip install pyyaml
In [ ]:
import tensorflow.compat.v1 as tf
from tensorflow.keras import layers
print(tf.VERSION)
print(tf.keras.__version__)
tf.keras
может запускать любой совместимый с Keras код, но тем не менее помни:
tf.keras
в последнем релизе TensorFlow может быть не самой
последнией версией keras
, доступной в PyPI. Всегда проверяй версию при помощи tf.keras.__version__
tf.keras
по умолчанию
сохраняет их в формате контрольной точки. Используй save_format='h5'
чтобы сохранять как HDF5В Keras мы используем слои для построения моделей. Обычно модель - это граф, состоящий из нескольких слоев. Самый распространенный тип модели это стэк идущих друг за другом слоев - последовательная модель tf.keras.Sequential
.
Для начала давай построим простую полносвязную сеть (или многослойный перцептрон):
In [ ]:
model = tf.keras.Sequential()
# Добавим в нашу модель слой Dense из 64 блоков:
model.add(layers.Dense(64, activation='relu'))
# И еще один:
model.add(layers.Dense(64, activation='relu'))
# Также добавим слой softmax с 10 выводящими блоками:
model.add(layers.Dense(10, activation='softmax'))
Существует много разных слоев tf.keras.layers
с общими параметрами конфигурации:
activation
: Устанавливает функцию активации для данного слоя. Этот параметр должен указываться в имени встроенной функции или использоваться как вызываемый объект. По умолчанию активация не используетсяkernel_initializer
и bias_initializer
: Инициализация, которая создает веса данного слоя (ядро kernel и смещение bias). Этот параметр используется как имя или вызываемый объект. По умолчанию используется инициализатор "Glorot uniform"
kernel_regularizer
и bias_regularizer
: Регуляризация, которая применяется к весам слоя (ядро kernel и смещение bias), например L1 или L2. По умолчанию не используетсяСледующий код используется для построения tf.keras.layers.Dense
с настройкой конфигурации каждого слоя:
In [ ]:
# Создаем сигмоидный слой:
layers.Dense(64, activation='sigmoid')
# Или:
layers.Dense(64, activation=tf.sigmoid)
# Линейный слой с регуляризацией L1 с коэффицентом 0.01 примененная к ядру матрицы:
layers.Dense(64, kernel_regularizer=tf.keras.regularizers.l1(0.01))
# Линейный слой с регуляризацией L2 с коэффицентом 0.01 примененная к вектору смещения (bias):
layers.Dense(64, bias_regularizer=tf.keras.regularizers.l2(0.01))
# Линейный слой с ядром, инициализированным в случайной прямоугольный матрице:
layers.Dense(64, kernel_initializer='orthogonal')
# Линейный слой с вектором смещения, инициализированным с коэффицентом 2:
layers.Dense(64, bias_initializer=tf.keras.initializers.constant(2.0))
In [ ]:
model = tf.keras.Sequential([
# Добавим в нашу модель слой `Dense` из 64 блоков:
layers.Dense(64, activation='relu', input_shape=(32,)),
# И еще один:
layers.Dense(64, activation='relu'),
# Также добавим слой softmax с 10 выводящими блоками:
layers.Dense(10, activation='softmax')])
model.compile(optimizer=tf.train.AdamOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
У tf.keras.Model.compile
есть три важных аргумента:
optimizer
: Этот объект определяет процедуру обучения. Мы будем использовать оптимизаторы из модуля tf.train
, например такие как tf.train.AdamOptimizer
, tf.train.RMSPropOptimizer
и tf.train.GradientDescentOptimizer
loss
: Эта функция минимизации для решения задач оптимизации. Самыми распространенными выборами этого аргумента являются среднеквадратическое отклонение (mse
), categorical_crossentropy
, и binary_crossentropy
. Функции потерь обозначены по имени или используются как вызываемые объекты из модуля tf.keras.losses
metrics
: Используются для наблюдения за процессом обучения. Используются как строки или вызываемые объекты модуля tf.keras.metrics
Ниже пример конфигурации модели для обучения:
In [ ]:
# Настраиваем регрессию модели, используем среднеквадратическое отклонение
model.compile(optimizer=tf.train.AdamOptimizer(0.01),
loss='mse', # среднеквадратическое отклонение
metrics=['mae']) # средняя абсолютная ошибка
# Настраиваем модель для классификации по категориям
model.compile(optimizer=tf.train.RMSPropOptimizer(0.01),
loss=tf.keras.losses.categorical_crossentropy,
metrics=[tf.keras.metrics.categorical_accuracy])
При работе с небольшими датасетами мы будем использовать загружаемые в память массивы данных NumPy{:.external} для обучения и оценки моделей. Модель будет "подстраиваться" под тренировочные данные при помощи метода fit
:
In [ ]:
import numpy as np
data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))
model.fit(data, labels, epochs=10, batch_size=32)
У tf.keras.Model.fit
есть три важных аргумента:
epochs
: Процесс обучения структурирован по эпохам. Эпоха означает один проход по всему набору входных данных, который происходит небольшими порциями в батчахbatch_size
: Когда мы используем массивы NumPy модель делит данные на небольшие батчи и затем выполняет указанное количество проходов. Это число определяет размер батча. Помни, что последний батч может быть меньше если общее количество образцов данных не делится на размер батчаvalidation_data
: Когда мы строим прототип модели, мы хотим легко наблюдать за ее точностью на проверочных данных. При помощи данного аргумента - обычно кортеж или метка - модель будет отображать потери и статистику в режиме выводов inference для прошедших через модель данных в конце каждой эпохиВот пример использования validation_data
:
In [ ]:
import numpy as np
data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))
val_data = np.random.random((100, 32))
val_labels = np.random.random((100, 10))
model.fit(data, labels, epochs=10, batch_size=32,
validation_data=(val_data, val_labels))
Чтобы обучать модель на больших датасетах или на нескольких устройствах мы можем воспользоваться Datasets API. Просто добавь tf.data.Dataset
к методу fit
:
In [ ]:
# Инициализируем пробную инстанцию датасета:
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32)
dataset = dataset.repeat()
# Не забудь указать количество шагов в каждой эпохе `steps_per_epoch` при использовании метода `fit`
model.fit(dataset, epochs=10, steps_per_epoch=30)
Таким образом, метод fit
использует аргумент steps_per_epoch
- это количество шагов обучения, которые модель должна сделать прежде, чем перейти на следующую эпоху. Поскольку Dataset
принимает батчи данных, то в этом примере кода нам не требуется указывать размер батча в batch_size
.
Также dataset
можно использовать для проверки точности модели:
In [ ]:
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32).repeat()
val_dataset = tf.data.Dataset.from_tensor_slices((val_data, val_labels))
val_dataset = val_dataset.batch(32).repeat()
model.fit(dataset, epochs=10, steps_per_epoch=30,
validation_data=val_dataset,
validation_steps=3)
In [ ]:
data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))
model.evaluate(data, labels, batch_size=32)
model.evaluate(dataset, steps=30)
Для предсказания вывода последнего слоя как массив NumPy, используй следующий код:
In [ ]:
result = model.predict(data, batch_size=32)
print(result.shape)
Последовательная модель tf.keras.Sequential
представляет из себя обычное наложение или стек слоев, которые не могут представлять произвольные модели. Используй
функциональный API Keras {:.external} для построения комплексных топологий моделей, например таких как:
Построение модели при помощи функционального API выглядит следующим образом:
tf.keras.Model
используем входные и выводящие тензорыSequential
Следующий пример показывает как использовать функциональный API для построения простой полносвязной сети:
In [ ]:
# Возвращает тензор-"заполнитель", который мы используем в качестве примера
inputs = tf.keras.Input(shape=(32,))
# Вызываемый на тензор слой, возвращает тензор
x = layers.Dense(64, activation='relu')(inputs)
x = layers.Dense(64, activation='relu')(x)
predictions = layers.Dense(10, activation='softmax')(x)
Обозначим вход и вывод данных нашей модели:
In [ ]:
model = tf.keras.Model(inputs=inputs, outputs=predictions)
# При помощи метода `compile` настраиваем конфигурацию обучения
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
# Тренируем модель в течение 5 эпох
model.fit(data, labels, batch_size=32, epochs=5)
Также ты можешь создать модель с нуля при помощи подклассов в tf.keras.Model
и определения собственных прямых проходов. Создавай слои в методе __init__
и установи их как атрибуты класса. Прямой проход должен быть указан в методе call
.
Создание подклассов моделей особенно полезно, когда активирован eager execution, так как прямой проход в этом случае всегда будет записан.
Ключевой момент: всегда используй правильный API для решения конкретной задачи. Поскольку создание подклассов модели предполагает определенную гибкость, эта гибкость осложняет определение структуры и может повлечь больше ошибок у пользователя. Если возможно, то всегда старайся использовать функциональный API.
Смотри следующий пример кода, в котором мы будем использовать подклассы tf.keras.Model
и собственный прямой проход:
In [ ]:
class MyModel(tf.keras.Model):
def __init__(self, num_classes=10):
super(MyModel, self).__init__(name='my_model')
self.num_classes = num_classes
# Здесь определим слои
self.dense_1 = layers.Dense(32, activation='relu')
self.dense_2 = layers.Dense(num_classes, activation='sigmoid')
def call(self, inputs):
# А здесь укажем прямой проход,
# используя указанные выше слои (в `__init__`).
x = self.dense_1(inputs)
return self.dense_2(x)
def compute_output_shape(self, input_shape):
# Если ты хочешь использовать подклассы модели
# в функциональном стиле, тогда эта функция будет переписана
# во время запуска кода. В остальных случаях этот метод необязателен.
shape = tf.TensorShape(input_shape).as_list()
shape[-1] = self.num_classes
return tf.TensorShape(shape)
Укажем класс новой модели:
In [ ]:
model = MyModel(num_classes=10)
# При помощи метода `compile` настраиваем конфигурацию обучения
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
# Обучаем в течение 5 эпох
model.fit(data, labels, batch_size=32, epochs=5)
Чтобы создать свой собственный слой при помощи подклассов tf.keras.layers.Layer
нам потребуются следующие методы:
build
: Создает веса слоя. Чтобы добавить веса в модель используй метод add_weight
call
: Определяет прямой проходcompute_output_shape
: Определяет как вычислить выводящую форму слоя для данной входной формыget_config
и метода класса from_config
Вот пример использования нового слоя, в котором мы использовали matmul
входа с матрицей ядра kernel
:
In [ ]:
class MyLayer(layers.Layer):
def __init__(self, output_dim, **kwargs):
self.output_dim = output_dim
super(MyLayer, self).__init__(**kwargs)
def build(self, input_shape):
shape = tf.TensorShape((input_shape[1], self.output_dim))
# Создаем обучаемую переменную весов для этого слоя
self.kernel = self.add_weight(name='kernel',
shape=shape,
initializer='uniform',
trainable=True)
# Обязательно вызови метод `build` в конце
super(MyLayer, self).build(input_shape)
def call(self, inputs):
return tf.matmul(inputs, self.kernel)
def compute_output_shape(self, input_shape):
shape = tf.TensorShape(input_shape).as_list()
shape[-1] = self.output_dim
return tf.TensorShape(shape)
def get_config(self):
base_config = super(MyLayer, self).get_config()
base_config['output_dim'] = self.output_dim
return base_config
@classmethod
def from_config(cls, config):
return cls(**config)
Теперь создадим модель, используя наш новый слой:
In [ ]:
model = tf.keras.Sequential([
MyLayer(10),
layers.Activation('softmax')])
# При помощи метода `compile` настраиваем конфигурацию обучения
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
# Обучаем в течение 5 эпох
model.fit(data, labels, batch_size=32, epochs=5)
Функция обратного вызова callback
- это объект, который передается модели для обработки и расширения ее поведения во время обучения. Ты можешь написать свою собственную функцию callback, или использовать готовые tf.keras.callbacks
в которые входят:
tf.keras.callbacks.ModelCheckpoint
: Сохраняет контрольные точки твоей модели через заданный интервалtf.keras.callbacks.LearningRateScheduler
: Замедляет темп обучения learning rate
для получения лучших результатов точностиtf.keras.callbacks.EarlyStopping
: Останавливает обучение как только точность перестает увеличиватьсяtf.keras.callbacks.TensorBoard
: Следит за поведением модели при помощи TensorBoardЧтобы использовать tf.keras.callbacks.Callback
просто передай его в метод fit
своей модели:
In [ ]:
callbacks = [
# Прерывает обучение если потери при проверке `val_loss` перестают
# уменьшаться после 2 эпох
tf.keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'),
# Записываем логи TensorBoard в папку `./logs`
tf.keras.callbacks.TensorBoard(log_dir='./logs')
]
model.fit(data, labels, batch_size=32, epochs=5, callbacks=callbacks,
validation_data=(val_data, val_labels))
In [ ]:
model = tf.keras.Sequential([
layers.Dense(64, activation='relu'),
layers.Dense(10, activation='softmax')])
model.compile(optimizer=tf.train.AdamOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
In [ ]:
# Сохраняем веса в контрольную точку формата TensorFlow
model.save_weights('./weights/my_model')
# Восстанавливаем состояние модели,
# требуется использование модели с точно такой же архитектурой
model.load_weights('./weights/my_model')
По умолчанию, веса модели сохраняются в формате контрольой точки TensorFlow. Веса также могут быть сохранены в формате Keras HDF5, который является стандартным в бэкенд структуре Keras:
In [ ]:
# Сохраняем веса в файл HDF5
model.save_weights('my_model.h5', save_format='h5')
# Загружаем текущее состояние модели
model.load_weights('my_model.h5')
Конфигурация модели также может быть сохранена: такой метод сериализирует архитектуру модели без сохранения весов.
Сохраненная конфигурация можеть быть загружена и инициализирована как оригинальная модель, даже без кода изначальной модели.
Keras поддерживает форматы сериализации данных JSON и YAML:
In [ ]:
# Сериализация модели в формат JSON
json_string = model.to_json()
json_string
In [ ]:
import json
import pprint
pprint.pprint(json.loads(json_string))
Давай воссоздадим только что инициализированную модель из JSON:
In [ ]:
fresh_model = tf.keras.models.model_from_json(json_string)
Сериализация модели в формат YAML требуется установки pyyaml
до импорта TensorFlow:
In [ ]:
yaml_string = model.to_yaml()
print(yaml_string)
Восстановим модель из формата YAML:
In [ ]:
fresh_model = tf.keras.models.model_from_yaml(yaml_string)
Важно: модели с подклассами не могут быть сериализированы, потому что их архитектура определяется кодом Python в методе call
.
In [ ]:
# Создаем простую модель
model = tf.keras.Sequential([
layers.Dense(10, activation='softmax', input_shape=(32,)),
layers.Dense(10, activation='softmax')
])
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(data, labels, batch_size=32, epochs=5)
# Сохраняем модель целиком в один файл формата HDF5
model.save('my_model.h5')
# Восстаналиваем ту же самую модель, включая веса и оптимизатор
model = tf.keras.models.load_model('my_model.h5')
Eager execution - это окружение императивного программирования, в котором все операции вычисляются мгновенно. В нем не требуется Keras, однако tf.keras
поддерживается и оказывается весьма полезен для проверки программы и отладки кода.
Все API tf.keras
для построения моделей совместимы с eager execution. В то время как функциональный API и Sequential
могут быть использованы и здесь, наибольшее преимущество получат модели с подклассами и модели с собственными слоями - это именно те API, в которых тебе необходимо указать прямой проход в виде кода (вместо тех API, которые создают модели посредством сборки существующих слоев).
Смотри Руководство по eager execution для ознакомления с примерами использования моделей Keras с уникальными циклами обучения tf.GradientTape
.
API Estimators используется для обучения моделей в распределенном окружении. Он необходим для решения задач распределенного обучения на больших датасетах например для экспорта модели в продакшен.
tf.keras.Model
может обучаться с API tf.estimator
посредством конвертации модели в объект tf.estimator.Estimator
при помощи tf.keras.estimator.model_to_estimator
. Читай больше в статье Создание Estimators из моделей Keras.
In [ ]:
model = tf.keras.Sequential([layers.Dense(10,activation='softmax'),
layers.Dense(10,activation='softmax')])
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
estimator = tf.keras.estimator.model_to_estimator(model)
Совет: используй eager execution для отладки функций входа Estimator и проверки данных.
Модели tf.keras
могут обучаться на нескольких GPU при помощи
tf.contrib.distribute.DistributionStrategy
. Этот API обеспечивает распределенное обучение на нескольких GPU почти без изменений основного кода модели.
В настоящее время tf.contrib.distribute.MirroredStrategy
является единственной поддерживаемой стратегией распределенного обучения. MirroredStrategy
выполняет внутриграфную репликацию с синхронным обучением, используя функцию all-reduce на одном устройстве. Чтобы использовать DistributionStrategy
вместе с Keras, конвертируй модель tf.keras.Model
в tf.estimator.Estimator
при помощи tf.keras.estimator.model_to_estimator
, а затем обучи получившийся estimator.
В следующем примере мы посмотрим как распределить tf.keras.Model
на нескольких GPU на одном устройстве.
Для начала определим простую модель:
In [ ]:
model = tf.keras.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10,)))
model.add(layers.Dense(1, activation='sigmoid'))
optimizer = tf.train.GradientDescentOptimizer(0.2)
model.compile(loss='binary_crossentropy', optimizer=optimizer)
model.summary()
Затем определим функцию загрузки и обработки данных. Функция Input_fn
возвращает объект tf.data.Dataset
, который используется для распределения данных на нескольких устройствах, где каждый GPU обрабатывает свой входящий батч.
In [ ]:
def input_fn():
x = np.random.random((1024, 10))
y = np.random.randint(2, size=(1024, 1))
x = tf.cast(x, tf.float32)
dataset = tf.data.Dataset.from_tensor_slices((x, y))
dataset = dataset.repeat(10)
dataset = dataset.batch(32)
return dataset
Далее, создадим tf.estimator.RunConfig
и передадим аргумент train_distribute
к tf.contrib.distribute.MirroredStrategy
. При создании
MirroredStrategy
ты можешь определить список устройств или передать аргумент num_gpus
с заданным количеством GPU для обучения. По умолчанию используются все доступные GPU как в следующем примере:
In [ ]:
strategy = tf.contrib.distribute.MirroredStrategy()
config = tf.estimator.RunConfig(train_distribute=strategy)
Конвертируем модель Keras в tf.estimator.Estimator
:
In [ ]:
keras_estimator = tf.keras.estimator.model_to_estimator(
keras_model=model,
config=config,
model_dir='/tmp/model_dir')
Наконец, обучаем Estimator
, передав аргументы input_fn
и steps
:
In [ ]:
keras_estimator.train(input_fn=input_fn, steps=10)