Прогресс модели может быть сохранен в течение или после тренировки. Это означает, что обучение модели может быть возобновлено с того места, где оно было остановлено, избежав долгого времени повторной тренировки. Сохранение также означает, что вы можете поделиться своей моделью и другие могут воссоздать вашу работу. Во время публикации исследовательских моделей и техник большинство практиков машинного обучения делятся:
- кодом для создания модели
- тренировочными весами, или параметрами, для модели
Предоставление этих данных позволяет другим понять как модель работает и испробовать модель самим с новыми данными.
Опции
Существуют различные пути для сохранения TensorFlow моделей - в зависимости от API, который использовать. Это руководство использует tf.keras - высокоуровневое API для построения и тренировки моделей в TensorFlow.
Настройка
Получение примерного набора данных
Мы будем использовать MNIST набор данных для тренировки нашей модели и демонстрации сохраненных весов. Чтобы ускорить демонстрацию, используем только первые 1000 примеров:
from future import absolute_import, division, print_function
import os
import tensorflow as tf
from tensorflow import keras
tf.version
'1.9.0'
(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://s3.amazonaws.com/img-datasets/mnist.npz
11493376/11490434 [==============================] - 2s 0us/step
Определение модели
Построим простую модель, которую мы будем использовать для демонстрации сохранения и загрузки весов.
# Возвращает короткую последовательную модель (sequential model)
def create_model():
model = tf.keras.models.Sequential([
keras.layers.Dense(512, activation=tf.nn.relu, input_shape=(784,)),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer=tf.keras.optimizers.Adam(),
loss=tf.keras.losses.sparse_categorical_crossentropy,
metrics=['accuracy'])
return model
# Создание инстанса базовой модели
model = create_model()
model.summary()
_________________________________________________________________
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 - это колбек (callback) (функция обратного вызова), который выполняет эту задачу. Колбек принимает пару аргументов, чтобы сконфигурировать создание контрольных точек.
Использование колбека контрольных точек
Тренируем модель и передаем ей ModelCheckpoint колбек:
checkpoint_path = "training_1/cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
# Создаем колбек контрольной точки
cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
save_weights_only=True,
verbose=1)
model = create_model()
model.fit(train_images, train_labels, epochs = 10,
validation_data = (test_images,test_labels),
callbacks = [cp_callback]) # передаем колбек
Train on 1000 samples, validate on 1000 samples
Epoch 1/10
1000/1000 [==============================] - 0s 342us/step - loss: 1.1603 - acc: 0.6670 - val_loss: 0.6827 - val_acc: 0.7880
Epoch 00001: saving model to training_1/cp.ckpt
Epoch 2/10
1000/1000 [==============================] - 0s 129us/step - loss: 0.4071 - acc: 0.8860 - val_loss: 0.5841 - val_acc: 0.8110
Epoch 00002: saving model to training_1/cp.ckpt
Epoch 3/10
1000/1000 [==============================] - 0s 118us/step - loss: 0.2796 - acc: 0.9350 - val_loss: 0.4610 - val_acc: 0.8520
Epoch 00003: saving model to training_1/cp.ckpt
Epoch 4/10
1000/1000 [==============================] - 0s 121us/step - loss: 0.2025 - acc: 0.9570 - val_loss: 0.4324 - val_acc: 0.8610
Epoch 00004: saving model to training_1/cp.ckpt
Epoch 5/10
1000/1000 [==============================] - 0s 117us/step - loss: 0.1489 - acc: 0.9690 - val_loss: 0.4290 - val_acc: 0.8620
Epoch 00005: saving model to training_1/cp.ckpt
Epoch 6/10
1000/1000 [==============================] - 0s 127us/step - loss: 0.1194 - acc: 0.9780 - val_loss: 0.4143 - val_acc: 0.8700
Epoch 00006: saving model to training_1/cp.ckpt
Epoch 7/10
1000/1000 [==============================] - 0s 118us/step - loss: 0.0845 - acc: 0.9860 - val_loss: 0.4208 - val_acc: 0.8670
Epoch 00007: saving model to training_1/cp.ckpt
Epoch 8/10
1000/1000 [==============================] - 0s 118us/step - loss: 0.0648 - acc: 0.9910 - val_loss: 0.4078 - val_acc: 0.8680
Epoch 00008: saving model to training_1/cp.ckpt
Epoch 9/10
1000/1000 [==============================] - 0s 121us/step - loss: 0.0531 - acc: 0.9970 - val_loss: 0.4184 - val_acc: 0.8670
Epoch 00009: saving model to training_1/cp.ckpt
Epoch 10/10
1000/1000 [==============================] - 0s 121us/step - loss: 0.0391 - acc: 0.9960 - val_loss: 0.4185 - val_acc: 0.8640
Epoch 00010: saving model to training_1/cp.ckpt
Это создает единственную коллекцию файлов контрольных точек TensorFlow, которые обновляются в конце каждой эпохи:
!ls {checkpoint_dir}
checkpoint cp.ckpt.data-00000-of-00001 cp.ckpt.index
Создадим новую нетренированную модель. При восстановлении модели только из весов необходимо иметь модель точно с такой же архитектурой, как и модель, которой принадлежали веса. Ввиду того, что это та же самая архитектура, мы можем поделиться весами, несмотря на то, что это другой экземпляр модели.
Теперь перестроим свежую, нетренированную модель, и оценим ее на тестовом наборе. Нетренированная модель будет выполняться на случайных уровнях (~10% аккуратности):
model = create_model()
loss, acc = model.evaluate(test_images, test_labels)
print("Untrained model, accuracy: {:5.2f}%".format(100*acc))
1000/1000 [==============================] - 0s 105us/step
Untrained model, accuracy: 7.20%
Затем загрузим веса из контрольной точки и переоценим:
model.load_weights(checkpoint_path)
loss,acc = model.evaluate(test_images, test_labels)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
1000/1000 [==============================] - 0s 24us/step
Restored model, accuracy: 86.40%
Свойства колбека контрольной точки
Колбек предоставляет несколько свойств для задания уникальных имен для результирующих контрольных точек и нормализации частоты контрольных точек.
Натренируем новую модель и сохраним уникально названные контрольные точки каждые 5 эпох:
# включаем эпоху в название файла (используя str.format)
checkpoint_path = "training_2/cp-{epoch:04d}.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
cp_callback = tf.keras.callbacks.ModelCheckpoint(
checkpoint_path, verbose=1, save_weights_only=True,
# Сохраняем веса каждые 5 эпох.
period=5)
model = create_model()
model.fit(train_images, train_labels,
epochs = 50, callbacks = [cp_callback],
validation_data = (test_images,test_labels),
verbose=0)
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
Теперь посмотрим на результирующие контрольные точки (сортируя по дате изменения):
import pathlib
# Сортируем контрольные точки по времени изменения
checkpoints = pathlib.Path(checkpoint_dir).glob("*.index")
checkpoints = sorted(checkpoints, key=lambda cp:cp.stat().st_mtime)
checkpoints = [cp.with_suffix('') for cp in checkpoints]
latest = str(checkpoints[-1])
checkpoints
[PosixPath('training_2/cp-0030.ckpt'),
PosixPath('training_2/cp-0035.ckpt'),
PosixPath('training_2/cp-0040.ckpt'),
PosixPath('training_2/cp-0045.ckpt'),
PosixPath('training_2/cp-0050.ckpt')]
Следует отметить, что по умолчанию TensorFlow сохраняет только 5 наиболее недавних контрольных точек.
Для тестирования сбросим модель и загрузим последнюю контрольную точку:
model = create_model()
model.load_weights(latest)
loss, acc = model.evaluate(test_images, test_labels)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
1000/1000 [==============================] - 0s 82us/step
Restored model, accuracy: 87.80%
В какие файлы сохраняются контрольные точки
Код выше сохраняет веса в коллекцию отформатированных по контрольным точкам файлов, которые содержат только тренированные веса в бинарном формате. Контрольные точки содержат:
- Один или более осколков, которые содержат веса модели.
- Индексный файл, который отражает какие веса сохранены в каждом осколке.
Если модель была тренирована только на одной машине, будет присутствовать только один осколок с суффиксом: .data-00000-of-00001
Ручное сохранение весов
Выше было показано как загружать веса в модель.
Ручное сохранение весов настолько же просто, используйте Model.save_weights метод.
# Сохраняем веса
model.save_weights('./checkpoints/my_checkpoint')
# Восстанавливаем веса
model = create_model()
model.load_weights('./checkpoints/my_checkpoint')
loss,acc = model.evaluate(test_images, test_labels)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
1000/1000 [==============================] - 0s 59us/step
Restored model, accuracy: 87.80%
Сохранение модели целиком
Модель целиком может быть сохранена в файл, который содержит значения весов, конфигурацию модели, и конфигурацию оптимизатора. Это позволяет создавать контрольную точку модели и восстанавливать тренировку позже, с того же самомо места, без доступа к исходному коду.
Сохранение полностью функционирующих моделей в Keras очень удобно - можно загружать их в TensorFlow.js и затем тренировать и исполнять их в веб-браузере.
Keras предоставляет базовый формат сохранения, используя HDF5 стандарт. Для наших целей сохраненная модель может трактоваться как единый бинарный блоб (blob).
model = create_model()
model.fit(train_images, train_labels, epochs=5)
# Сохраняем модель целиком в HDF5 файле
model.save('my_model.h5')
Epoch 1/5
1000/1000 [==============================] - 0s 317us/step - loss: 1.1730 - acc: 0.6640
Epoch 2/5
1000/1000 [==============================] - 0s 109us/step - loss: 0.4257 - acc: 0.8790
Epoch 3/5
1000/1000 [==============================] - 0s 106us/step - loss: 0.2889 - acc: 0.9240
Epoch 4/5
1000/1000 [==============================] - 0s 104us/step - loss: 0.2171 - acc: 0.9390
Epoch 5/5
1000/1000 [==============================] - 0s 106us/step - loss: 0.1615 - acc: 0.9670
Теперь пересоздаем модель из этого файла:
# Пересоздаем ту же самую модель, включая веса и оптимизатор.
new_model = keras.models.load_model('my_model.h5')
new_model.summary()
_________________________________________________________________
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)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
1000/1000 [==============================] - 0s 78us/step
Restored model, accuracy: 86.60%
Эта техника сохраняет все:
- Значения весов
- Конфигурацию модели (архитектуру)
- Конфигурацию оптимизатора
Keras сохраняет модели, проверяя архитектуру. На данный момент не доступно сохранение TensorFlow оптимизаторов (из tf.train). При их использовании необходимо перекомпилировать модель после загрузки - при этом освобождается состояние оптимизатора.