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
позволяет непрерывно сохранять модель как во время так и по окончанию обучения
Создайте коллбек 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-отформатированных файлов, которые содержат только обученные веса в двоичном формате. Чекпоинты содержат:
Если Вы обучаете модель только на одной машине, у Вас будет один раздел с суффиксом: .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, Сохраненная модель)
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
). При их использовании вам нужно перекомпилировать модель после загрузки и вы потеряете текущее состояние оптимизатора.
Предупреждение: Этот метод сохранения модели 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))