Keras modellerini kaydedin ve yükleyin

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Not defterini indir

Tanıtım

Bir Keras modeli birden çok bileşenden oluşur:

  • Modelin hangi katmanları içerdiğini ve bunların nasıl bağlanacağını belirten mimari veya konfigürasyon.
  • Bir dizi ağırlık değeri ("modelin durumu").
  • Bir optimize edici (modelin derlenmesiyle tanımlanır).
  • Kayıpları ve metrik bir dizi (model derleme ya da arama tarafından tanımlanan add_loss() ya da add_metric() ).

Keras API, tüm bu parçaları bir kerede diske kaydetmeyi veya yalnızca bazılarını seçerek kaydetmeyi mümkün kılar:

  • Her şeyi TensorFlow SavedModel formatında (veya daha eski Keras H5 formatında) tek bir arşive kaydetme. Bu standart uygulamadır.
  • Yalnızca mimariyi/yapılandırmayı, tipik olarak bir JSON dosyası olarak kaydetme.
  • Yalnızca ağırlık değerlerinin kaydedilmesi. Bu genellikle modeli eğitirken kullanılır.

Bu seçeneklerin her birine bir göz atalım. Birini veya diğerini ne zaman kullanırsınız ve bunlar nasıl çalışır?

Bir model nasıl kaydedilir ve yüklenir

Bu kılavuzu okumak için yalnızca 10 saniyeniz varsa, bilmeniz gerekenler burada.

Keras modelini kaydetme:

model = ...  # Get model (Sequential, Functional Model, or Model subclass)
model.save('path/to/location')

Modeli geri yükleme:

from tensorflow import keras
model = keras.models.load_model('path/to/location')

Şimdi ayrıntılara bakalım.

Kurmak

import numpy as np
import tensorflow as tf
from tensorflow import keras

Tüm model kaydetme ve yükleme

Tüm bir modeli tek bir esere kaydedebilirsiniz. Şunları içerecektir:

  • Modelin mimarisi/yapılandırması
  • Modelin ağırlık değerleri (eğitim sırasında öğrenilen)
  • Modelin derleme bilgileri (eğer compile() denirdi)
  • Optimize edici ve varsa durumu (bu, eğitime kaldığınız yerden yeniden başlamanızı sağlar)

API'ler

TensorFlow SavedModel biçimini ve daha eski Keras H5 biçimi: Eğer diske bütün bir modeli kaydetmek için kullanabileceğiniz iki biçimi vardır. Önerilen biçim SavedModel'dir. Kullanmak zaman varsayılan model.save() .

H5 formatına şu şekilde geçebilirsiniz:

  • Geçme save_format='h5' için save() .
  • Bir dosya adı geçirerek uçları o .h5 veya .keras için save() .

Kaydedilmiş Model biçimi

SavedModel, model mimarisini, ağırlıkları ve çağrı işlevlerinin izlenen Tensorflow alt grafiklerini kaydeden daha kapsamlı kaydetme biçimidir. Bu, Keras'ın hem yerleşik katmanları hem de özel nesneleri geri yüklemesini sağlar.

Örnek:

def get_model():
    # Create a simple model.
    inputs = keras.Input(shape=(32,))
    outputs = keras.layers.Dense(1)(inputs)
    model = keras.Model(inputs, outputs)
    model.compile(optimizer="adam", loss="mean_squared_error")
    return model


model = get_model()

# Train the model.
test_input = np.random.random((128, 32))
test_target = np.random.random((128, 1))
model.fit(test_input, test_target)

# Calling `save('my_model')` creates a SavedModel folder `my_model`.
model.save("my_model")

# It can be used to reconstruct the model identically.
reconstructed_model = keras.models.load_model("my_model")

# Let's check:
np.testing.assert_allclose(
    model.predict(test_input), reconstructed_model.predict(test_input)
)

# The reconstructed model is already compiled and has retained the optimizer
# state, so training can resume:
reconstructed_model.fit(test_input, test_target)
4/4 [==============================] - 1s 2ms/step - loss: 0.5884
2021-08-25 17:49:05.320893: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: my_model/assets
4/4 [==============================] - 0s 2ms/step - loss: 0.5197
<keras.callbacks.History at 0x7f99486ad490>

SavedModel'in içeriği

Arayan model.save('my_model') adında bir klasör oluşturur my_model aşağıdakileri içeren:

ls my_model
assets  keras_metadata.pb  saved_model.pb  variables

Model mimari ve (iyileştirici, kayıp, ve metrik dahil) eğitim yapılandırma saklanır saved_model.pb . Ağırlıklar kaydedilir variables/ dizinine.

SavedModel biçimi hakkında ayrıntılı bilgi için bkz SavedModel kılavuzu (diskte SavedModel biçimi) .

SavedModel özel nesneleri nasıl işler?

(Eğer uygulanırsa ve yapılandırma,) modelini ve katmanlarını, SavedModel biçim mağazaları sınıf adı, çağrı işlevi, kayıp, ve ağırlıklar kaydederken. Çağrı işlevi, modelin/katmanın hesaplama grafiğini tanımlar.

Model/katman yapılandırmasının yokluğunda, çağrı işlevi, orijinal model gibi eğitilebilen, değerlendirilebilen ve çıkarım için kullanılabilen bir model oluşturmak için kullanılır.

Yine de tanımlamak için iyi bir uygulamadır her zaman get_config ve from_config bir özel model veya katman sınıf yazarken yöntemleri. Bu, gerekirse daha sonra hesaplamayı kolayca güncellemenizi sağlar. Hakkında bölümüne bakınız Özel nesneler daha fazla bilgi için.

Örnek:

class CustomModel(keras.Model):
    def __init__(self, hidden_units):
        super(CustomModel, self).__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}

    @classmethod
    def from_config(cls, config):
        return cls(**config)


model = CustomModel([16, 16, 10])
# Build the model by calling it
input_arr = tf.random.uniform((1, 5))
outputs = model(input_arr)
model.save("my_model")

# Option 1: Load with the custom_object argument.
loaded_1 = keras.models.load_model(
    "my_model", custom_objects={"CustomModel": CustomModel}
)

# Option 2: Load without the CustomModel class.

# Delete the custom-defined model class to ensure that the loader does not have
# access to it.
del CustomModel

loaded_2 = keras.models.load_model("my_model")
np.testing.assert_allclose(loaded_1(input_arr), outputs)
np.testing.assert_allclose(loaded_2(input_arr), outputs)

print("Original model:", model)
print("Model Loaded with custom objects:", loaded_1)
print("Model loaded without the custom object class:", loaded_2)
INFO:tensorflow:Assets written to: my_model/assets
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.
Original model: <__main__.CustomModel object at 0x7f9949c86810>
Model Loaded with custom objects: <__main__.CustomModel object at 0x7f99681f61d0>
Model loaded without the custom object class: <keras.saving.saved_model.load.CustomModel object at 0x7f9aaceefd10>

İlk yüklenen modeli yapılandırma kullanılarak yüklenir CustomModel sınıfı. İkinci model, orijinal model gibi davranan model sınıfı dinamik olarak oluşturularak yüklenir.

SavedModel'i Yapılandırma

Yeni TensoFlow 2.4'te argüman save_traces eklendi model.save SavedModel fonksiyonu izleme geçiş yapmanızı sağlar, hangi. Fonksiyonlar, bu nedenle zaman orijinal sınıf definitons olmadan yeniden yük özel nesnelere keras izin kaydedilir save_traces=False , tüm özel nesneler tanımlanmış olmalı get_config / from_config yöntemleri. Yüklerken, özel nesneler aktarılması gerekir custom_objects argüman. save_traces=False SavedModel ve zamandan tasarruf tarafından kullanılan disk alanını azaltır.

Keras H5 formatı

Keras ayrıca modelin mimarisi, ağırlıklar değerleri ve içeren tek HDF5 dosyasını tasarruf destekler compile() bilgisini. SavedModel'e hafif bir alternatiftir.

Örnek:

model = get_model()

# Train the model.
test_input = np.random.random((128, 32))
test_target = np.random.random((128, 1))
model.fit(test_input, test_target)

# Calling `save('my_model.h5')` creates a h5 file `my_model.h5`.
model.save("my_h5_model.h5")

# It can be used to reconstruct the model identically.
reconstructed_model = keras.models.load_model("my_h5_model.h5")

# Let's check:
np.testing.assert_allclose(
    model.predict(test_input), reconstructed_model.predict(test_input)
)

# The reconstructed model is already compiled and has retained the optimizer
# state, so training can resume:
reconstructed_model.fit(test_input, test_target)
4/4 [==============================] - 0s 1ms/step - loss: 1.6322
4/4 [==============================] - 0s 1ms/step - loss: 1.4790
<keras.callbacks.History at 0x7f9aacc0fd50>

sınırlamalar

SavedModel biçimiyle karşılaştırıldığında, H5 dosyasına dahil edilmeyen iki şey vardır:

  • İle eklenmiş Dış kayıplar ve ölçümlerini model.add_loss() & model.add_metric() (SavedModel aksine) kaydedilmez. Modelinizde bu tür kayıplar ve metrikler varsa ve eğitime devam etmek istiyorsanız, modeli yükledikten sonra bu kayıpları kendiniz eklemeniz gerekir. Not Bu yoluyla katmanları içinde oluşturulan kayıplar / ölçümlere geçerli olmadığını self.add_loss() & self.add_metric() . Parçası oldukları çoktan katman yüklenen Olarak, bu kayıplar ve metrikler, tutulur call tabakasının yöntemle.
  • Özel tabakalar kaydedilen dosyanın dahil olarak özel hesaplama grafik nesneleri gibi. Yükleme sırasında, modeli yeniden yapılandırmak için Keras'ın bu nesnelerin Python sınıflarına/işlevlerine erişmesi gerekir. Bkz Özel nesneleri .

Mimariyi kaydetme

Modelin konfigürasyonu (veya mimarisi), modelin hangi katmanları içerdiğini ve bu katmanların nasıl bağlandığını belirtir*. Bir modelin konfigürasyonuna sahipseniz, model, ağırlıklar için yeni başlatılmış bir durumla ve derleme bilgisi olmadan oluşturulabilir.

*Bunun yalnızca işlevsel veya Sıralı api alt sınıflanmamış modeller kullanılarak tanımlanan modeller için geçerli olduğunu unutmayın.

Sıralı modelin veya İşlevsel API modelinin yapılandırılması

Bu tür modeller, açık katman grafikleridir: konfigürasyonları her zaman yapılandırılmış bir biçimde mevcuttur.

API'ler

get_config() ve from_config()

Arayan config = model.get_config() modelinin yapılandırmasını içeren bir Python dicti döndürür. Aynı model, daha sonra yoluyla yeniden olabilir Sequential.from_config(config) , (a için Sequential modeli) ya da Model.from_config(config) (Fonksiyonel API modeli için).

Aynı iş akışı, herhangi bir seri hale getirilebilir katman için de çalışır.

Katman örneği:

layer = keras.layers.Dense(3, activation="relu")
layer_config = layer.get_config()
new_layer = keras.layers.Dense.from_config(layer_config)

Sıralı model örneği:

model = keras.Sequential([keras.Input((32,)), keras.layers.Dense(1)])
config = model.get_config()
new_model = keras.Sequential.from_config(config)

Fonksiyonel model örneği:

inputs = keras.Input((32,))
outputs = keras.layers.Dense(1)(inputs)
model = keras.Model(inputs, outputs)
config = model.get_config()
new_model = keras.Model.from_config(config)

to_json() ve tf.keras.models.model_from_json()

Bu benzer get_config / from_config o zaman orijinal modelin sınıfa olmadan yüklenebilir bir JSON dize içine modeli döner hariç. Ayrıca modellere özeldir, katmanlar için değildir.

Örnek:

model = keras.Sequential([keras.Input((32,)), keras.layers.Dense(1)])
json_config = model.to_json()
new_model = keras.models.model_from_json(json_config)

Özel nesneler

Modeller ve katmanlar

Sınıflandırma model ve katmanların mimarisi yöntemleri tanımlanmıştır __init__ ve call . (Örneğin aracılığıyla size bayt kodu seri hale deneyebilirsiniz - Onlar JSON uyumlu yapılandırmada içine getirilemez Python bytecode, kabul edilir pickle ), ama tamamen güvensiz olduğunu ve model farklı bir sistem üzerinde yüklenemiyor demektir.

/ Kaydetme özel tanımlı katmanlar sahip bir model ya da bir sınıflandırma modeli yükleme amacıyla, üzerine yazmak gerekir get_config ve isteğe bağlı from_config yöntemleri. Ek olarak, Keras'ın bundan haberdar olması için özel nesneyi kaydettirmelisiniz.

Özel işlevler

Özel-tanımlı fonksiyonlar (örneğin aktivasyon kaybı ya da başlatma) bir gerek yoktur get_config yöntemi. İşlev adı, özel bir nesne olarak kaydedildiği sürece yükleme için yeterlidir.

Yalnızca TensorFlow grafiğini yükleme

Keras tarafından oluşturulan TensorFlow grafiğini yüklemek mümkündür. Bunu, herhangi sağlamak gerekmez custom_objects . Bunu şu şekilde yapabilirsiniz:

model.save("my_model")
tensorflow_graph = tf.saved_model.load("my_model")
x = np.random.uniform(size=(4, 32)).astype(np.float32)
predicted = tensorflow_graph(x).numpy()
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
INFO:tensorflow:Assets written to: my_model/assets

Bu yöntemin birkaç dezavantajı olduğunu unutmayın:

  • İzlenebilirlik nedenleriyle, kullanılan özel nesnelere her zaman erişiminiz olmalıdır. Yeniden yaratamayacağınız bir modeli üretime sokmak istemezsiniz.
  • Tarafından döndürülen nesne tf.saved_model.load bir Keras model değildir. Yani kullanımı o kadar kolay değil. Örneğin, hiç erişemez .predict() veya .fit()

Bunun kullanımı tavsiye edilmez bile, örneğin, sıkı bir noktada iseniz özel nesnelerin kod kaybetmiş veya modelin yükleme sorunları varsa, o size yardımcı olabilir tf.keras.models.load_model() .

Sen daha öğrenebilirsiniz hakkında sayfa tf.saved_model.load

Yapılandırma yöntemlerini tanımlama

Özellikler:

  • get_config Mimarlık ve model tasarrufu API'ler keras ile uyumlu olması için bir JSON serileştirilebilir sözlüğü dönmelidir.
  • from_config(config) ( classmethod ) yapılandırma oluşturulur yeni bir katman ya da model nesne döndürmelidir. Varsayılan uygulama döner cls(**config) .

Örnek:

class CustomLayer(keras.layers.Layer):
    def __init__(self, a):
        self.var = tf.Variable(a, name="var_a")

    def call(self, inputs, training=False):
        if training:
            return inputs * self.var
        else:
            return inputs

    def get_config(self):
        return {"a": self.var.numpy()}

    # There's actually no need to define `from_config` here, since returning
    # `cls(**config)` is the default behavior.
    @classmethod
    def from_config(cls, config):
        return cls(**config)


layer = CustomLayer(5)
layer.var.assign(2)

serialized_layer = keras.layers.serialize(layer)
new_layer = keras.layers.deserialize(
    serialized_layer, custom_objects={"CustomLayer": CustomLayer}
)

Özel nesneyi kaydetme

Keras, yapılandırmayı hangi sınıfın oluşturduğunu not eder. Yukarıdaki örnekte, tf.keras.layers.serialize özel tabakasının bir seri formunu oluşturur:

{'class_name': 'CustomLayer', 'config': {'a': 2} }

Keras bir ana liste tutar tüm yerleşik çağrı için doğru sınıfını bulmak için kullanılır katmanı modeli, optimize edici, ve metrik sınıflar, from_config . Sınıf bulunamazsa, o zaman bir hata (yükseltilir Value Error: Unknown layer ). Bu listeye özel sınıfları kaydetmenin birkaç yolu vardır:

  1. Ayar custom_objects yükleme işlevi argüman. (yukarıdaki "Yapılandırma yöntemlerini tanımlama" bölümündeki örneğe bakın)
  2. tf.keras.utils.custom_object_scope veya tf.keras.utils.CustomObjectScope
  3. tf.keras.utils.register_keras_serializable

Özel katman ve işlev örneği

class CustomLayer(keras.layers.Layer):
    def __init__(self, units=32, **kwargs):
        super(CustomLayer, self).__init__(**kwargs)
        self.units = units

    def build(self, input_shape):
        self.w = self.add_weight(
            shape=(input_shape[-1], self.units),
            initializer="random_normal",
            trainable=True,
        )
        self.b = self.add_weight(
            shape=(self.units,), initializer="random_normal", trainable=True
        )

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

    def get_config(self):
        config = super(CustomLayer, self).get_config()
        config.update({"units": self.units})
        return config


def custom_activation(x):
    return tf.nn.tanh(x) ** 2


# Make a model with the CustomLayer and custom_activation
inputs = keras.Input((32,))
x = CustomLayer(32)(inputs)
outputs = keras.layers.Activation(custom_activation)(x)
model = keras.Model(inputs, outputs)

# Retrieve the config
config = model.get_config()

# At loading time, register the custom objects with a `custom_object_scope`:
custom_objects = {"CustomLayer": CustomLayer, "custom_activation": custom_activation}
with keras.utils.custom_object_scope(custom_objects):
    new_model = keras.Model.from_config(config)

Bellek içi model klonlama

Ayrıca yoluyla bir modelin bellek içi klonlama yapabilirsiniz tf.keras.models.clone_model() . Bu, yapılandırmayı alıp ardından modeli yapılandırmasından yeniden oluşturmaya eşdeğerdir (bu nedenle derleme bilgilerini veya katman ağırlık değerlerini korumaz).

Örnek:

with keras.utils.custom_object_scope(custom_objects):
    new_model = keras.models.clone_model(model)

Yalnızca modelin ağırlık değerlerini kaydetme ve yükleme

Yalnızca bir modelin ağırlıklarını kaydetmeyi ve yüklemeyi seçebilirsiniz. Bu, aşağıdaki durumlarda yararlı olabilir:

  • Modele yalnızca çıkarım için ihtiyacınız var: bu durumda eğitimi yeniden başlatmanız gerekmeyecek, bu nedenle derleme bilgilerine veya optimize edici durumuna ihtiyacınız yok.
  • Transfer öğrenimi yapıyorsunuz: bu durumda, önceki bir modelin durumunu yeniden kullanarak yeni bir modeli eğitiyor olacaksınız, bu nedenle önceki modelin derleme bilgilerine ihtiyacınız yok.

Bellek içi ağırlık aktarımı için API'ler

Ağırlıklar kullanarak farklı nesneler arasında kopyalanabilir get_weights ve set_weights :

Aşağıdaki örnekler.

Ağırlıkları bir katmandan diğerine bellekte aktarma

def create_layer():
    layer = keras.layers.Dense(64, activation="relu", name="dense_2")
    layer.build((None, 784))
    return layer


layer_1 = create_layer()
layer_2 = create_layer()

# Copy weights from layer 1 to layer 2
layer_2.set_weights(layer_1.get_weights())

Ağırlıkları bir modelden başka bir modele uyumlu bir mimariye sahip bellekte aktarma

# Create a simple functional model
inputs = keras.Input(shape=(784,), name="digits")
x = keras.layers.Dense(64, activation="relu", name="dense_1")(inputs)
x = keras.layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = keras.layers.Dense(10, name="predictions")(x)
functional_model = keras.Model(inputs=inputs, outputs=outputs, name="3_layer_mlp")

# Define a subclassed model with the same architecture
class SubclassedModel(keras.Model):
    def __init__(self, output_dim, name=None):
        super(SubclassedModel, self).__init__(name=name)
        self.output_dim = output_dim
        self.dense_1 = keras.layers.Dense(64, activation="relu", name="dense_1")
        self.dense_2 = keras.layers.Dense(64, activation="relu", name="dense_2")
        self.dense_3 = keras.layers.Dense(output_dim, name="predictions")

    def call(self, inputs):
        x = self.dense_1(inputs)
        x = self.dense_2(x)
        x = self.dense_3(x)
        return x

    def get_config(self):
        return {"output_dim": self.output_dim, "name": self.name}


subclassed_model = SubclassedModel(10)
# Call the subclassed model once to create the weights.
subclassed_model(tf.ones((1, 784)))

# Copy weights from functional_model to subclassed_model.
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())

Durumsuz katmanlar durumu

Durum bilgisi olmayan katmanlar ağırlıkların sırasını veya sayısını değiştirmediğinden, fazladan/eksik durumsuz katmanlar olsa bile modeller uyumlu mimarilere sahip olabilir.

inputs = keras.Input(shape=(784,), name="digits")
x = keras.layers.Dense(64, activation="relu", name="dense_1")(inputs)
x = keras.layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = keras.layers.Dense(10, name="predictions")(x)
functional_model = keras.Model(inputs=inputs, outputs=outputs, name="3_layer_mlp")

inputs = keras.Input(shape=(784,), name="digits")
x = keras.layers.Dense(64, activation="relu", name="dense_1")(inputs)
x = keras.layers.Dense(64, activation="relu", name="dense_2")(x)

# Add a dropout layer, which does not contain any weights.
x = keras.layers.Dropout(0.5)(x)
outputs = keras.layers.Dense(10, name="predictions")(x)
functional_model_with_dropout = keras.Model(
    inputs=inputs, outputs=outputs, name="3_layer_mlp"
)

functional_model_with_dropout.set_weights(functional_model.get_weights())

Ağırlıkları diske kaydetmek ve geri yüklemek için API'ler

Ağırlıklar arayarak diske kaydedilebilir model.save_weights aşağıdaki biçimlerde:

  • TensorFlow Kontrol Noktası
  • HDF5

İçin varsayılan biçim model.save_weights TensorFlow kontrol noktası olduğunu. Kaydetme biçimini belirtmenin iki yolu vardır:

  1. save_format argümanı: Set değeri save_format="tf" veya save_format="h5" .
  2. path argümanı: ile yol uçları ise .h5 veya .hdf5 ardından HDF5 biçimi kullanılır. Sürece diğer ekleri bir TensorFlow kontrol noktasında yol açacak save_format ayarlanır.

Ağırlıkları bellek içi numpy dizileri olarak alma seçeneği de vardır. Her API'nin aşağıda ayrıntıları verilen artıları ve eksileri vardır.

TF Kontrol Noktası formatı

Örnek:

# Runnable example
sequential_model = keras.Sequential(
    [
        keras.Input(shape=(784,), name="digits"),
        keras.layers.Dense(64, activation="relu", name="dense_1"),
        keras.layers.Dense(64, activation="relu", name="dense_2"),
        keras.layers.Dense(10, name="predictions"),
    ]
)
sequential_model.save_weights("ckpt")
load_status = sequential_model.load_weights("ckpt")

# `assert_consumed` can be used as validation that all variable values have been
# restored from the checkpoint. See `tf.train.Checkpoint.restore` for other
# methods in the Status object.
load_status.assert_consumed()
<tensorflow.python.training.tracking.util.CheckpointLoadStatus at 0x7f9aaca4ced0>

Biçim ayrıntıları

TensorFlow Checkpoint formatı, nesne öznitelik adlarını kullanarak ağırlıkları kaydeder ve geri yükler. Örneğin, düşünün tf.keras.layers.Dense katmanı. : Tabakası iki ağırlıkları içeren dense.kernel ve dense.bias . Tabaka ile kaydedildiğinde tf biçimi, ortaya çıkan denetim noktası tuşları içeriyor "kernel" ve "bias" ve bunlara karşılık gelen ağırlık değerleri. Daha fazla bilgi için bkz TF Checkpoint kılavuzunda "Yükleme mekaniği" .

Adı üst nesne, değişken olmayan adına kullanıldıktan sonra bu özellik / grafik kenar adlandırılır edin. Düşünün CustomLayer aşağıdaki örnekte. Değişken CustomLayer.var birlikte kaydedilir "var" anahtar parçası olarak değil, "var_a" .

class CustomLayer(keras.layers.Layer):
    def __init__(self, a):
        self.var = tf.Variable(a, name="var_a")


layer = CustomLayer(5)
layer_ckpt = tf.train.Checkpoint(layer=layer).save("custom_layer")

ckpt_reader = tf.train.load_checkpoint(layer_ckpt)

ckpt_reader.get_variable_to_dtype_map()
{'save_counter/.ATTRIBUTES/VARIABLE_VALUE': tf.int64,
 '_CHECKPOINTABLE_OBJECT_GRAPH': tf.string,
 'layer/var/.ATTRIBUTES/VARIABLE_VALUE': tf.int32}

Transfer öğrenme örneği

Esasen, iki model aynı mimariye sahip olduğu sürece, aynı kontrol noktasını paylaşabilirler.

Örnek:

inputs = keras.Input(shape=(784,), name="digits")
x = keras.layers.Dense(64, activation="relu", name="dense_1")(inputs)
x = keras.layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = keras.layers.Dense(10, name="predictions")(x)
functional_model = keras.Model(inputs=inputs, outputs=outputs, name="3_layer_mlp")

# Extract a portion of the functional model defined in the Setup section.
# The following lines produce a new model that excludes the final output
# layer of the functional model.
pretrained = keras.Model(
    functional_model.inputs, functional_model.layers[-1].input, name="pretrained_model"
)
# Randomly assign "trained" weights.
for w in pretrained.weights:
    w.assign(tf.random.normal(w.shape))
pretrained.save_weights("pretrained_ckpt")
pretrained.summary()

# Assume this is a separate program where only 'pretrained_ckpt' exists.
# Create a new functional model with a different output dimension.
inputs = keras.Input(shape=(784,), name="digits")
x = keras.layers.Dense(64, activation="relu", name="dense_1")(inputs)
x = keras.layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = keras.layers.Dense(5, name="predictions")(x)
model = keras.Model(inputs=inputs, outputs=outputs, name="new_model")

# Load the weights from pretrained_ckpt into model.
model.load_weights("pretrained_ckpt")

# Check that all of the pretrained weights have been loaded.
for a, b in zip(pretrained.weights, model.weights):
    np.testing.assert_allclose(a.numpy(), b.numpy())

print("\n", "-" * 50)
model.summary()

# Example 2: Sequential model
# Recreate the pretrained model, and load the saved weights.
inputs = keras.Input(shape=(784,), name="digits")
x = keras.layers.Dense(64, activation="relu", name="dense_1")(inputs)
x = keras.layers.Dense(64, activation="relu", name="dense_2")(x)
pretrained_model = keras.Model(inputs=inputs, outputs=x, name="pretrained")

# Sequential example:
model = keras.Sequential([pretrained_model, keras.layers.Dense(5, name="predictions")])
model.summary()

pretrained_model.load_weights("pretrained_ckpt")

# Warning! Calling `model.load_weights('pretrained_ckpt')` won't throw an error,
# but will *not* work as expected. If you inspect the weights, you'll see that
# none of the weights will have loaded. `pretrained_model.load_weights()` is the
# correct method to call.
Model: "pretrained_model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
digits (InputLayer)          [(None, 784)]             0         
_________________________________________________________________
dense_1 (Dense)              (None, 64)                50240     
_________________________________________________________________
dense_2 (Dense)              (None, 64)                4160      
=================================================================
Total params: 54,400
Trainable params: 54,400
Non-trainable params: 0
_________________________________________________________________

 --------------------------------------------------
Model: "new_model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
digits (InputLayer)          [(None, 784)]             0         
_________________________________________________________________
dense_1 (Dense)              (None, 64)                50240     
_________________________________________________________________
dense_2 (Dense)              (None, 64)                4160      
_________________________________________________________________
predictions (Dense)          (None, 5)                 325       
=================================================================
Total params: 54,725
Trainable params: 54,725
Non-trainable params: 0
_________________________________________________________________
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
pretrained (Functional)      (None, 64)                54400     
_________________________________________________________________
predictions (Dense)          (None, 5)                 325       
=================================================================
Total params: 54,725
Trainable params: 54,725
Non-trainable params: 0
_________________________________________________________________
<tensorflow.python.training.tracking.util.CheckpointLoadStatus at 0x7f9aaca76990>

Model oluşturmak için genellikle aynı API'ye bağlı kalmanız önerilir. Sıralı ve İşlevsel veya İşlevsel ve alt sınıflı vb. arasında geçiş yaparsanız, her zaman önceden eğitilmiş modeli yeniden oluşturun ve önceden eğitilmiş ağırlıkları bu modele yükleyin.

Bir sonraki soru, model mimarileri oldukça farklıysa ağırlıklar nasıl kaydedilebilir ve farklı modellere yüklenebilir? Solüsyon kullanmaktır tf.train.Checkpoint kesin katmanlar / değişkenleri kaydetmek ve geri yüklemek için.

Örnek:

# Create a subclassed model that essentially uses functional_model's first
# and last layers.
# First, save the weights of functional_model's first and last dense layers.
first_dense = functional_model.layers[1]
last_dense = functional_model.layers[-1]
ckpt_path = tf.train.Checkpoint(
    dense=first_dense, kernel=last_dense.kernel, bias=last_dense.bias
).save("ckpt")

# Define the subclassed model.
class ContrivedModel(keras.Model):
    def __init__(self):
        super(ContrivedModel, self).__init__()
        self.first_dense = keras.layers.Dense(64)
        self.kernel = self.add_variable("kernel", shape=(64, 10))
        self.bias = self.add_variable("bias", shape=(10,))

    def call(self, inputs):
        x = self.first_dense(inputs)
        return tf.matmul(x, self.kernel) + self.bias


model = ContrivedModel()
# Call model on inputs to create the variables of the dense layer.
_ = model(tf.ones((1, 784)))

