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.

Обзор Keras

Note: Данный раздел переведён с помощью русскоязычного сообщества Tensorflow на общественных началах. Поскольку перевод не является официальным, мы не гарантируем, что он на 100% точен и соответствует официальной документации на английском языке. Если у вас есть предложения по исправлению перевода, мы будем очень рады увидеть pull request в репозиторий tensorflow/docs-l10n на GitHub. Если вы хотите помочь сделать документацию по Tensorflow лучше (выполнить перевод или проверить перевод, подготовленный кем-то другим), напишите нам на docs-ru@tensorflow.org list.

Это руководство даст вам основы для начала работы с Keras. Чтение займет 10 минут.

Импортируйте tf.keras

tf.keras является реализацией TensorFlow спецификации Keras API. Это высокоуровневый API для построения и обучения моделей включающий первоклассную поддержку для TensorFlow-специфичной функциональности, такой как eager execution, конвейеры tf.data, и Estimators. tf.keras делает использование TensorFlow проще не жертвуя при этом гибкостью и производительностью.

Для начала, импортируйте tf.keras как часть установки вашей TensorFlow:


In [ ]:
import tensorflow as tf

from tensorflow import keras

tf.keras может выполнять любой Keras-совместимый код, но имейте ввиду:

  • Версия tf.keras в последнем релизе TensorFlow может отличаться от последней версии keras в PyPI. Проверьте tf.keras.__version__.
  • При сохранении весоа моделей, tf.keras делает это по умолчанию в формате checkpoint. Передайте параметр save_format='h5' для использования HDF5 (или добавьте к имени файла расширение .h5).

Постройте простую модель

Последовательная модель

В Keras, вы собираете слои (layers) для построения моделей (models). Модель это (обычно) граф слоев. Наиболее распространенным видом модели является стек слоев: модель tf.keras.Sequential.

Построение простой полносвязной сети (т.е. многослойного перцептрона):


In [ ]:
from tensorflow.keras import layers

model = tf.keras.Sequential()
# Добавим полносвязный слой с 64 узлами к модели:
model.add(layers.Dense(64, activation='relu'))
# Добавим другой слой:
model.add(layers.Dense(64, activation='relu'))
# Добавим слой softmax с 10 выходами:
model.add(layers.Dense(10, activation='softmax'))

Вы можете найти короткий, но полный пример того, как использовать последовательные (Sequential) модели здесь.

Чтобы узнать о построении более сложных чем последовательные (Sequential), см:

Настройте слои

Доступно много разновидностей слоев tf.keras.layers. Большинство из них используют общий конструктор аргументов:

  • activation: Установка функции активации для слоя. В этом параметре указывается имя встроенной функции или вызываемый объект. У параметра нет значения по умолчанию.
  • kernel_initializer И bias_initializer: Схемы инициализации создающие веса слоя (ядро и сдвиг). В этом параметре может быть имя или вызываемый объект. По умолчанию используется инициализатор "Glorot uniform".
  • kernel_regularizer и bias_regularizer: Схемы регуляризации добавляемые к весам слоя (ядро и сдвиг), такие как L1 или L2 регуляризации. По умолчанию регуляризация не устанавливается.

Следующие примеры слоев tf.keras.layers.Dense используют аргументы конструктора:


In [ ]:
# Создать слой с сигмоидой:
layers.Dense(64, activation='sigmoid')
# Или:
layers.Dense(64, activation=tf.keras.activations.sigmoid)

# Линейный слой с регуляризацией L1 с коэфициентом 0.01 примененной к матрице ядра:
layers.Dense(64, kernel_regularizer=tf.keras.regularizers.l1(0.01))

# Линейный слой с регуляризацией L2 с коэффициентом 0.01 примененной к вектору сдвига:
layers.Dense(64, bias_regularizer=tf.keras.regularizers.l2(0.01))

# Линейный слой с ядром инициализированным случайной ортогональной матрицей:
layers.Dense(64, kernel_initializer='orthogonal')

# Линейный слой с вектором сдвига инициализированным значениями 2.0:
layers.Dense(64, bias_initializer=tf.keras.initializers.Constant(2.0))

Обучение и оценка

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

После того как модель сконструирована, настройте процесс ее обучения вызовом метода compile:


