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 Defteri indirin

Giriş

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

  • Modelin hangi katmanları içerdiğini ve nasıl bağlandıklarını belirten mimari veya konfigürasyon.
  • Bir dizi ağırlık değeri ("modelin durumu").
  • Bir iyileştirici (modeli derleyerek tanımlanır).
  • Bir dizi kayıp ve ölçüm (modeli derleyerek veya add_loss() veya add_metric() çağırarak tanımlanır).

Keras API, tüm bu parçaları tek seferde diske kaydetmeyi veya yalnızca bazılarını seçmeli olarak kaydetmeyi mümkün kılar:

  • Her şeyi TensorFlow SavedModel biçiminde (veya daha eski Keras H5 biçiminde) tek bir arşive kaydetme. Bu standart uygulamadır.
  • Yalnızca mimariyi / yapılandırmayı, genellikle bir JSON dosyası olarak kaydetme.
  • Yalnızca ağırlık değerlerini kaydetme. 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, işte bilmeniz gerekenler.

Bir 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.

Kurulum

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 yapıya kaydedebilirsiniz. Şunları içerecektir:

  • Modelin mimarisi / yapılandırması
  • Modelin ağırlık değerleri (eğitim sırasında öğrenilenler)
  • Modelin derleme bilgileri ( compile() çağrıldıysa)
  • Optimize edici ve varsa durumu (bu, eğitimi kaldığınız yerden yeniden başlatmanıza olanak tanır)

API'ler

Tüm modeli diske kaydetmek için kullanabileceğiniz iki format vardır: TensorFlow SavedModel formatı ve daha eski Keras H5 formatı . Önerilen biçim SavedModel'dir. model.save() kullandığınızda varsayılandır.

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

  • save_format='h5' save() için save_format='h5' .
  • save() .keras için .h5 veya .keras ile biten bir dosya adı .h5 .

SavedModel biçimi

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

Misal:

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.9237
INFO:tensorflow:Assets written to: my_model/assets
4/4 [==============================] - 0s 1ms/step - loss: 0.7730
<tensorflow.python.keras.callbacks.History at 0x7fd0a032a390>

SavedModel'in içeriği

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

ls my_model
assets  saved_model.pb  variables

Model mimarisi ve eğitim yapılandırması (optimize edici, kayıplar ve ölçümler dahil) saved_model.pb saklanır. Ağırlıklar variables/ dizinine kaydedilir.

SavedModel formatı hakkında ayrıntılı bilgi için, SavedModel kılavuzuna ( diskteki SavedModel formatı ) bakın .

SavedModel özel nesneleri nasıl işler?

Modeli ve katmanlarını kaydederken, SavedModel biçimi sınıf adını, çağrı işlevini , kayıpları ve ağırlıkları (ve uygulanmışsa yapılandırmayı) depolar. Ç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, özel bir model veya katman sınıfı yazarken get_config ve from_config yöntemlerini tanımlamak her zaman iyi bir uygulamadır. Bu, gerekirse hesaplamayı daha sonra kolayca güncellemenizi sağlar. Daha fazla bilgi için Özel nesnelerle ilgili bölüme bakın.

Misal:

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 0x7fd0a035bcf8>
Model Loaded with custom objects: <__main__.CustomModel object at 0x7fd1455d04e0>
Model loaded without the custom object class: <tensorflow.python.keras.saving.saved_model.load.CustomModel object at 0x7fd14553af98>

İlk yüklenen model, config ve CustomModel sınıfı kullanılarak yüklenir. İkinci model, orijinal model gibi davranan model sınıfının dinamik olarak oluşturulmasıyla 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, save_traces=False orijinal sınıf save_traces=False olmadan özel nesneleri yeniden yüklemesine izin vermek için kaydedilir, bu nedenle, save_traces=False olduğunda, tüm özel nesnelerin tanımlanmış get_config / from_config yöntemleri olması gerekir. Yükleme sırasında, özel nesneler custom_objects bağımsız değişkenine custom_objects . save_traces=False , SavedModel tarafından kullanılan disk alanını azaltır ve zamandan tasarruf sağlar.

Keras H5 biçimi

Keras ayrıca modelin mimarisini, ağırlık değerlerini ve compile() bilgilerini içeren tek bir HDF5 dosyasını kaydetmeyi destekler. SavedModel'e hafif bir alternatiftir.

Misal:

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.0153
4/4 [==============================] - 0s 1ms/step - loss: 0.9104
<tensorflow.python.keras.callbacks.History at 0x7fd1455c66a0>

