Сохраните дату! Google I / O возвращается 18-20 мая Зарегистрируйтесь сейчас
Эта страница переведена с помощью Cloud Translation API.
Switch to English

Сохранить и загрузить модели

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

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

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

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

Параметры

Существуют разные способы сохранения моделей TensorFlow в зависимости от используемого API. В этом руководстве используется tf.keras , высокоуровневый API для создания и обучения моделей в TensorFlow. Для других подходов см. Руководство по сохранению и восстановлению TensorFlow или « Сохранение в нетерпении» .

Настраивать

Установки и импорт

Установите и импортируйте TensorFlow и зависимости:

pip install -q pyyaml h5py  # Required to save models in HDF5 format
import os

import tensorflow as tf
from tensorflow import keras

print(tf.version.VERSION)
2.4.1

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

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

(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
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step

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

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

# Define a simple sequential model
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)
  ])

  model.compile(optimizer='adam',
                loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
                metrics=[tf.metrics.SparseCategoricalAccuracy()])

  return model

# Create a basic model instance
model = create_model()

# Display the model's architecture
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 512)               401920    
_________________________________________________________________
dropout (Dropout)            (None, 512)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 10)                5130      
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________

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

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

Использование обратного вызова контрольной точки

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

checkpoint_path = "training_1/cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)

# Create a callback that saves the model's weights
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
                                                 save_weights_only=True,
                                                 verbose=1)

# Train the model with the new callback
model.fit(train_images, 
          train_labels,  
          epochs=10,
          validation_data=(test_images, test_labels),
          callbacks=[cp_callback])  # Pass callback to training

# This may generate warnings related to saving the state of the optimizer.
# These warnings (and similar warnings throughout this notebook)
# are in place to discourage outdated usage, and can be ignored.
Epoch 1/10
32/32 [==============================] - 1s 14ms/step - loss: 1.6718 - sparse_categorical_accuracy: 0.4717 - val_loss: 0.7284 - val_sparse_categorical_accuracy: 0.7810

Epoch 00001: saving model to training_1/cp.ckpt
Epoch 2/10
32/32 [==============================] - 0s 4ms/step - loss: 0.4771 - sparse_categorical_accuracy: 0.8706 - val_loss: 0.5380 - val_sparse_categorical_accuracy: 0.8350

Epoch 00002: saving model to training_1/cp.ckpt
Epoch 3/10
32/32 [==============================] - 0s 4ms/step - loss: 0.2798 - sparse_categorical_accuracy: 0.9223 - val_loss: 0.4721 - val_sparse_categorical_accuracy: 0.8490

Epoch 00003: saving model to training_1/cp.ckpt
Epoch 4/10
32/32 [==============================] - 0s 4ms/step - loss: 0.1965 - sparse_categorical_accuracy: 0.9597 - val_loss: 0.4343 - val_sparse_categorical_accuracy: 0.8550

Epoch 00004: saving model to training_1/cp.ckpt
Epoch 5/10
32/32 [==============================] - 0s 4ms/step - loss: 0.1510 - sparse_categorical_accuracy: 0.9667 - val_loss: 0.4308 - val_sparse_categorical_accuracy: 0.8660

Epoch 00005: saving model to training_1/cp.ckpt
Epoch 6/10
32/32 [==============================] - 0s 4ms/step - loss: 0.1140 - sparse_categorical_accuracy: 0.9845 - val_loss: 0.4052 - val_sparse_categorical_accuracy: 0.8680

Epoch 00006: saving model to training_1/cp.ckpt
Epoch 7/10
32/32 [==============================] - 0s 4ms/step - loss: 0.0908 - sparse_categorical_accuracy: 0.9838 - val_loss: 0.4120 - val_sparse_categorical_accuracy: 0.8660

Epoch 00007: saving model to training_1/cp.ckpt
Epoch 8/10
32/32 [==============================] - 0s 4ms/step - loss: 0.0632 - sparse_categorical_accuracy: 0.9936 - val_loss: 0.4178 - val_sparse_categorical_accuracy: 0.8600