In [ ]:
model = tf.keras.Sequential([
# Добавляем полносвязный слой с 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.keras.optimizers.Adam(0.01),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

tf.keras.Model.compile принимает три важных аргумента:

  • optimizer: Этот объект определяет процедуру обучения. Передайте в него экземпляры оптимизатора из модуля tf.keras.optimizers, такие как tf.keras.optimizers.Adam или tf.keras.optimizers.SGD. Если вы просто хотите использовать значения по умолчанию, вы также можете указать оптимизаторы ключевыми словами, такими как 'adam' или 'sgd'.
  • loss: Это функция которая минимизируется в процессе обучения. Среди распространенных вариантов mean square error (mse), categorical_crossentropy, и binary_crossentropy. Функции потерь указываются по имени или по передаче вызываемого объекта из модуля tf.keras.losses.
  • metrics: Используются для мониторинга обучения. Это строковые имена или вызываемые объекты из модуля tf.keras.metrics.
  • Кроме того, чтобы быть уверенным, что модель обучается и оценивается eagerly, проверьте что вы передали компилятору параметр run_eagerly=True

Далее посмотрим несколько примеров конфигурации модели для обучения:


In [ ]:
# Сконфигурируем модель для регрессии со среднеквадратичной ошибкой.
model.compile(optimizer=tf.keras.optimizers.Adam(0.01),
              loss='mse',       # срееднеквадратичная ошибка
              metrics=['mae'])  # средняя абсолютная ошибка

# Сконфигурируем модель для категориальной классификации.
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.01),
              loss=tf.keras.losses.CategoricalCrossentropy(),
              metrics=[tf.keras.metrics.CategoricalAccuracy()])

Обучение на данных NumPy

Для небольших датасетов используйте помещающиеся в память массивы NumPy для обучения и оценки модели. Модель "обучается" на тренировочных даннных используя метод 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, модель разбивает данные на меньшие блоки (batches) и итерирует по этим блокам во время обучения. Это число указывает размер каждого блока данных. Помните, что последний блок может быть меньшего размера если общее число записей не делится на размер партии.
  • validation_data: При прототипировании модели вы хотите легко отслеживать её производительность на валидационных данных. Передача с этим аргументом кортежа входных данных и меток позволяет модели отопражать значения функции потерь и метрики в режиме вывода для передаваемых данных в конце каждой эпохи.

Вот пример использования 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))

Обучение с использованием наборов данных tf.data

Используйте Datasets API для масштабирования больших баз данных или обучения на нескольких устройствах. Передайте экземпляр tf.data.Dataset в метод fit:


In [ ]:
# Создает экземпляр учебного датасета:
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32)

model.fit(dataset, epochs=10)

Поскольку Dataset выдает данные пакетами, этот кусок кода не требует аргумента batch_size.

Датасеты могут быть также использованы для валидации:


In [ ]:
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32)

val_dataset = tf.data.Dataset.from_tensor_slices((val_data, val_labels))
val_dataset = val_dataset.batch(32)

model.fit(dataset, epochs=10,
          validation_data=val_dataset)

Оценка и предсказание

Методы tf.keras.Model.evaluate и tf.keras.Model.predict могут использовать данные NumPy и tf.data.Dataset.

Вот так можно оценить потери в режиме вывода и метрики для предоставленных данных:


In [ ]:
# С массивом Numpy
data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))

model.evaluate(data, labels, batch_size=32)

# С датасетом
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32)

model.evaluate(dataset)

А вот как предсказать вывод последнего уровня в режиме вывода для предоставленных данных, в виде массива NumPy:


In [ ]:
result = model.predict(data, batch_size=32)
print(result.shape)

Полное руководство по обучению и оценке модели, включая описание написания пользовательских циклов обучения с нуля, см. в [руководстве по обучению и оценке] (./ train_and_evaluate.ipynb).

Построение сложных моделей

The Functional API

Модель tf.keras.Sequential это простой стек слоев с помощью которого нельзя представить произвольную модель. Используйте Keras functional API для построения сложных топологий моделей, таких как:

  • Модели с несколькими входами,
  • Модели с несколькими выходами,
  • Модели с общими слоями (один и тот же слой вызывается несколько раз),
  • Модели с непоследовательными потоками данных (напр. остаточные связи).

Построение модели с functional API работает следующим образом:

  1. Экземпляр слоя является вызываемым и возвращает тензор.
  2. Входные и выходные тензоры используются для определения экземпляра tf.keras.Model
  3. Эта модель обучается точно так же как и Sequential модель.

Следующий пример использует functional 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)

# Шаг компиляции определяет конфигурацию обучения.
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# Обучение  за 5 эпох
model.fit(data, labels, batch_size=32, epochs=5)

Сабклассинг моделей

Создайте полностью настраиваемую модель с помощью сабклассинга tf.keras.Model и определения вашего собственного прямого распространения. Создайте слои в методе __init__ и установите их как атрибуты экземпляра класса. Определите прямое распространение в методе call.

Сабклассинг модели особенно полезен когда включен eager execution, поскольку он позволяет написать прямое распространение императивно.

Примечание: если вам нужно чтобы ваша модель всегда выполнялась императивно, вы можете установить dynamic=True когда вызываете конструктор super.

