Узнайте, как настраивать каждый шаг модели, сбережения в керасах

Узнайте, как настраивать каждый шаг модели, сбережения в керасах

13 июня 2025 г.

Обзор контента

  • Введение
  • Апис
  • Настраивать'
  • Состояние сохранения настройки
  • save_own_variables () и load_own_variables ()
  • save_assets () и load_assets ()
  • Создание и составление сбережений настройки
  • get_build_config () и compile_from_config ()
  • Заключение

Введение

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

Апис

Мы рассмотрим следующие API:

  • save_assets()иload_assets()
  • save_own_variables()иload_own_variables()
  • get_build_config()иbuild_from_config()
  • get_compile_config()иcompile_from_config()

При восстановлении модели они выполняются в следующем порядке:

  • build_from_config()
  • compile_from_config()
  • load_own_variables()
  • load_assets()

Настраивать

import os
import numpy as np
import tensorflow as tf
import keras

Состояние сохранения настройки

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

save_own_variables()иload_own_variables()

Эти методы сохраняют и загружают переменные состояния слоя, когдаmodel.save()иkeras.models.load_model()называются соответственно. По умолчанию переменные состояния, сохраненные и загруженные, являются весами слоя (как обучаемого, так и необработанного). Вот реализация по умолчаниюsave_own_variables():

def save_own_variables(self, store):
    all_vars = self._trainable_weights + self._non_trainable_weights
    for i, v in enumerate(all_vars):
        store[f"{i}"] = v.numpy()

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

Пример:

@keras.utils.register_keras_serializable(package="my_custom_package")
class LayerWithCustomVariables(keras.layers.Dense):
    def __init__(self, units, **kwargs):
        super().__init__(units, **kwargs)
        self.stored_variables = tf.Variable(
            np.random.random((10,)), name="special_arr", dtype=tf.float32
        )

    def save_own_variables(self, store):
        super().save_own_variables(store)
        # Stores the value of the `tf.Variable` upon saving
        store["variables"] = self.stored_variables.numpy()

    def load_own_variables(self, store):
        # Assigns the value of the `tf.Variable` upon loading
        self.stored_variables.assign(store["variables"])
        # Load the remaining weights
        for i, v in enumerate(self.weights):
            v.assign(store[f"{i}"])
        # Note: You must specify how all variables (including layer weights)
        # are loaded in `load_own_variables.`

    def call(self, inputs):
        return super().call(inputs) * self.stored_variables


model = keras.Sequential([LayerWithCustomVariables(1)])

ref_input = np.random.random((8, 10))
ref_output = np.random.random((8,))
model.compile(optimizer="adam", loss="mean_squared_error")
model.fit(ref_input, ref_output)

model.save("custom_vars_model.keras")
restored_model = keras.models.load_model("custom_vars_model.keras")

np.testing.assert_allclose(
    model.layers[0].stored_variables.numpy(),
    restored_model.layers[0].stored_variables.numpy(),
)

1/1 [==============================] - 4s 4s/step - loss: 0.2723

save_assets()иload_assets()

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

Например, слои доменов NLP, такие как слои текстовой версии и слои indexlookup, могут потребоваться хранение связанного с ним словарного запаса (или таблицы поиска) в текстовом файле при сохранении.

Давайте возьмем основы этого рабочего процесса с простым файломassets.txtПолем

Пример:

@keras.saving.register_keras_serializable(package="my_custom_package")
class LayerWithCustomAssets(keras.layers.Dense):
    def __init__(self, vocab=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.vocab = vocab

    def save_assets(self, inner_path):
        # Writes the vocab (sentence) to text file at save time.
        with open(os.path.join(inner_path, "vocabulary.txt"), "w") as f:
            f.write(self.vocab)

    def load_assets(self, inner_path):
        # Reads the vocab (sentence) from text file at load time.
        with open(os.path.join(inner_path, "vocabulary.txt"), "r") as f:
            text = f.read()
        self.vocab = text.replace("<unk>", "little")


model = keras.Sequential(
    [LayerWithCustomAssets(vocab="Mary had a <unk> lamb.", units=5)]
)

x = np.random.random((10, 10))
y = model(x)

model.save("custom_assets_model.keras")
restored_model = keras.models.load_model("custom_assets_model.keras")

np.testing.assert_string_equal(
    restored_model.layers[0].vocab, "Mary had a little lamb."
)

buildиcompileСохранение настройки

get_build_config()иbuild_from_config()

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

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

Пример:

@keras.saving.register_keras_serializable(package="my_custom_package")
class LayerWithCustomBuild(keras.layers.Layer):
    def __init__(self, units=32, **kwargs):
        super().__init__(**kwargs)
        self.units = units

    def call(self, inputs):
        return tf.matmul(inputs, self.w) + self.b

    def get_config(self):
        return dict(units=self.units, **super().get_config())

    def build(self, input_shape, layer_init):
        # Note the customization in overriding `build()` adds an extra argument.
        # Therefore, we will need to manually call build with `layer_init` argument
        # before the first execution of `call()`.
        super().build(input_shape)
        self.w = self.add_weight(
            shape=(input_shape[-1], self.units),
            initializer=layer_init,
            trainable=True,
        )
        self.b = self.add_weight(
            shape=(self.units,),
            initializer=layer_init,
            trainable=True,
        )
        self.layer_init = layer_init

    def get_build_config(self):
        build_config = super().get_build_config()  # only gives `input_shape`
        build_config.update(
            {"layer_init": self.layer_init}  # Stores our initializer for `build()`
        )
        return build_config

    def build_from_config(self, config):
        # Calls `build()` with the parameters at loading time
        self.build(config["input_shape"], config["layer_init"])


custom_layer = LayerWithCustomBuild(units=16)
custom_layer.build(input_shape=(8,), layer_init="random_normal")

model = keras.Sequential(
    [
        custom_layer,
        keras.layers.Dense(1, activation="sigmoid"),
    ]
)

x = np.random.random((16, 8))
y = model(x)

model.save("custom_build_model.keras")
restored_model = keras.models.load_model("custom_build_model.keras")

np.testing.assert_equal(restored_model.layers[0].layer_init, "random_normal")
np.testing.assert_equal(restored_model.built, True)

get_compile_config()иcompile_from_config()

Эти методы работают вместе, чтобы сохранить информацию, с которой была скомпилирована модель (оптимизаторы, потери и т. Д.) И восстановить и повторно выполнять модель с помощью этой информации.

Переопределение этих методов может быть полезно для составления восстановленной модели с пользовательскими оптимизаторами, пользовательскими потерями и т. Д., Поскольку их необходимо покинуть перед вызовомmodel.compileвcompile_from_config()Полем

Давайте посмотрим на пример этого.

Пример:

@keras.saving.register_keras_serializable(package="my_custom_package")
def small_square_sum_loss(y_true, y_pred):
    loss = tf.math.squared_difference(y_pred, y_true)
    loss = loss / 10.0
    loss = tf.reduce_sum(loss, axis=1)
    return loss


@keras.saving.register_keras_serializable(package="my_custom_package")
def mean_pred(y_true, y_pred):
    return tf.reduce_mean(y_pred)


@keras.saving.register_keras_serializable(package="my_custom_package")
class ModelWithCustomCompile(keras.Model):
    def __init__(self):
        super().__init__()
        self.dense1 = keras.layers.Dense(8, activation="relu")
        self.dense2 = keras.layers.Dense(4, activation="softmax")

    def call(self, inputs):
        x = self.dense1(inputs)
        return self.dense2(x)

    def compile(self, optimizer, loss_fn, metrics):
        super().compile(optimizer=optimizer, loss=loss_fn, metrics=metrics)
        self.model_optimizer = optimizer
        self.loss_fn = loss_fn
        self.loss_metrics = metrics

    def get_compile_config(self):
        # These parameters will be serialized at saving time.
        return {
            "model_optimizer": self.model_optimizer,
            "loss_fn": self.loss_fn,
            "metric": self.loss_metrics,
        }

    def compile_from_config(self, config):
        # Deserializes the compile parameters (important, since many are custom)
        optimizer = keras.utils.deserialize_keras_object(config["model_optimizer"])
        loss_fn = keras.utils.deserialize_keras_object(config["loss_fn"])
        metrics = keras.utils.deserialize_keras_object(config["metric"])

        # Calls compile with the deserialized parameters
        self.compile(optimizer=optimizer, loss_fn=loss_fn, metrics=metrics)


model = ModelWithCustomCompile()
model.compile(
    optimizer="SGD", loss_fn=small_square_sum_loss, metrics=["accuracy", mean_pred]
)

x = np.random.random((4, 8))
y = np.random.random((4,))

model.fit(x, y)

model.save("custom_compile_model.keras")
restored_model = keras.models.load_model("custom_compile_model.keras")

np.testing.assert_equal(model.model_optimizer, restored_model.model_optimizer)
np.testing.assert_equal(model.loss_fn, restored_model.loss_fn)
np.testing.assert_equal(model.loss_metrics, restored_model.loss_metrics)

1/1 [==============================] - 1s 651ms/step - loss: 0.0616 - accuracy: 0.0000e+00 - mean_pred: 0.2500
WARNING:absl:Skipping variable loading for optimizer 'SGD', because it has 1 variables whereas the saved optimizer has 5 variables.

Заключение

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

  • save_own_variablesиload_own_variablesОпределите, как ваши штаты сохраняются и загружаются.
  • save_assetsиload_assetsМожет быть добавлено для хранения и загрузки любой дополнительной информации, которую нуждается в вашей модели.
  • get_build_configиbuild_from_configСохраните и восстановите настроенные состояния модели.
  • get_compile_configиcompile_from_configСохраните и восстановите скомпилированные состояния модели.

Первоначально опубликовано наTensorflowВеб -сайт, эта статья появляется здесь под новым заголовком и имеет лицензию в CC на 4.0. Образцы кода, разделенные по лицензии Apache 2.0


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE