"Введение«Очень важным шагом после обучения модели является сохранение информации о модели для последующего переобучения и онлайн-обслуживания. Помимо личного использования, сохраненный файл модели также можно отправить в TensorFlow Hub, чтобы другие могли легко разрабатывать и обучать на основе предварительно обученной модели.
Обзор модели Керас
общийKeras
Модель обычно состоит из следующих частей:
-
Структура или конфигурация модели: определяет слои, включенные в модель, и способ их соединения.
-
Последовательность значений весовой матрицы: используется для записи состояния модели.
-
Оптимизатор: используется для оптимизации функции потерь, которую можно скомпилировать в модели (
compile
) уточняется. -
Ряд потерь и метрик: используется для регулирования процесса обучения, как потери и метрики, указанные во время компиляции, так и
add_loss()
а такжеadd_metric()
Метод добавления потерь и метрик.
использоватьKeras API
Вы можете сохранить все или некоторые из вышеперечисленных компонентов модели на диск.Keras API
Предусмотрены следующие три варианта:
-
Сохраните все содержимое модели: обычно как
TensorFlow SavedModel
формат илиKeras H5
Это наиболее часто используемый способ сохранения моделей. -
Сохраняется только структура модели: обычно как
json
сохранить в виде файла. -
Сохраняйте только значение матрицы весов модели: обычно в виде
numpy
Он сохраняется в виде массива, который обычно используется при переобучении модели или трансферном обучении.
Построение модели и обучение
Перед сохранением модели нам нужно построить модель и обучить ее, чтобы потери и метрики модели достигли определенного состояния. Рассмотрим следующую простую модель, в которой используетсяFunctional API
понял один3
Слои глубоких нейронных сетей.
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np
inputs = keras.Input(shape=(784, ), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, name='predictions')(x)
model = keras.Model(inputs=inputs, outputs=outputs, name='3_layer_mlp')
model.summary()
x_train, y_train = (
np.random.random((60000, 784)),
np.random.randint(10, size=(60000, 1)),
)
x_test, y_test = (
np.random.random((10000, 784)),
np.random.randint(10, size=(10000, 1)),
)
model.compile(
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
optimizer=keras.optimizers.RMSprop())
history = model.fit(x_train, y_train, batch_size=64, epochs=1)
# Save predictions for future checks
predictions = model.predict(x_test)
После одного раунда итеративного обучения модели со случайными данными значение матрицы весов модели и состояние оптимизатора изменились.На этом этапе мы можем сохранить модель.Конечно, вы также можете сделать это перед обучением Модель сохраняется, но делать это особого смысла нет.
сохранить всю модель
Keras
Вся информация о модели может быть сохранена в файловом каталоге, а модель может быть реконструирована с использованием файлового каталога позже, даже без исходного кода модели, процесс реконструкции может быть завершен.
Сохраненный файл модели содержит следующую информацию:
-
Структура модели.
-
Матрица весов для модели, представляющая собой информацию, полученную моделью во время обучения.
-
Сборка модели (
compile
) Информация. -
Информация о состоянии оптимизатора для модели, позволяющая продолжить обучение с того места, где закончилось последнее обучение.
существуетKeras
, ты можешь использоватьmodel.save()
метод илиtf.keras.models.save_model()
метод сохранения модели, используйтеtf.keras.models.load_model()
метод для загрузки сохраненного файла модели и перестроения модели.
Формат файла модели можно сохранить в2
вид, один дляTensorFlow SavedModel
формат, другойKeras H5
Формат, официально рекомендуемый к использованиюSavedModel
формат сохранения модели, он жеmodel.save()
Формат сохранения, используемый методом по умолчанию. может быть установленsave()
параметры в методеformat='h5'
или укажитеsave()
Суффикс имени файла в методе.h5
или.keras
перейти на использованиеH5
Формат для сохранения модели.
Сохранено в формате SavedModel
использоватьSavedModel
Код для сохранения и реконструкции модели в формате выглядит следующим образом:
# Export the model to a SavedModel
model.save('path_to_saved_model')
# Recreate the exact same model
new_model = keras.models.load_model('path_to_saved_model')
# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, rtol=1e-6, atol=1e-6)
# Note that the optimizer state is preserved as well:
# you can resume training where you left off.
new_model.fit(x_train, y_train, batch_size=64, epochs=1)
Выполнение приведенного выше кода создаст файл с именемpath_to_saved_model
каталог, вся информация о модели будет сохранена в этом каталоге, структура каталога следующая:
.
├── assets
├── saved_model.pb
└── variables
├── variables.data-00000-of-00001
└── variables.index
вassets
— необязательный каталог, используемый для хранения вспомогательных файлов, необходимых для работы модели, таких как файлы словарей.variables
Файл контрольной точки веса модели хранится в каталоге, и вся информация о весе модели хранится в этом каталоге.saved_model.pb
Файл содержит структуру модели и информацию о конфигурации для обучения, такую как оптимизаторы, потери и метрики.
Сохранить в формате H5
Keras
также поддерживает использованиеH5
Формат сохранения и реконструкции модели.Сохраненный файл содержит структуру модели, значение матрицы весов и информацию о компиляции.По сравнению сSavedModel
Формат,H5
Формат является более легкой альтернативой.
использоватьH5
Код для сохранения и реконструкции модели в формате выглядит следующим образом:
# Save the model
model.save('path_to_my_model.h5')
# Recreate the exact same model purely from the file
new_model = keras.models.load_model('path_to_my_model.h5')
# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, rtol=1e-6, atol=1e-6)
# Note that the optimizer state is preserved as well:
# you can resume training where you left off.
new_model.fit(x_train, y_train, batch_size=64, epochs=1)
но использоватьH5
Формат имеет свои ограничения по сравнению сSavedModel
,H5
Следующие два вида информации не могут быть сохранены в файле модели формата:
-
Внешне добавленная информация об убытках и индикаторах: Pass
model.add_loss()
метод иmodel.add_metric()
Информация о потерях и метриках, добавленная методом, не сохраняется вH5
в файле. Если вы хотите загрузить модели и продолжить использовать их в обучении, вам нужно добавить их снова с помощью описанного выше метода. Следует отметить, что вKeras
пройти черезself.add_loss()
илиself.add_metric()
Добавленные потери и показателиH5
Файл автоматически сохраняется. -
Информация вычислительного графика пользовательских объектов: таких как пользовательские слои (
layers
) не будет сохранен вH5
в файле. В этот момент, если вы используетеH5
Файл напрямую загружает модель и сообщаетValueError: Unknown layer
Ошибка.
Так что при сохранении всей модели, особенно для пользовательских (Subclassed
) модель, нам лучше использоватьSavedModel
формат для сохранения и реконструкции модели.
Кроме того, как видно из кода, посколькуmodel.save()
Метод сохраняет всю информацию о модели, поэтому после перестроения модели вы можете продолжить обучение на основе исходной модели без каких-либо дополнительных настроек.
сохранить только структуру модели
Иногда нас может интересовать только структура модели, и мы не хотим сохранять такую информацию, как значения веса модели и состояние оптимизатора. В этом случае мы можем использовать модель配置方法
(config
), чтобы сохранить и перестроить структуру модели.
Sequential/Functional
заSequential
модель иFunctional API
модели, так как они в основном состоят из предопределенных слоев (layers
), поэтому их информация о конфигурации существует в структурированной форме, что позволяет легко сохранить структуру модели. Мы можем использовать модельget_config()
метод, чтобы получить конфигурацию модели, затем передатьfrom_config(config)
метод восстановления модели.
-
Для первого представленного
Functional API
Для модели код сохранения и реконструкции ее структуры выглядит следующим образом:config = model.get_config() new_model = keras.Model.from_config(config) # Note that the model state is not preserved! We only saved the architecture. new_predictions = new_model.predict(x_test) assert abs(np.sum(predictions - new_predictions)) > 0.
в
get_config()
Результат, возвращаемый методом, представляет собойpython
Словарь, который содержит всю информацию о структуре модели, поэтому ее можно легко реконструировать.python
Содержание словаря следующее:{ 'name': '3_layer_mlp', 'layers': [{ 'class_name': 'InputLayer', 'config': { 'batch_input_shape': (None, 784), 'dtype': 'float32', 'sparse': False, 'ragged': False, 'name': 'digits' }, 'name': 'digits', 'inbound_nodes': [] }, { 'class_name': 'Dense', 'config': { 'name': 'dense_1', 'trainable': True, 'dtype': 'float32', 'units': 64, 'activation': 'relu', 'use_bias': True, 'kernel_initializer': { 'class_name': 'GlorotUniform', 'config': { 'seed': None } }, 'bias_initializer': { 'class_name': 'Zeros', 'config': {} }, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None }, 'name': 'dense_1', 'inbound_nodes': [[['digits', 0, 0, {}]]] }, { 'class_name': 'Dense', 'config': { 'name': 'dense_2', 'trainable': True, 'dtype': 'float32', 'units': 64, 'activation': 'relu', 'use_bias': True, 'kernel_initializer': { 'class_name': 'GlorotUniform', 'config': { 'seed': None } }, 'bias_initializer': { 'class_name': 'Zeros', 'config': {} }, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None }, 'name': 'dense_2', 'inbound_nodes': [[['dense_1', 0, 0, {}]]] }, { 'class_name': 'Dense', 'config': { 'name': 'predictions', 'trainable': True, 'dtype': 'float32', 'units': 10, 'activation': 'linear', 'use_bias': True, 'kernel_initializer': { 'class_name': 'GlorotUniform', 'config': { 'seed': None } }, 'bias_initializer': { 'class_name': 'Zeros', 'config': {} }, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None }, 'name': 'predictions', 'inbound_nodes': [[['dense_2', 0, 0, {}]]] }], 'input_layers': [['digits', 0, 0]], 'output_layers': [['predictions', 0, 0]] }
-
за
Sequential
Для модели пример кода для сохранения и перестроения структуры модели выглядит следующим образом:from tensorflow import keras model = keras.Sequential([keras.Input((32, )), keras.layers.Dense(1)]) config = model.get_config() new_model = keras.Sequential.from_config(config) new_model.summary()
Чтобы облегчить постоянное хранение структуры модели, вы можете напрямую использоватьto_json()
метод сериализует информацию модели какjson
Затем формат сохраняется локально и может использоваться при перестроении модели.from_json()
метод разбораjson
содержимое файла для завершения восстановления. Пример кода выглядит следующим образом:
json_config = model.to_json()
new_model = keras.models.model_from_json(json_config)
Следует отметить, что поскольку сохраняется только структура модели, после перестроения модели новая модель не содержит информации о компиляции и информации о состоянии предыдущей модели, поэтому новую модель необходимо перекомпилировать для последующих операций обучения. .
Подклассы моделей и слоев
Subclassed
Структурная информация модели находится в__init__
иcall
метод, они рассматриваются какpython
байт-код, не имея возможности сериализовать его какjson
Формат. На момент написания этой статьи нет возможности直接
Для пользовательских моделей (унаследованных отkeras.Model
)из结构信息
Выполнение операций сохранения и восстановления.
И дляSubclassed
слой (унаследован отkeras.Layer
) для сохранения и реконструкции структуры нам нужно переписать ееget_config()
Методы иfrom_config()
(необязательный) метод для достижения этого.
вget_config()
Метод должен возвращатьjson
сериализованные словари для адаптацииKeras
Структура модели и интерфейс сохранения модели.from_config(config)
Методы класса должны быть основаны наconfig
Параметр возвращает новый объект слоя.
четко определенный слойconfig
метод, мы можем использоватьserialize
иdeserialize
способ сериализации (сохранения) и десериализации (перестроения) информации о структуре слоя, обратите внимание, что при перестроении слоя вам нужно начать сcustom_objects
способ предоставления информации о пользовательских слоях. Пример кода выглядит следующим образом:
from tensorflow import keras
class ThreeLayerMLP(keras.layers.Layer):
def __init__(self, hidden_units):
super().__init__()
self.hidden_units = hidden_units
self.dense_layers = [keras.layers.Dense(u) for u in hidden_units]
def call(self, inputs):
x = inputs
for layer in self.dense_layers:
x = layer(x)
return x
def get_config(self):
return {"hidden_units": self.hidden_units}
layer = ThreeLayerMLP([64, 64, 10])
serialized_layer = keras.layers.serialize(layer)
print(serialized_layer)
new_layer = keras.layers.deserialize(
serialized_layer,
custom_objects={"ThreeLayerMLP": ThreeLayerMLP},
)
вserialize
Результат, возвращаемый методом, выглядит следующим образом:
{'class_name': 'ThreeLayerMLP', 'config': {'hidden_units': ListWrapper([64, 64, 10])}}
Для конструкций, построенных с использованием пользовательских слоев и пользовательских функцийFunctional API
модели, либо с использованием вышеуказанногоserialize/deserialize
методы сохранения и восстановления структуры модели, в том числе с помощьюget_config/keras.Model.from_config
метод для завершения этой операции сохранения и восстановления, но с помощьюkeras.utils.custom_object_scope
метод для указания пользовательского объекта. Пример кода выглядит следующим образом:
def custom_activation(x):
return tf.nn.tanh(x)**2
inputs = keras.Input((64, ))
x = layer(inputs)
outputs = keras.layers.Activation(custom_activation)(x)
model = keras.Model(inputs, outputs)
config = model.get_config()
print(config)
custom_objects = {
"ThreeLayerMLP": ThreeLayerMLP,
"custom_activation": custom_activation
}
with keras.utils.custom_object_scope(custom_objects):
new_model = keras.Model.from_config(config)
new_model.summary()
В дополнение к вышеперечисленномуFunctional API
Модель также можно скопировать непосредственно в память, что в основном аналогично процессу получения конфигурации и последующего перестроения модели через конфигурацию. Пример кода выглядит следующим образом:
with keras.utils.custom_object_scope(custom_objects):
new_model = keras.models.clone_model(model)
new_model.summary()
Сохранить только вес модели
В дополнение к выбору сохранения только структурной информации модели, вы также можете сохранить только информацию о весе модели. Это может быть полезно в следующих случаях:
-
Вам нужно использовать модель только для прогнозирования: в этом случае вам не нужно продолжать обучение существующей модели, и нет необходимости сохранять информацию о компиляции модели и информацию о состоянии оптимизатора.
-
Вы выполняете трансферное обучение: в этом случае вы обучаете новую модель, используя состояние (весовую матрицу) существующей модели, поэтому информация о компиляции существующей модели также не требуется.
существуетKeras
, можно передать модельget_weights()
иset_weights()
методы получения и установки значений весовой матрицы. Код выглядит следующим образом:
weights = model.get_weights() # Retrieves the state of the model.
model.set_weights(weights) # Sets the state of the model.
модельget_weights()
метод возвращаетnumpy array
состоит изlist
, который записывает информацию обо всех весовых матрицах модели, а сохраненную информацию о весе можно использовать какset_weights(weights)
Параметры метода используются для задания состояния новой модели, эту операцию также можно понимать как перенос веса между моделями.
В дополнение к переносу веса между похожими моделями операции переноса веса также могут выполняться между моделями с совместимыми архитектурами, например, мы можем получить предыдущийFunctional
Информация о весовой матрице модели, а затем значение весовой матрицы передается черезset_weights()
методы переносятся в соответствующиеSubclassed
в модели. Однако следует отметить, что порядок, количество и размер весовых матриц в двух моделях должны быть согласованы. Пример кода выглядит следующим образом:
from tensorflow import keras
from tensorflow.keras import layers
class ThreeLayerMLP(keras.Model):
def __init__(self, hidden_units):
super().__init__()
self.hidden_units = hidden_units
self.dense_layers = [layers.Dense(u) for u in hidden_units]
def call(self, inputs):
x = inputs
for layer in self.dense_layers:
x = layer(x)
return x
def get_config(self):
return {"hidden_units": self.hidden_units}
subclassed_model = ThreeLayerMLP([64, 64, 10])
subclassed_model(tf.ones((1, 784)))
subclassed_model.set_weights(functional_model.get_weights())
assert len(functional_model.weights) == len(subclassed_model.weights)
for a, b in zip(functional_model.weights, subclassed_model.weights):
np.testing.assert_allclose(a.numpy(), b.numpy())
Кроме того, для слоя без состояния, поскольку он не содержит матрицы весов, он не меняет порядок и количество матриц весов в модели, поэтому даже если между разными моделями существуют дополнительные слои без состояния (например,Dropout
слой), они также могут иметь совместимые структуры моделей, а также могут использовать описанный выше метод для переноса весовой матрицы.
Если вы хотите сохранить информацию о матрице веса локально, вы можете использоватьsave_weights(fpath)
способ локального сохранения, который можно использовать позжеload_weights(fpath)
Метод загружает информацию о весе из локального файла, чтобы восстановить состояние модели. Пример кода выглядит следующим образом:
# Save weights to disk
model.save_weights('path_to_my_weights.h5')
new_model = ThreeLayerMLP([64, 64, 10])
new_model(tf.ones((1, 784)))
new_model.load_weights('path_to_my_weights.h5')
# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, rtol=1e-6, atol=1e-6)
# Note that the optimizer was not preserved.
new_model.compile(
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
optimizer=keras.optimizers.RMSprop())
new_model.fit(x_train, y_train, batch_size=64, epochs=1)
Уведомление,save_weights
методы могут быть сохранены какKeras HDF5
файл формата, также может быть сохранен какTensorFlow Checkpoint
файл формата. иmodel.save
метод аналогичен, он также содержит параметрsave_format
, также есть два значения. По умолчаниюtf
указать использованиеCheckpoint
сохранение формата,h5
указать использованиеHDF5
сохранить формат. Если он не указан явно, он будет делать вывод на основе суффикса файла, заканчивающегося на.h5
или.hdf5
имена файлов заканчиваются наHDF5
формат для сохранения.
можно использовать в комбинацииget_config()/from_config()
иget_weights()/set_weights()
перестроить модель и восстановить исходное состояние. Но с использованиемmodel.save()
Таким образом, поскольку обучающая конфигурация модели и состояние оптимизатора не могут быть сохранены, необходимо повторно вызвать модель.compile
метод для указания некоторой конфигурации, необходимой для процесса обучения. Код выглядит следующим образом:
config = model.get_config()
weights = model.get_weights()
new_model = keras.Model.from_config(config)
new_model.set_weights(weights)
# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, rtol=1e-6, atol=1e-6)
# Note that the optimizer was not preserved,
# so the model should be compiled anew before training
# (and the optimizer will start from a blank state).
new_model.compile(
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
optimizer=keras.optimizers.RMSprop())
new_model.fit(x_train, y_train, batch_size=64, epochs=1)
TensorFlow Hub
TensorFlow Hub
представляет собой репозиторий моделей и библиотеку функций для многоразового машинного обучения.TensorFlow Hub
Модели можно повторно использовать в различных учебных задачах (即迁移学习
), что позволяет добиться хороших результатов, используя при обучении лишь небольшой набор данных, при этом улучшая способность модели к обобщению и ускоряя скорость обучения модели.
Когда мы реализуем более общую модель, мы можем отдать приоритет использованиюTensorFlow Hub
Существующая модель предварительного обучения в модели и дальнейшее моделирование и обучение на основе модели, чтобы уменьшить объем кода программы и время обучения модели.
TensorFlow 2.x
Рекомендуемое использованиеSavedModel
файл в форматеTensorFlow Hub
Делитесь предварительно обученными моделями на .tensorflow_hub
Библиотека предоставляет классhub.KerasLayer
, к которому можно получить доступ с удаленного или локальногоSavedModel
Прочитайте информацию о модели из файла и начните сKeras Layer
Реконструированная модель содержит информацию о предварительно обученной матрице весов.
использоватьhub.KerasLayer
Код для загрузки модели и прогнозирования выглядит следующим образом:
import tensorflow_hub as hub
new_layer = hub.KerasLayer(
'path_to_my_model',
trainable=True,
input_shape=[784],
dtype=tf.float32,
)
# Check that the state is preserved
new_predictions = new_layer(x_test.astype('float32'))
np.testing.assert_allclose(predictions, new_predictions, rtol=1e-6, atol=1e-6)
Делая прогнозы, следите за тем, чтобы тип данных весовой матрицы в сохраненном файле модели соответствовал типу входных данных. существуетTensorFlow 2.x
, тип данных файла модели определяется какtf.keras.backend.floatx()
получить, по умолчаниюfloat32
. в состоянии пройтиtf.keras.backend.set_floatx('float64')
Измените тип данных модели или преобразуйте входные данные, чтобы избежать ошибок из-за несоответствия типов.
Используйте этот метод для загрузки модели и использованияkeras.models.load_model
Есть несколько отличий от загрузки модели:
-
С одной стороны, это по существу
Keras Layer
, поэтому не используйте некоторые методы модели, напримерsummary
метод. -
Во-вторых, его внутренняя структура была скрыта, поэтому его конкретный состав не может быть просмотрен (
layers
). -
В-третьих, при обучении его нужно использовать как слой модели, а для продолжения обучения можно создать новую модель.
существуетKeras
используется в кодеhub.KerasLayer
Код для обучения следующий:
new_layer = hub.KerasLayer(
'path_to_my_model',
trainable=True,
input_shape=[784],
dtype=tf.float32,
)
new_model = tf.keras.Sequential([new_layer])
new_model.compile(
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
optimizer=keras.optimizers.RMSprop())
new_model.fit(x_train, y_train, batch_size=64, epochs=1)
Как видно из кода, мы можем использоватьKeras Layer
использовать то же самоеhub.KerasLayer
. по умолчанию,hub.KerasLayer
Значение весовой матрицы в не поддается обучению, то есть остается неизменным в новом процессе обучения.Если вам нужно доработать исходную модель, вы можетеtrainable
параметр установлен наTrue
.
Кроме того, если вам нужно повторно экспортировать доработанную модель, вы можете использовать различные методы, описанные выше, такие какmodel.save()
илиtf.keras.models.save_model()
Экспортируйте по мере необходимости.
Если вы хотите поделиться своей предварительно обученной моделью сTensorFlow Hub
, вам сначала нужно экспортировать модель какSavedModel
Отформатируйте файл, а затем отправьте его в Интернет для совместного использования модели. При экспорте файлов модели нужно быть внимательным.Если вы хотите поделиться всей моделью, вызовите модельsave
метод требуетinclude_optimizer
параметр установлен наFalse
, то есть общая модель не может содержать информацию о состоянии оптимизатора; если вы хотите поделиться только определенной частью модели, вы можете извлечь часть для совместного использования перед построением модели и сохранить ее после обучения завершено. Пример кода выглядит следующим образом:
piece_to_share = tf.keras.Model(...)
full_model = tf.keras.Sequential([piece_to_share, ...])
full_model.fit(...)
piece_to_share.save(..., include_optimizer=False)