Ключевой момент: Используйте правильный API для работы. Хоть сабклассинг модели обеспечивает гибкость, за нее приходится платить большей сложностью и большими возможностями для пользовательских ошибок. Если это возможно выбирайте functional 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)

Создайте экземпляр класса новой модели:


In [ ]:
model = MyModel(num_classes=10)

# Шаг компиляции определяет конфигурацию обучения.
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# Обучение за 5 эпох.
model.fit(data, labels, batch_size=32, epochs=5)

Пользовательские слои

Создайте пользовательский слой сабклассингом tf.keras.layers.Layer и реализацией следующих методов:

  • __init__: Опционально определите подслои которые будут использоваться в этом слое.
  • build: Создайте веса слоя. Добавьте веса при помощи метода add_weight.
  • call: Определите прямое распространение.
  • Опционально, слой может быть сериализован реализацией метода get_config и метода класса from_config.

Ниже пример пользовательского слоя который осуществляет умножение матрицы (matmul) поданной на вход с матрицей ядра:


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):
    # Создадим обучаемую весовую переменную для этого слоя.
    self.kernel = self.add_weight(name='kernel',
                                  shape=(input_shape[1], self.output_dim),
                                  initializer='uniform',
                                  trainable=True)

  def call(self, inputs):
    return tf.matmul(inputs, self.kernel)

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

# Шаг компиляции определяет конфигурацию обучения
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# Обучение за 5 эпох.
model.fit(data, labels, batch_size=32, epochs=5)

Узнайте больше о создании новых слоев и моделей с нуля с помощью сабклассинга в Руководстве написания слоев и моделей с нуля.

Колбеки

Колбек это объект переданный модели чтобы кастомизировать и расширить ее поведение во время обучения. Вы можете написать свой пользовательский колбек или использовать встроенный tf.keras.callbacks который включает:

  • tf.keras.callbacks.ModelCheckpoint: Сохранение контрольных точек модели за регулярные интервалы.
  • tf.keras.callbacks.LearningRateScheduler: Динамичное изменение шага обучения.
  • 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))

Сохранение и восстановление

Сохранение только значений весов

Сохраните и загрузите веса модели с помощью tf.keras.Model.save_weights:


In [ ]:
model = tf.keras.Sequential([
layers.Dense(64, activation='relu', input_shape=(32,)),
layers.Dense(10, activation='softmax')])

model.compile(optimizer=tf.keras.optimizers.Adam(0.001),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

In [ ]:
# Сохраним веса в файл TensorFlow Checkpoint
model.save_weights('./weights/my_model')

# Восстановим состояние модели,
# для этого необходима модель с такой же архитектурой.
model.load_weights('./weights/my_model')

По умолчанию веса модели сохраняются в формате TensorFlow checkpoint. Веса могут быть также сохранены в формате 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')

Узнайте больше о сохранении и сериализации моделей Keras в руководстве по сохранению и сериализации моделей.

Eager execution

Eager execution это императивное программирование среда которая выполняет операции немедленно. Это не требуется для Keras, но поддерживается tf.keras и полезно для проверки вашей программы и отладки.

Все строящие модели API tf.keras совместимы eager execution. И хотя могут быть использованы Sequential и functional API, eager execution особенно полезно при сабклассировании модели и построении пользовательских слоев — эти API требуют от вас написание прямого распространения в виде кода (вместо API которые создают модели путем сборки существующих слоев).

См руководство eager execution для примеров использования моделей Keras с пользовательскими циклами обучения и tf.GradientTape. Вы можете также найти полный коротки пример тут.

Распределение

Множественные GPU

tf.keras модели можно запускать на множестве GPU с использованием tf.distribute.Strategy. Этот API обеспечивает распределенное обучение на нескольких GPU практически без изменений в существующем коде.

На данный момент, tf.distribute.MirroredStrategy единственная поддерживаемая стратегия распределения. MirroredStrategy выполняет репликацию в графах с синхронным обучением используя all-reduce на одной машине. Для использования distribute.Strategy , вложите инсталляцию оптимизатора, конструкцию и компиляцию модели в Strategy's .scope(), затем обучите модель.

Следующий пример распределяет tf.keras.Model между множеством GPU на одной машине.

Сперва определим модель внутри области распределенной стратегии:


In [ ]:
strategy = tf.distribute.MirroredStrategy()

with strategy.scope():
  model = tf.keras.Sequential()
  model.add(layers.Dense(16, activation='relu', input_shape=(10,)))
  model.add(layers.Dense(1, activation='sigmoid'))

  optimizer = tf.keras.optimizers.SGD(0.2)

  model.compile(loss='binary_crossentropy', optimizer=optimizer)

model.summary()

Затем обучим модель на данных как обычно:


In [ ]:
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.shuffle(buffer_size=1024).batch(32)

model.fit(dataset, epochs=1)