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.

In [ ]:
#@title MIT License
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

Сохранение и загрузка моделей

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

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

  • кодом необходимым для создания модели, и
  • обученными весами, или параметрами модели

Публикация этих данных помогает другим понять как работает модель и попробовать ее самостоятельно с новыми данными.

Предупреждение: Будьте осторожны с ненадежным кодом — модели TensorFlow являются кодом. См. Безопасное использование TensorFlow для подробностей.

Варианты

Существуют различные способы сохранения моделей Tensorflow - зависит от API которое ты используешь. Это руководство использует tf.keras высокоуровневый API для построения и обучения моделей в TensorFlow. Для остальных подходов см. руководство TensorFlow сохранение и восстановление или Сохранение в eager.

Установка

Инсталляция и импорт

Установим и импортируем TensorFlow и зависимые библиотеки:


In [ ]:
!pip install pyyaml h5py  # Требуется для сохранения модели в формате HDF5

In [ ]:
import os

import tensorflow as tf
from tensorflow import keras

print(tf.version.VERSION)

Получите набор данных

Для демонстрации того как сохранять и загружать веса вы используете датасет MNIST. Для ускорения запусков используйте только первые 1000 примеров:


In [ ]:
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()

train_labels = train_labels[:1000]
test_labels = test_labels[:1000]

train_images = train_images[:1000].reshape(-1, 28 * 28) / 255.0
test_images = test_images[:1000].reshape(-1, 28 * 28) / 255.0

Определите модель

Начните с построения простой последовательной модели:


In [ ]:
# Определим простую последовательную модель
def create_model():
  model = tf.keras.models.Sequential([
    keras.layers.Dense(512, activation='relu', input_shape=(784,)),
    keras.layers.Dropout(0.2),
    keras.layers.Dense(10, activation='softmax')
  ])

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

  return model

# Создадим экземпляр базовой модели
model = create_model()

# Распечатаем архитектуру модели
model.summary()

Сохраните контрольные точки во время обучения

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

Использование коллбека контрольной точки (checkpoint callback)

Создайте коллбек tf.keras.callbacks.ModelCheckpoint который сохраняет веса только во время обучения:


In [ ]:
checkpoint_path = "training_1/cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)

# Создаем коллбек сохраняющий веса модели
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
                                                 save_weights_only=True,
                                                 verbose=1)

# Обучаем модель с новым коллбеком
model.fit(train_images, 
          train_labels,  
          epochs=10,
          validation_data=(test_images,test_labels),
          callbacks=[cp_callback])  # Pass callback to training

# Это может генерировать предупреждения относящиеся к сохранению состояния оптимизатора.
# Эти предупреждения (и подобные предупреждения в этом уроке)
# используются для предотвращения устаревшего использования и могут быть проигнорированы.

Это создаст единый набор файлов контрольных точек TensorFlow который обновляется в конце каждой эпохи:


In [ ]:
!ls {checkpoint_dir}

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

Сейчас восстановите свежую, необученную модель и оцените ее на тестовом наборе. Неподготовленная модель будет работать на уровне угадывания (точность ~ 10%):


In [ ]:
# Создайте экземпляр базовой модели
model = create_model()

# Оцените модель
loss, acc = model.evaluate(test_images,  test_labels, verbose=2)
print("Untrained model, accuracy: {:5.2f}%".format(100*acc))

Затем загрузите веса из чекпоинта и оцените снова:


In [ ]:
# Загрузим веса
model.load_weights(checkpoint_path)

# Оценим модель снова
loss,acc = model.evaluate(test_images,  test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))

Параметры коллбека контрольной точки

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

Обучите новую модель и сохраните по разному названные чекпоинты каждые пять эпох:


In [ ]:
# Добавим эпоху в имя файла (uses `str.format`)
checkpoint_path = "training_2/cp-{epoch:04d}.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)

# Создадим коллбек сохраняющий веса модели каждые 5 эпох
cp_callback = tf.keras.callbacks.ModelCheckpoint(
    filepath=checkpoint_path, 
    verbose=1, 
    save_weights_only=True,
    period=5)

# Создадим новый экземпляр модели
model = create_model()

# Сохраним веса используя формат `checkpoint_path` format
model.save_weights(checkpoint_path.format(epoch=0))

# Обучим модель с новым коллбеком
model.fit(train_images, 
              train_labels,
              epochs=50, 
              callbacks=[cp_callback],
              validation_data=(test_images,test_labels),
              verbose=0)

Сейчас посмотрите на получившиеся чекпоинты и выберите последний:


In [ ]:
! ls {checkpoint_dir}

In [ ]:
latest = tf.train.latest_checkpoint(checkpoint_dir)
latest

Замечание: базовый формат tensorflow сохраняет только 5 последних контрольных точек.

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