Sınırlamalar

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

  • model.add_loss() ve model.add_metric() aracılığıyla eklenen harici kayıplar ve metrikler kaydedilmez (SavedModel'den farklı olarak). Modelinizde bu tür kayıplar ve metrikler varsa ve eğitime devam etmek istiyorsanız, modeli yükledikten sonra bu kayıpları kendiniz geri eklemeniz gerekir. Bunun katmanların içinde self.add_loss() & self.add_metric() aracılığıyla oluşturulan kayıplar / metrikler için geçerli olmadığını unutmayın. Katman yüklendiği sürece, bu kayıplar ve ölçümler, katmanın call yönteminin bir parçası oldukları için korunur.
  • Özel katmanlar gibi özel nesnelerin hesaplama grafiği kaydedilen dosyaya dahil edilmez. Yükleme sırasında, Keras'ın modeli yeniden yapılandırmak için bu nesnelerin Python sınıflarına / işlevlerine erişmesi gerekecektir. Bkz. Özel nesneler .

Mimariyi kurtarmak

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

* Bunun yalnızca, alt sınıflara dahil olmayan fonksiyonel veya Sıralı apis modelleri kullanılarak tanımlanan modeller için geçerli olduğunu unutmayın.

Sıralı bir modelin veya İşlevsel API modelinin yapılandırması

Bu tür modeller, katmanların açık grafikleridir: yapılandırmaları her zaman yapılandırılmış bir formda mevcuttur.

API'ler

get_config() ve from_config()

config = model.get_config() , modelin yapılandırmasını içeren bir Python config = model.get_config() döndürülür. Aynı model daha sonra Sequential.from_config(config) ( Sequential model için) veya Model.from_config(config) (bir Fonksiyonel API modeli için) aracılığıyla yeniden Sequential.from_config(config) .

Aynı iş akışı, herhangi bir serileştirilebilir 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)

İşlevsel 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, modeli bir JSON dizesine dönüştürmesi dışında get_config / from_config ile benzerdir ve daha sonra orijinal model sınıfı olmadan yüklenebilir. Aynı zamanda modellere özeldir, katmanlara yönelik değildir.

Misal:

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

Alt sınıflara ayrılmış modellerin ve katmanların mimarisi __init__ ve call yöntemlerinde tanımlanır. JSON uyumlu bir yapılandırmada serileştirilemeyen Python bayt kodu olarak kabul edilirler - bayt kodunu serileştirmeyi deneyebilirsiniz (örn. pickle yoluyla), ancak bu tamamen güvensizdir ve modelinizin farklı bir sisteme yüklenemeyeceği anlamına gelir.

Özel tanımlı katmanlara sahip bir modeli veya alt get_config bir modeli kaydetmek / yüklemek için get_config ve isteğe bağlı olarak from_config yöntemlerinin üzerine yazmanız gerekir. Ek olarak, Keras'ın farkında olması için özel nesneyi kaydettirmelisiniz.

Özel işlevler

Özel tanımlı işlevler (örn. Aktivasyon kaybı veya başlatma) bir get_config yöntemine ihtiyaç get_config . İş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 yaparsanız, herhangi bir custom_objects sağlamanız 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()
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.
  • tf.saved_model.load tarafından döndürülen nesne bir tf.saved_model.load modeli değildir. Yani kullanımı o kadar kolay değil. Örneğin, .predict() veya .fit() erişiminiz olmayacak

Kullanımı tavsiye tf.keras.models.load_model() bile, dar bir noktadaysanız, örneğin özel nesnelerinizin kodunu kaybettiyseniz veya modeli tf.keras.models.load_model() ile yüklerken sorun yaşıyorsanız size yardımcı olabilir.

tf.saved_model.load ilgili sayfada daha fazla bilgi tf.saved_model.load

Yapılandırma yöntemlerini tanımlama

Özellikler:

  • get_config , get_config mimarisi ve model tasarrufu sağlayan API'lerle uyumlu olması için bir JSON serileştirilebilir sözlük döndürmelidir.
  • from_config(config) ( classmethod ), yapılandırmadan oluşturulan yeni bir katman veya model nesnesi döndürmelidir. Varsayılan uygulama cls(**config) döndürür.

Misal:

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ğuna dair bir not tutar. Yukarıdaki örnekten, tf.keras.layers.serialize özel katmanın serileştirilmiş bir biçimini oluşturur:

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

from_config doğru sınıfı bulmak için kullanılan tüm yerleşik katman, model, optimize edici ve metrik sınıflarının ana listesini tutar. Sınıf bulunamazsa, bir hata oluşur ( Value Error: Unknown layer ). Bu listeye özel sınıfları kaydetmenin birkaç yolu vardır:

  1. Yükleme işlevinde custom_objects bağımsız değişkeni ayarlanıyor. ("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 tf.keras.models.clone_model() aracılığıyla bir modelin bellek içi klonlamasını da yapabilirsiniz. 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ıkları değerlerini korumaz).

Misal:

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

Sadece 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:

  • Yalnızca çıkarım için modele ihtiyacınız vardır: bu durumda eğitimi yeniden başlatmanız gerekmeyecektir, bu nedenle derleme bilgilerine veya optimize edici durumuna ihtiyacınız olmaz.
  • Transfer öğrenimi yapıyorsunuz: bu durumda, önceki modelin durumunu yeniden kullanarak yeni bir model eğitiyor olacaksınız, böylece önceki modelin derleme bilgilerine ihtiyacınız olmayacak.

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

get_weights ve set_weights kullanılarak farklı nesneler arasında ağırlıklar kopyalanabilir:

Aşağıdaki örnekler.

Hafızada bir katmandan diğerine ağırlık aktarımı

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())

Hafızada, uyumlu bir mimariye sahip bir modelden başka bir modele ağırlık aktarımı

# 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())

Vatansız katman durumu

Durum bilgisi olmayan katmanlar, ağırlıkların sırasını veya sayısını değiştirmediğinden, modeller, fazladan / eksik durum bilgisiz katmanlar olsa bile 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şağıdaki formatlarda model.save_weights ağırlıklar diske kaydedilebilir:

  • TensorFlow Kontrol Noktası
  • HDF5

model.save_weights için varsayılan biçim TensorFlow denetim noktasıdır. Kaydetme biçimini belirlemenin iki yolu vardır:

  1. save_format bağımsız değişkeni: Değeri save_format="tf" veya save_format="h5" .
  2. path bağımsız değişkeni: Yol .h5 veya .hdf5 ile .h5 , HDF5 biçimi kullanılır. save_format ayarlanmadıkça diğer son ekler bir TensorFlow denetim noktasıyla sonuçlanır.

Bellek içi numpy dizileri olarak ağırlıkları alma seçeneği de vardır. Her API'nin avantajları ve dezavantajları vardır ve bunlar aşağıda ayrıntılı olarak verilmiştir.

TF Kontrol noktası biçimi

Misal:

# 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 0x7fd0a065f128>

Biçim ayrıntıları

TensorFlow Checkpoint biçimi, ağırlıkları nesne öznitelik adlarını kullanarak kaydeder ve geri yükler. Örneğin, tf.keras.layers.Dense katmanını düşünün. Katman iki ağırlık içerir: dense.kernel ve dense.bias . Katman tf formatında kaydedildiğinde, elde edilen kontrol noktası "kernel" ve "bias" anahtarlarını ve bunlara karşılık gelen ağırlık değerlerini içerir. Daha fazla bilgi için , TF Kontrol Noktası kılavuzundaki "Yükleme mekaniği" bölümüne bakın.

Öznitelik / grafik kenarının, değişkenin adından değil, ana nesnede kullanılan addan sonra adlandırıldığını unutmayın. Aşağıdaki örnekte CustomLayer düşünün. CustomLayer.var değişkeni, anahtarın parçası olarak "var_a" yerine "var" ile kaydedilir.

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 öğrenimi örneği

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

Misal:

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 0x7fd144b20b38>

Model oluşturmak için genellikle aynı API'ye bağlı kalınması önerilir. Sıralı ve İşlevsel veya İşlevsel ve alt sınıf 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.

Sonraki soru, model mimarileri oldukça farklıysa ağırlıklar nasıl kaydedilebilir ve farklı modellere yüklenebilir? Çözüm, tam katmanları / değişkenleri kaydetmek ve geri yüklemek için tf.train.Checkpoint kullanmaktır.

Misal:

# 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.6/site-packages/tensorflow/python/keras/engine/base_layer.py:2281: 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 0x7fd1455c6cc0>

HDF5 biçimi

HDF5 formatı, katman adlarına göre gruplandırılmış ağırlıkları içerir. Ağırlıklar, eğitilebilir ağırlıklar listesinin layer.weights ağırlıklar listesine ( layer.weights ağırlıkları ile aynı) birleştirilmesiyle sıralanan listelerdir. Bu nedenle, bir model, kontrol noktasında kaydedilenle aynı katmanlara ve eğitilebilir durumlara sahipse bir hdf5 kontrol noktası kullanabilir.

Misal:

# 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")

layer.trainable değiştirilmesinin, model iç içe katmanlar içerdiğinde farklı bir layer.weights sıralamasına neden olabileceğini unutmayın.

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 öğrenimi örneği

HDF5'ten önceden eğitilmiş ağırlıkları yüklerken, ağırlıkların orijinal kontrol noktalı modele yüklenmesi ve ardından istenen ağırlıkların / katmanların yeni bir modele çıkarılması önerilir.

Misal:

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
_________________________________________________________________