Epoch 00008: saving model to training_1/cp.ckpt
Epoch 9/10
32/32 [==============================] - 0s 4ms/step - loss: 0.0526 - sparse_categorical_accuracy: 0.9991 - val_loss: 0.3975 - val_sparse_categorical_accuracy: 0.8680

Epoch 00009: saving model to training_1/cp.ckpt
Epoch 10/10
32/32 [==============================] - 0s 4ms/step - loss: 0.0391 - sparse_categorical_accuracy: 1.0000 - val_loss: 0.4106 - val_sparse_categorical_accuracy: 0.8660

Epoch 00010: saving model to training_1/cp.ckpt
<tensorflow.python.keras.callbacks.History at 0x7f54502f6128>

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

os.listdir(checkpoint_dir)
['checkpoint', 'cp.ckpt.data-00000-of-00001', 'cp.ckpt.index']

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

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

# Create a basic model instance
model = create_model()

# Evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Untrained model, accuracy: {:5.2f}%".format(100 * acc))
32/32 - 0s - loss: 2.3199 - sparse_categorical_accuracy: 0.1070
Untrained model, accuracy: 10.70%

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

# Loads the weights
model.load_weights(checkpoint_path)

# Re-evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
32/32 - 0s - loss: 0.4106 - sparse_categorical_accuracy: 0.8660
Restored model, accuracy: 86.60%

Варианты обратного вызова контрольной точки

Обратный вызов предоставляет несколько вариантов для предоставления уникальных имен для контрольных точек и настройки частоты контрольных точек.

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

# Include the epoch in the file name (uses `str.format`)
checkpoint_path = "training_2/cp-{epoch:04d}.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)

batch_size = 32

# Create a callback that saves the model's weights every 5 epochs
cp_callback = tf.keras.callbacks.ModelCheckpoint(
    filepath=checkpoint_path, 
    verbose=1, 
    save_weights_only=True,
    save_freq=5*batch_size)

# Create a new model instance
model = create_model()

# Save the weights using the `checkpoint_path` format
model.save_weights(checkpoint_path.format(epoch=0))

# Train the model with the new callback
model.fit(train_images, 
          train_labels,
          epochs=50, 
          batch_size=batch_size, 
          callbacks=[cp_callback],
          validation_data=(test_images, test_labels),
          verbose=0)
WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.iter
WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.beta_1
WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.beta_2
WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.decay
WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.learning_rate
WARNING:tensorflow:A checkpoint was restored (e.g. tf.train.Checkpoint.restore or tf.keras.Model.load_weights) but not all checkpointed values were used. See above for specific issues. Use expect_partial() on the load status object, e.g. tf.train.Checkpoint.restore(...).expect_partial(), to silence these warnings, or use assert_consumed() to make the check explicit. See https://www.tensorflow.org/guide/checkpoint#loading_mechanics for details.

Epoch 00005: saving model to training_2/cp-0005.ckpt

Epoch 00010: saving model to training_2/cp-0010.ckpt

Epoch 00015: saving model to training_2/cp-0015.ckpt

Epoch 00020: saving model to training_2/cp-0020.ckpt

Epoch 00025: saving model to training_2/cp-0025.ckpt

Epoch 00030: saving model to training_2/cp-0030.ckpt

Epoch 00035: saving model to training_2/cp-0035.ckpt

Epoch 00040: saving model to training_2/cp-0040.ckpt

Epoch 00045: saving model to training_2/cp-0045.ckpt

Epoch 00050: saving model to training_2/cp-0050.ckpt
<tensorflow.python.keras.callbacks.History at 0x7f544fe8ffd0>

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

os.listdir(checkpoint_dir)
['cp-0035.ckpt.index',
 'cp-0010.ckpt.data-00000-of-00001',
 'cp-0025.ckpt.index',
 'cp-0035.ckpt.data-00000-of-00001',
 'checkpoint',
 'cp-0015.ckpt.data-00000-of-00001',
 'cp-0050.ckpt.data-00000-of-00001',
 'cp-0040.ckpt.data-00000-of-00001',
 'cp-0005.ckpt.index',
 'cp-0005.ckpt.data-00000-of-00001',
 'cp-0020.ckpt.data-00000-of-00001',
 'cp-0045.ckpt.index',
 'cp-0010.ckpt.index',
 'cp-0045.ckpt.data-00000-of-00001',
 'cp-0030.ckpt.index',
 'cp-0000.ckpt.index',
 'cp-0015.ckpt.index',
 'cp-0025.ckpt.data-00000-of-00001',
 'cp-0030.ckpt.data-00000-of-00001',
 'cp-0000.ckpt.data-00000-of-00001',
 'cp-0020.ckpt.index',
 'cp-0050.ckpt.index',
 'cp-0040.ckpt.index']