In [ ]:
# Создадим новый экземпляр модели
model = create_model()

# Загрузим предварительно сохраненные веса
model.load_weights(latest)

# Заново оценим модель
loss, acc = model.evaluate(test_images,  test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))

Что это за файлы?

Приведенный выше код хранит веса в коллекции checkpoint-отформатированных файлов, которые содержат только обученные веса в двоичном формате. Чекпоинты содержат:

  • Один или несколько разделов (shards) которые содержат веса вашей модели.
  • Индексный файл который указывает какие веса содрержатся в каждом из разделов.

Если Вы обучаете модель только на одной машине, у Вас будет один раздел с суффиксом: .data-00000-of-00001

Сохраните веса вручную

Вы уже видели как загрузить веса в модель. Ручное их сохранение так же просто с использованием метода Model.save_weights. По умолчанию tf.keras и save_weights в частности используют формат чекпоинтов TensorFlow с расширением .ckpt (сохранение в HDF5 с раширением .h5 рассмотренно в материале Сохранение и сериализация моделей guide):


In [ ]:
# Сохраним веса
model.save_weights('./checkpoints/my_checkpoint')

# Создадим новый экземпляр модели
model = create_model()

# Восстановим веса
model.load_weights('./checkpoints/my_checkpoint')

# Оценим модель
loss,acc = model.evaluate(test_images,  test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))

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

Модель и оптимизатор могут быть сохранены в файл который содержит и их состояние (веса и переменные) и конфигурацию модели. Это позволит Вам экспортировать модель так, чтобы она могла быть использована без доступа к исходному коду Python. Поскольку состояние оптимизатора восстановлено, вы можете продолжить обучение в точности с того места где остановились.

Сохранение полностью функциональной модели очень полезно - вы можете загрузить его в TensorFlow.js (HDF5, Сохраненная модель) и затем обучить и запустить ее в веб-браузере, или сконвертировать для исполнения в мобильных устройствах с использованием TensorFlow Lite (HDF5, Сохраненная модель)

Сохраните модель в файл HDF5

Keras также обеспечивает базовый формат сохранения с использованием стандарта HDF5. Для наших целей сохраненная модель может быть рассмотрена как единый двоичный blob:


In [ ]:
# Создадим новый экземпляр модели
model = create_model()

# Обучим модель
model.fit(train_images, train_labels, epochs=5)

# Сохраним всю модель в  HDF5 файл
model.save('my_model.h5')

Сейчас восстановим модель с того файла:


In [ ]:
# Восстановим в точности ту же модель, включая веса и оптимизатор
new_model = keras.models.load_model('my_model.h5')

# Покажем архитектуру модели
new_model.summary()

Проверим ее точность:


In [ ]:
loss, acc = new_model.evaluate(test_images,  test_labels, verbose=2)
print("Точность восстановленной модели: {:5.2f}%".format(100*acc))

Эта техника сохраняет все:

  • Значения весов
  • Конфигурацию модели (архитектуру)
  • Конфигурацию оптимизатора

Keras сохраняет модели путем проверки архитектуры. Сейчас Keras не может сохранять оптимизаторы TensorFlow (из tf.train). При их использовании вам нужно перекомпилировать модель после загрузки и вы потеряете текущее состояние оптимизатора.

Как и saved_model

Предупреждение: Этот метод сохранения модели tf.keras экспериментальный и может измениться в будущих версиях.

Постройте новую модель и затем обучите ее:


In [ ]:
model = create_model()

model.fit(train_images, train_labels, epochs=5)

Создайте saved_model, и поместите ее в папку с временной меткой с tf.keras.experimental.export_saved_model:


In [ ]:
import time
saved_model_path = "./saved_models/{}".format(int(time.time()))

tf.keras.experimental.export_saved_model(model, saved_model_path)
saved_model_path

Выведите на экран ваши сохраненные модели:


In [ ]:
!ls saved_models/

Загрузите свежую модель Keras из сохраненной модели:


In [ ]:
new_model = tf.keras.experimental.load_from_saved_model(saved_model_path)

# Проверим ее архитектуру
new_model.summary()

Запустите предсказания с восстановленной моделью:


In [ ]:
model.predict(test_images).shape

In [ ]:
# Модель должна быть скомпилирована перед использованием.
# Этот шаг не требуется если сохраненная модель только разворачивается.

new_model.compile(optimizer=model.optimizer,  #Оставляем загруженный оптимизатор
                  loss='sparse_categorical_crossentropy', 
                  metrics=['accuracy'])

# Evaluate the restored model
loss, acc = new_model.evaluate(test_images,  test_labels, verbose=2)
print("Точность восстановленной модели: {:5.2f}%".format(100*acc))