Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

Simpan dan muat model Keras

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

pengantar

Model Keras terdiri dari beberapa komponen:

  • Arsitektur, atau konfigurasi, yang menentukan lapisan apa yang berisi model, dan bagaimana mereka terhubung.
  • Satu set nilai bobot ("keadaan model").
  • Pengoptimal (ditentukan dengan menyusun model).
  • Serangkaian kerugian dan metrik (ditentukan dengan mengompilasi model atau memanggil add_loss() atau add_metric() ).

Keras API memungkinkan untuk menyimpan bagian-bagian ini ke disk sekaligus, atau hanya menyimpan sebagian secara selektif:

  • Menyimpan semuanya ke dalam satu arsip dalam format TensorFlow SavedModel (atau dalam format Keras H5 yang lebih lama). Ini adalah praktik standar.
  • Menyimpan arsitektur / konfigurasi saja, biasanya sebagai file JSON.
  • Menyimpan nilai bobot saja. Ini biasanya digunakan saat melatih model.

Mari kita lihat masing-masing opsi ini: kapan Anda akan menggunakan salah satunya? Bagaimana mereka bekerja?

Jawaban singkat untuk menyimpan & memuat

Jika Anda hanya memiliki 10 detik untuk membaca panduan ini, inilah yang perlu Anda ketahui.

Menyimpan model Keras:

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

Memuat model kembali:

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

Sekarang, mari kita lihat detailnya.

Mempersiapkan

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

Penghematan & pemuatan seluruh model

Anda dapat menyimpan seluruh model ke satu artefak. Ini akan mencakup:

  • Arsitektur / konfigurasi model
  • Nilai berat model (yang dipelajari selama pelatihan)
  • Informasi kompilasi model (jika compile() ) dipanggil
  • Pengoptimal dan statusnya, jika ada (ini memungkinkan Anda untuk memulai kembali pelatihan di mana Anda tinggalkan)

Lebah

Ada dua format yang dapat Anda gunakan untuk menyimpan seluruh model ke disk: format TensorFlow SavedModel , dan format Keras H5 yang lebih lama . Format yang direkomendasikan adalah SavedModel. Ini adalah default saat Anda menggunakan model.save() .

Anda dapat beralih ke format H5 dengan:

  • Lewat save_format='h5' untuk save() .
  • Meneruskan nama file yang diakhiri dengan .h5 atau .keras to save() .

Format SavedModel

Contoh:

 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 [==============================] - 0s 1ms/step - loss: 1.1917
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/resource_variable_ops.py:1817: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
INFO:tensorflow:Assets written to: my_model/assets
4/4 [==============================] - 0s 1ms/step - loss: 1.0581

<tensorflow.python.keras.callbacks.History at 0x7f13700096d8>

Isi dari SavedModel

Memanggil model.save('my_model') membuat folder bernama my_model , berisi yang berikut:

ls my_model
assets  saved_model.pb  variables

Arsitektur model, dan konfigurasi pelatihan (termasuk pengoptimal, kerugian, dan metrik) disimpan di saved_model.pb . Bobot disimpan dalam variables/ direktori.

Untuk informasi terperinci tentang format SavedModel, lihat panduan SavedModel ( Format SavedModel pada disk ) .

Bagaimana SavedModel menangani objek khusus

Saat menyimpan model dan lapisannya, format SavedModel menyimpan nama kelas, fungsi panggilan , kehilangan, dan bobot (dan konfigurasi, jika diterapkan). Fungsi panggilan mendefinisikan grafik komputasi model / lapisan.

Dengan tidak adanya konfigurasi model / lapisan, fungsi panggilan digunakan untuk membuat model yang ada seperti model asli yang dapat dilatih, dievaluasi, dan digunakan untuk inferensi.

Namun demikian, itu selalu merupakan praktik yang baik untuk mendefinisikan metode get_config dan from_config saat menulis model kustom atau kelas lapisan. Ini memungkinkan Anda untuk dengan mudah memperbarui komputasi nanti jika diperlukan. Lihat bagian tentang objek Kustom untuk informasi lebih lanjut.

Di bawah ini adalah contoh dari apa yang terjadi saat memuat lapisan kustom dari format SavedModel tanpa menimpa metode konfigurasi.

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


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

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

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

print("Original model:", model)
print("Loaded model:", loaded)
 
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.
Original model: <__main__.CustomModel object at 0x7f1370081550>
Loaded model: <tensorflow.python.keras.saving.saved_model.load.CustomModel object at 0x7f1328722e48>

Seperti yang terlihat pada contoh di atas, loader secara dinamis membuat kelas model baru yang bertindak seperti model aslinya.

Format Keras H5

Keras juga mendukung penyimpanan satu file HDF5 yang berisi arsitektur model, nilai bobot, dan informasi compile() . Ini adalah alternatif ringan untuk SavedModel.

Contoh:

 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: 4.1064
4/4 [==============================] - 0s 1ms/step - loss: 3.8469

<tensorflow.python.keras.callbacks.History at 0x7f14171934a8>

Batasan

Dibandingkan dengan format SavedModel, ada dua hal yang tidak disertakan dalam file H5:

  • Kerugian eksternal & metrik yang ditambahkan melalui model.add_loss() & model.add_metric() tidak disimpan (tidak seperti SavedModel). Jika Anda memiliki kerugian & metrik seperti itu pada model Anda dan Anda ingin melanjutkan pelatihan, Anda perlu menambahkan kembali kerugian ini setelah memuat model. Perhatikan bahwa ini tidak berlaku untuk kerugian / metrik yang dibuat di dalam lapisan melalui self.add_loss() & self.add_metric() . Selama lapisan tersebut dimuat, kerugian & metrik ini disimpan, karena merupakan bagian dari metode call lapisan tersebut.
  • Grafik komputasi objek kustom seperti lapisan kustom tidak disertakan dalam file yang disimpan. Pada waktu pemuatan, Keras membutuhkan akses ke kelas / fungsi Python dari objek ini untuk merekonstruksi model. Lihat Objek kustom .

Menyimpan arsitektur

Konfigurasi model (atau arsitektur) menentukan lapisan apa yang dikandung model, dan bagaimana lapisan ini terhubung *. Jika Anda memiliki konfigurasi model, maka model dapat dibuat dengan status yang baru diinisialisasi untuk bobot dan tidak ada informasi kompilasi.

* Perhatikan bahwa ini hanya berlaku untuk model yang ditentukan menggunakan model fungsional atau Sequential apis not subclassed.

Konfigurasi model Sequential atau model Fungsional API

Jenis model ini adalah grafik lapisan eksplisit: konfigurasinya selalu tersedia dalam bentuk terstruktur.

Lebah

get_config() dan from_config()

Memanggil config = model.get_config() akan mengembalikan config = model.get_config() Python yang berisi konfigurasi model. Model yang sama kemudian dapat direkonstruksi melalui Sequential.from_config(config) (untuk model Sequential ) atau Model.from_config(config) (untuk model API Fungsional).

Alur kerja yang sama juga berfungsi untuk semua lapisan yang dapat diserialkan.

Contoh lapisan:

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

Contoh model sekuensial:

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

Contoh model fungsional:

 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() dan tf.keras.models.model_from_json()

Ini mirip dengan get_config / from_config , kecuali itu mengubah model menjadi string JSON, yang kemudian dapat dimuat tanpa kelas model asli. Ini juga khusus untuk model, ini tidak dimaksudkan untuk lapisan.

Contoh:

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

Objek khusus

Model dan lapisan

Arsitektur model dan lapisan subclass didefinisikan dalam metode __init__ dan call . Mereka dianggap bytecode Python, yang tidak dapat diserialisasi ke dalam konfigurasi yang kompatibel dengan JSON - Anda dapat mencoba membuat serial bytecode (misalnya melalui pickle ), tetapi sama sekali tidak aman dan berarti model Anda tidak dapat dimuat pada sistem yang berbeda.

Untuk menyimpan / memuat model dengan lapisan yang ditentukan khusus, atau model subclass, Anda harus menimpa get_config dan secara opsional from_config metode. Selain itu, Anda harus menggunakan register objek kustom sehingga Keras menyadarinya.

Fungsi kustom

Fungsi yang ditentukan khusus (mis. Kehilangan aktivasi atau inisialisasi) tidak memerlukan metode get_config . Nama fungsi cukup untuk memuat selama itu terdaftar sebagai objek khusus.

Memuat grafik TensorFlow saja

Ini mungkin untuk memuat grafik TensorFlow yang dihasilkan oleh Keras. Jika Anda melakukannya, Anda tidak perlu memberikan custom_objects . Anda dapat melakukannya seperti ini:

 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

Perhatikan bahwa metode ini memiliki beberapa kekurangan:

  • Untuk alasan ketertelusuran, Anda harus selalu memiliki akses ke objek kustom yang digunakan. Anda tidak ingin memasukkan model yang tidak dapat Anda buat ulang ke dalam produksi.
  • Objek yang dikembalikan oleh tf.saved_model.load bukanlah model Keras. Jadi tidak mudah digunakan. Misalnya, Anda tidak akan memiliki akses ke .predict() atau .fit()

Meskipun penggunaannya tidak disarankan, ini dapat membantu Anda jika Anda berada dalam tf.keras.models.load_model() , misalnya, jika Anda kehilangan kode objek khusus atau mengalami masalah saat memuat model dengan tf.keras.models.load_model() .

Anda dapat mengetahui lebih lanjut di halaman tentang tf.saved_model.load

Mendefinisikan metode konfigurasi

Spesifikasi:

  • get_config harus mengembalikan kamus yang dapat diserialkan JSON agar kompatibel dengan arsitektur Keras- dan API penyimpanan model.
  • from_config(config) ( classmethod ) harus mengembalikan lapisan baru atau objek model yang dibuat dari konfigurasi. Implementasi default mengembalikan cls(**config) .

Contoh:

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

Mendaftarkan objek khusus

Keras menyimpan catatan kelas mana yang menghasilkan konfigurasi. Dari contoh di atas, tf.keras.layers.serialize menghasilkan bentuk serial dari lapisan kustom:

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

Keras menyimpan daftar master dari semua kelas lapisan, model, pengoptimal, dan metrik from_config , yang digunakan untuk menemukan kelas yang benar untuk dipanggil from_config . Jika kelas tidak dapat ditemukan, maka akan muncul kesalahan ( Value Error: Unknown layer ). Ada beberapa cara untuk mendaftarkan kelas khusus ke daftar ini:

  1. Menyetel argumen custom_objects dalam fungsi pemuatan. (lihat contoh di bagian atas "Menentukan metode konfigurasi")
  2. tf.keras.utils.custom_object_scope atau tf.keras.utils.CustomObjectScope
  3. tf.keras.utils.register_keras_serializable

Lapisan kustom dan contoh fungsi

 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)
 

Kloning model dalam memori

Anda juga dapat melakukan kloning dalam memori dari suatu model melalui tf.keras.models.clone_model() . Ini sama dengan mendapatkan konfigurasi lalu membuat ulang model dari konfigurasinya (sehingga tidak menyimpan informasi kompilasi atau nilai bobot lapisan).

Contoh:

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

Menyimpan & memuat hanya nilai bobot model

Anda dapat memilih untuk hanya menyimpan & memuat bobot model. Ini dapat bermanfaat jika:

  • Anda hanya memerlukan model untuk inferensi: dalam hal ini Anda tidak perlu memulai ulang pelatihan, jadi Anda tidak memerlukan informasi kompilasi atau status pengoptimal.
  • Anda sedang melakukan pembelajaran transfer: dalam hal ini Anda akan melatih model baru menggunakan kembali status model sebelumnya, jadi Anda tidak memerlukan informasi kompilasi dari model sebelumnya.

API untuk transfer berat dalam memori

Bobot dapat disalin di antara objek yang berbeda dengan menggunakan get_weights dan set_weights :

Contoh di bawah ini.

Mentransfer bobot dari satu lapisan ke lapisan lainnya, dalam memori

 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 2 to layer 1
layer_2.set_weights(layer_1.get_weights())
 

Mentransfer bobot dari satu model ke model lain dengan arsitektur yang kompatibel, dalam memori

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

Kasus lapisan tanpa negara

Karena lapisan stateless tidak mengubah urutan atau jumlah bobot, model dapat memiliki arsitektur yang kompatibel bahkan jika ada lapisan stateless tambahan / hilang.

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

API untuk menyimpan bobot ke disk & memuatnya kembali

Berat dapat disimpan ke disk dengan memanggil model.save_weights dalam format berikut:

  • TensorFlow Checkpoint
  • HDF5

Format default untuk model.save_weights adalah pos pemeriksaan TensorFlow. Ada dua cara untuk menentukan format penyimpanan:

  1. Argumen save_format : Setel nilai ke save_format="tf" atau save_format="h5" .
  2. argumen path : Jika jalur diakhiri dengan .h5 atau .hdf5 , maka format HDF5 akan digunakan. Sufiks lain akan menghasilkan checkpoint save_format kecuali save_format disetel.

Ada juga opsi untuk mengambil bobot sebagai array numpy dalam memori. Setiap API memiliki pro dan kontra mereka yang dirinci di bawah ini.

Format TF Checkpoint

Contoh:

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

Detail format

Format TensorFlow Checkpoint menyimpan dan mengembalikan bobot menggunakan nama atribut objek. Misalnya, pertimbangkan lapisan tf.keras.layers.Dense . Lapisan tersebut berisi dua bobot: dense.kernel dan dense.bias . Ketika lapisan disimpan ke format tf , hasil pemeriksaan berisi kunci "kernel" dan "bias" dan nilai bobot yang sesuai. Untuk informasi lebih lanjut, lihat "Mekanika pemuatan" di panduan TF Checkpoint .

Perhatikan bahwa tepi atribut / grafik dinamai setelah nama yang digunakan dalam objek induk, bukan nama variabel . Pertimbangkan CustomLayer pada contoh di bawah ini. Variabel CustomLayer.var disimpan dengan "var" sebagai bagian dari kunci, bukan "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}

Contoh pembelajaran transfer

Intinya, selama dua model memiliki arsitektur yang sama, mereka dapat berbagi pos pemeriksaan yang sama.

Contoh:

 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 (Model)           (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 0x7f1416704278>

Biasanya disarankan untuk tetap menggunakan API yang sama untuk membuat model. Jika Anda beralih antara Berurutan dan Fungsional, atau Fungsional dan subkelas, dll., Maka selalu buat ulang model yang telah dilatih sebelumnya dan muat bobot yang telah dilatih sebelumnya ke model tersebut.

Pertanyaan berikutnya adalah, bagaimana bobot dapat disimpan dan dimuat ke model yang berbeda jika arsitektur model sangat berbeda? Solusinya adalah dengan menggunakan tf.train.Checkpoint untuk menyimpan dan memulihkan lapisan / variabel yang tepat.

Contoh:

 # 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()
 
WARNING:tensorflow:From <ipython-input-21-eec1d28bc826>:15: Layer.add_variable (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.
Instructions for updating:
Please use `layer.add_weight` method instead.

<tensorflow.python.training.tracking.util.CheckpointLoadStatus at 0x7f1416713358>

Format HDF5

Format HDF5 berisi bobot yang dikelompokkan berdasarkan nama lapisan. Bobot adalah daftar yang diurutkan dengan menggabungkan daftar bobot yang dapat dilatih ke daftar bobot yang tidak dapat dilatih (sama seperti layer.weights ). Jadi, model dapat menggunakan checkpoint hdf5 jika memiliki lapisan yang sama dan status dapat dilatih seperti yang disimpan di pos pemeriksaan.

Contoh:

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

Perhatikan bahwa mengubah layer.trainable dapat mengakibatkan layer.weights memesan yang berbeda ketika model berisi layer bersarang.

 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

Contoh pembelajaran transfer

Saat memuat anak timbangan yang telah dilatih sebelumnya dari HDF5, disarankan untuk memuat anak timbangan tersebut ke dalam model pos pemeriksaan asli, dan kemudian mengekstrak bobot / lapisan yang diinginkan ke dalam model baru.

Contoh:

 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
_________________________________________________________________