latest = tf.train.latest_checkpoint(checkpoint_dir)
latest
'training_2/cp-0050.ckpt'

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

# Create a new model instance
model = create_model()

# Load the previously saved weights
model.load_weights(latest)

# Re-evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
32/32 - 0s - loss: 0.4639 - sparse_categorical_accuracy: 0.8770
Restored model, accuracy: 87.70%

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

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

  • Один или несколько осколков, содержащих веса вашей модели.
  • Индексный файл, который указывает, какие веса хранятся в каком сегменте.

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

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

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

# Save the weights
model.save_weights('./checkpoints/my_checkpoint')

# Create a new model instance
model = create_model()

# Restore the weights
model.load_weights('./checkpoints/my_checkpoint')

# Evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.iter
WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.beta_1
WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.beta_2
WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.decay
WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.learning_rate
WARNING:tensorflow:A checkpoint was restored (e.g. tf.train.Checkpoint.restore or tf.keras.Model.load_weights) but not all checkpointed values were used. See above for specific issues. Use expect_partial() on the load status object, e.g. tf.train.Checkpoint.restore(...).expect_partial(), to silence these warnings, or use assert_consumed() to make the check explicit. See https://www.tensorflow.org/guide/checkpoint#loading_mechanics for details.
32/32 - 0s - loss: 0.4639 - sparse_categorical_accuracy: 0.8770
Restored model, accuracy: 87.70%

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

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

Вся модель может быть сохранена в двух разных форматах файлов ( SavedModel и HDF5 ). Формат SavedModel - это формат файла по умолчанию в TF2.x. Однако модели можно сохранять в формате HDF5 . Более подробная информация о сохранении целых моделей в двух форматах файлов описана ниже.

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

* Пользовательские объекты (например, подклассы моделей или слои) требуют особого внимания при сохранении и загрузке. См. Раздел « Сохранение пользовательских объектов » ниже.

Формат SavedModel

Формат SavedModel - еще один способ сериализации моделей. Модели, сохраненные в этом формате, могут быть восстановлены с помощью tf.keras.models.load_model и совместимы с TensorFlow Serving. В руководстве SavedModel подробно рассказывается о том, как обслуживать / проверять SavedModel. В следующем разделе показаны шаги по сохранению и восстановлению модели.

# Create and train a new model instance.
model = create_model()
model.fit(train_images, train_labels, epochs=5)

# Save the entire model as a SavedModel.
!mkdir -p saved_model
model.save('saved_model/my_model')
Epoch 1/5
32/32 [==============================] - 0s 2ms/step - loss: 1.5348 - sparse_categorical_accuracy: 0.5511
Epoch 2/5
32/32 [==============================] - 0s 2ms/step - loss: 0.4735 - sparse_categorical_accuracy: 0.8777
Epoch 3/5
32/32 [==============================] - 0s 2ms/step - loss: 0.2538 - sparse_categorical_accuracy: 0.9408
Epoch 4/5
32/32 [==============================] - 0s 2ms/step - loss: 0.2100 - sparse_categorical_accuracy: 0.9483
Epoch 5/5
32/32 [==============================] - 0s 2ms/step - loss: 0.1559 - sparse_categorical_accuracy: 0.9679
INFO:tensorflow:Assets written to: saved_model/my_model/assets

Формат SavedModel - это каталог, содержащий двоичный файл protobuf и контрольную точку TensorFlow. Осмотрите каталог сохраненной модели:

# my_model directory
ls saved_model

# Contains an assets folder, saved_model.pb, and variables folder.
ls saved_model/my_model
my_model
assets  saved_model.pb  variables

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