# Create a Checkpoint with the same structure as before, and load the weights.
tf.train.Checkpoint(
    dense=model.first_dense, kernel=model.kernel, bias=model.bias
).restore(ckpt_path).assert_consumed()
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/engine/base_layer.py:2223: UserWarning: `layer.add_variable` is deprecated and will be removed in a future version. Please use `layer.add_weight` method instead.
  warnings.warn('`layer.add_variable` is deprecated and '
<tensorflow.python.training.tracking.util.CheckpointLoadStatus at 0x7f9aaca6f390>

HDF5 formatı

HDF5 formatı, katman adlarına göre gruplandırılmış ağırlıklar içerir. Ağırlıklar olmayan eğitilebilen ağırlıkları (aynı listesine eğitilebilen ağırlıkların listesini birleştirerek sıralı listeleri layer.weights ). Bu nedenle, bir model, kontrol noktasında kaydedilenle aynı katmanlara ve eğitilebilir durumlara sahipse bir hdf5 kontrol noktası kullanabilir.

Örnek:

# Runnable example
sequential_model = keras.Sequential(
    [
        keras.Input(shape=(784,), name="digits"),
        keras.layers.Dense(64, activation="relu", name="dense_1"),
        keras.layers.Dense(64, activation="relu", name="dense_2"),
        keras.layers.Dense(10, name="predictions"),
    ]
)
sequential_model.save_weights("weights.h5")
sequential_model.load_weights("weights.h5")

Değişen geldiğini hatırlatırız layer.trainable farklı sonuçlanabilir layer.weights modeli iç içe katmanları içerdiğinde sipariş.

class NestedDenseLayer(keras.layers.Layer):
    def __init__(self, units, name=None):
        super(NestedDenseLayer, self).__init__(name=name)
        self.dense_1 = keras.layers.Dense(units, name="dense_1")
        self.dense_2 = keras.layers.Dense(units, name="dense_2")

    def call(self, inputs):
        return self.dense_2(self.dense_1(inputs))


nested_model = keras.Sequential([keras.Input((784,)), NestedDenseLayer(10, "nested")])
variable_names = [v.name for v in nested_model.weights]
print("variables: {}".format(variable_names))

print("\nChanging trainable status of one of the nested layers...")
nested_model.get_layer("nested").dense_1.trainable = False

variable_names_2 = [v.name for v in nested_model.weights]
print("\nvariables: {}".format(variable_names_2))
print("variable ordering changed:", variable_names != variable_names_2)
variables: ['nested/dense_1/kernel:0', 'nested/dense_1/bias:0', 'nested/dense_2/kernel:0', 'nested/dense_2/bias:0']

Changing trainable status of one of the nested layers...

variables: ['nested/dense_2/kernel:0', 'nested/dense_2/bias:0', 'nested/dense_1/kernel:0', 'nested/dense_1/bias:0']
variable ordering changed: True

Transfer öğrenme örneği

HDF5'ten önceden eğitilmiş ağırlıkları yüklerken, ağırlıkları orijinal kontrol noktası modele yüklemeniz ve ardından istenen ağırlıkları/katmanları yeni bir modele çıkarmanız önerilir.

Örnek:

def create_functional_model():
    inputs = keras.Input(shape=(784,), name="digits")
    x = keras.layers.Dense(64, activation="relu", name="dense_1")(inputs)
    x = keras.layers.Dense(64, activation="relu", name="dense_2")(x)
    outputs = keras.layers.Dense(10, name="predictions")(x)
    return keras.Model(inputs=inputs, outputs=outputs, name="3_layer_mlp")


functional_model = create_functional_model()
functional_model.save_weights("pretrained_weights.h5")

# In a separate program:
pretrained_model = create_functional_model()
pretrained_model.load_weights("pretrained_weights.h5")

# Create a new model by extracting layers from the original model:
extracted_layers = pretrained_model.layers[:-1]
extracted_layers.append(keras.layers.Dense(5, name="dense_3"))
model = keras.Sequential(extracted_layers)
model.summary()
Model: "sequential_6"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 64)                50240     
_________________________________________________________________
dense_2 (Dense)              (None, 64)                4160      
_________________________________________________________________
dense_3 (Dense)              (None, 5)                 325       
=================================================================
Total params: 54,725
Trainable params: 54,725
Non-trainable params: 0
_________________________________________________________________