new_model = tf.keras.models.load_model('saved_model/my_model')

# Check its architecture
new_model.summary()
Model: "sequential_5"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_10 (Dense)             (None, 512)               401920    
_________________________________________________________________
dropout_5 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_11 (Dense)             (None, 10)                5130      
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________

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

# Evaluate the restored model
loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)
print('Restored model, accuracy: {:5.2f}%'.format(100 * acc))

print(new_model.predict(test_images).shape)
32/32 - 0s - loss: 0.4454 - sparse_categorical_accuracy: 0.8500
Restored model, accuracy: 85.00%
(1000, 10)

Формат HDF5

Keras предоставляет базовый формат сохранения с использованием стандарта HDF5 .

# Create and train a new model instance.
model = create_model()
model.fit(train_images, train_labels, epochs=5)

# Save the entire model to a HDF5 file.
# The '.h5' extension indicates that the model should be saved to HDF5.
model.save('my_model.h5')
Epoch 1/5
32/32 [==============================] - 0s 2ms/step - loss: 1.6127 - sparse_categorical_accuracy: 0.5163
Epoch 2/5
32/32 [==============================] - 0s 2ms/step - loss: 0.4528 - sparse_categorical_accuracy: 0.8731
Epoch 3/5
32/32 [==============================] - 0s 2ms/step - loss: 0.2975 - sparse_categorical_accuracy: 0.9306
Epoch 4/5
32/32 [==============================] - 0s 2ms/step - loss: 0.2404 - sparse_categorical_accuracy: 0.9338
Epoch 5/5
32/32 [==============================] - 0s 2ms/step - loss: 0.1419 - sparse_categorical_accuracy: 0.9679

Теперь воссоздайте модель из этого файла:

# Recreate the exact same model, including its weights and the optimizer
new_model = tf.keras.models.load_model('my_model.h5')

# Show the model architecture
new_model.summary()
Model: "sequential_6"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_12 (Dense)             (None, 512)               401920    
_________________________________________________________________
dropout_6 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_13 (Dense)             (None, 10)                5130      
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________

Проверьте его точность:

loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)
print('Restored model, accuracy: {:5.2f}%'.format(100 * acc))
32/32 - 0s - loss: 0.4260 - sparse_categorical_accuracy: 0.8680
Restored model, accuracy: 86.80%

Keras сохраняет модели, проверяя их архитектуры. Этот прием спасает все:

  • Значения веса
  • Архитектура модели
  • Конфигурация обучения модели (что вы передаете .compile() )
  • Оптимизатор и его состояние, если таковое имеется (это позволяет перезапустить обучение с того места, где вы остановились)

Keras не может сохранить оптимизаторы v1.x (из tf.compat.v1.train ), поскольку они несовместимы с контрольными tf.compat.v1.train . Для оптимизаторов v1.x вам необходимо перекомпилировать модель после загрузки - потеря состояния оптимизатора.

Сохранение пользовательских объектов

Если вы используете формат SavedModel, вы можете пропустить этот раздел. Ключевое различие между HDF5 и SavedModel заключается в том, что HDF5 использует конфигурации объектов для сохранения архитектуры модели, а SavedModel сохраняет график выполнения. Таким образом, SavedModels может сохранять настраиваемые объекты, такие как подклассовые модели и настраиваемые слои, без необходимости использования исходного кода.

Чтобы сохранить пользовательские объекты в HDF5, необходимо сделать следующее:

  1. Определите в своем объекте метод get_config и, возможно, from_config класса from_config.
    • get_config(self) возвращает JSON-сериализуемый словарь параметров, необходимых для воссоздания объекта.
    • from_config(cls, config) использует конфигурацию, возвращенную из get_config для создания нового объекта. По умолчанию эта функция будет использовать конфиг в качестве инициализации kwargs ( return cls(**config) ).
  2. Передайте объект в аргумент custom_objects при загрузке модели. Аргументом должен быть словарь, сопоставляющий имя строкового класса с классом Python. Например, tf.keras.models.load_model(path, custom_objects={'CustomLayer': CustomLayer})

См. get_config « Написание слоев и моделей с нуля», где приведены примеры пользовательских объектов и get_config .

# 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.