केरस मॉडल सहेजें और लोड करें

TensorFlow.org पर देखें Google Colab में चलाएं GitHub पर स्रोत देखें नोटबुक डाउनलोड करें

परिचय

एक केरस मॉडल में कई घटक होते हैं:

  • आर्किटेक्चर, या कॉन्फ़िगरेशन, जो निर्दिष्ट करता है कि मॉडल में कौन सी परतें हैं, और वे कैसे जुड़े हुए हैं।
  • वज़न मानों का एक सेट ("मॉडल की स्थिति")।
  • एक अनुकूलक (मॉडल को संकलित करके परिभाषित)।
  • नुकसान और मीट्रिक का सेट (मॉडल संकलन या फोन करके परिभाषित add_loss() या add_metric() )।

केरस एपीआई इन सभी टुकड़ों को एक बार में डिस्क पर सहेजना संभव बनाता है, या केवल उनमें से कुछ को चुनिंदा रूप से सहेजना संभव बनाता है:

  • TensorFlow SavedModel प्रारूप (या पुराने Keras H5 प्रारूप में) में सब कुछ एक संग्रह में सहेजा जा रहा है। यह मानक अभ्यास है।
  • केवल आर्किटेक्चर/कॉन्फ़िगरेशन को सहेजना, आमतौर पर JSON फ़ाइल के रूप में।
  • केवल वज़न मानों को सहेजना। यह आमतौर पर मॉडल को प्रशिक्षित करते समय उपयोग किया जाता है।

आइए इनमें से प्रत्येक विकल्प पर एक नज़र डालें। आप एक या दूसरे का उपयोग कब करेंगे और वे कैसे काम करते हैं?

मॉडल को कैसे सेव और लोड करें

यदि आपके पास इस गाइड को पढ़ने के लिए केवल 10 सेकंड हैं, तो आपको यह जानने की आवश्यकता है।

एक केरस मॉडल सहेजा जा रहा है:

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

मॉडल वापस लोड हो रहा है:

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

अब, आइए विवरण देखें।

सेट अप

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

पूरे मॉडल की बचत और लोडिंग

आप एक पूरे मॉडल को एक आर्टिफैक्ट में सहेज सकते हैं। इसमें शामिल होंगे:

  • मॉडल का आर्किटेक्चर/कॉन्फ़िगरेशन
  • मॉडल के वजन मान (जो प्रशिक्षण के दौरान सीखे गए थे)
  • मॉडल के संकलन जानकारी (यदि compile() कहा जाता था)
  • ऑप्टिमाइज़र और उसकी स्थिति, यदि कोई हो (यह आपको प्रशिक्षण को फिर से शुरू करने में सक्षम बनाता है जहाँ आपने छोड़ा था)

शहद की मक्खी

TensorFlow SavedModel प्रारूप, और पुराने Keras H5 प्रारूप: वहाँ दो प्रारूपों आप डिस्क के लिए एक पूरे मॉडल को बचाने के लिए उपयोग कर सकते हैं। अनुशंसित प्रारूप सहेजा गया मॉडल है। जब आप का उपयोग यह डिफ़ॉल्ट है model.save()

आप H5 प्रारूप में स्विच कर सकते हैं:

  • पासिंग save_format='h5' को save()
  • एक फ़ाइल नाम पासिंग में समाप्त हो जाती है कि .h5 या .keras को save()

सहेजा गया मॉडल प्रारूप

SavedModel अधिक व्यापक सेव फॉर्मेट है जो मॉडल आर्किटेक्चर, वेट और कॉल फंक्शन के ट्रेस किए गए Tensorflow सबग्राफ को सेव करता है। यह केरस को अंतर्निहित परतों के साथ-साथ कस्टम ऑब्जेक्ट दोनों को पुनर्स्थापित करने में सक्षम बनाता है।

उदाहरण:

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>

सहेजे गए मॉडल में क्या शामिल है

कॉलिंग model.save('my_model') नाम का एक फ़ोल्डर बनाता है my_model , निम्नलिखित युक्त

ls my_model
assets  keras_metadata.pb  saved_model.pb  variables

मॉडल वास्तुकला, और प्रशिक्षण विन्यास (अनुकूलक, हानि, और मीट्रिक सहित) में जमा हो जाती saved_model.pb । वजन में सहेजे जाते हैं variables/ निर्देशिका।

SavedModel प्रारूप के बारे में विस्तृत जानकारी के लिए, SavedModel गाइड (डिस्क पर SavedModel प्रारूप)

कैसे सहेजा गया मॉडल कस्टम ऑब्जेक्ट्स को संभालता है

जब मॉडल और उसके परतें, SavedModel प्रारूप भंडार वर्ग के नाम, कॉल समारोह, हानि, और वजन बचत (और config, अगर लागू किया)। कॉल फ़ंक्शन मॉडल/परत के गणना ग्राफ को परिभाषित करता है।

मॉडल/लेयर कॉन्फिगरेशन के अभाव में, कॉल फंक्शन का उपयोग ऐसे मॉडल को बनाने के लिए किया जाता है जो मूल मॉडल की तरह मौजूद होता है जिसे प्रशिक्षित, मूल्यांकन और अनुमान के लिए इस्तेमाल किया जा सकता है।

फिर भी, यह हमेशा परिभाषित करने के लिए एक अच्छा अभ्यास है get_config और from_config जब कस्टम मॉडल या परत वर्ग लेखन तरीकों। यह आपको जरूरत पड़ने पर बाद में गणना को आसानी से अपडेट करने की अनुमति देता है। के बारे में अनुभाग देखें कस्टम वस्तुओं और जानकारी के लिए।

उदाहरण:

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>

पहले से भरी हुई मॉडल config और का उपयोग कर भरी हुई है CustomModel वर्ग। दूसरा मॉडल गतिशील रूप से मॉडल वर्ग बनाकर लोड किया जाता है जो मूल मॉडल की तरह कार्य करता है।

सहेजे गए मॉडल को कॉन्फ़िगर करना

नई TensoFlow 2.4 में तर्क save_traces में जोड़ा गया है model.save , जो आप टॉगल SavedModel समारोह ट्रेसिंग करने के लिए अनुमति देता है। कार्य मूल वर्ग definitons बिना फिर से लोड कस्टम वस्तुओं के लिए Keras अनुमति देने के लिए सहेजे जाते हैं, इसलिए जब save_traces=False , सभी कस्टम वस्तुओं को परिभाषित किया है चाहिए get_config / from_config तरीकों। जब लोड हो रहा है, कस्टम वस्तुओं को भेजे जाने चाहिए custom_objects तर्क। save_traces=False डिस्क SavedModel और बचत समय द्वारा प्रयोग किया जाता अंतरिक्ष कम कर देता है।

केरस एच५ प्रारूप

Keras भी मॉडल की वास्तुकला, वजन मूल्यों, और वाली एकल HDF5 फ़ाइल को सहेजने का समर्थन करता है compile() जानकारी। यह SavedModel का एक हल्का-फुल्का विकल्प है।

उदाहरण:

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>

सीमाओं

SavedModel प्रारूप की तुलना में, दो चीजें हैं जो H5 फ़ाइल में शामिल नहीं होती हैं:

  • बाहरी घाटे और मीट्रिक के माध्यम से शामिल की model.add_loss() और model.add_metric() (SavedModel के विपरीत) बचाया नहीं गया है। यदि आपके मॉडल पर इस तरह के नुकसान और मेट्रिक्स हैं और आप प्रशिक्षण फिर से शुरू करना चाहते हैं, तो आपको मॉडल लोड करने के बाद इन नुकसानों को खुद वापस जोड़ना होगा। ध्यान दें कि यह माध्यम से परतों के अंदर बनाई नुकसान / मीट्रिक पर लागू नहीं होता self.add_loss() और self.add_metric() । जब तक परत लोड हो जाता है के रूप में, इन नुकसानों और मीट्रिक के रखा जाता है, क्योंकि वे का हिस्सा हैं call परत की विधि।
  • कस्टम की गणना ग्राफ इस तरह की वस्तुओं के रूप में कस्टम परतों सहेजी गई फ़ाइल में शामिल नहीं है। लोडिंग समय पर, मॉडल को फिर से संगठित करने के लिए केरस को इन वस्तुओं के पायथन वर्गों/कार्यों तक पहुंच की आवश्यकता होगी। देखें कस्टम वस्तुओं

वास्तुकला को सहेजना

मॉडल का कॉन्फ़िगरेशन (या आर्किटेक्चर) निर्दिष्ट करता है कि मॉडल में कौन सी परतें हैं, और ये परतें कैसे जुड़ी हुई हैं*। यदि आपके पास किसी मॉडल का कॉन्फ़िगरेशन है, तो मॉडल को वज़न के लिए नए सिरे से आरंभिक स्थिति के साथ बनाया जा सकता है और कोई संकलन जानकारी नहीं है।

*ध्यान दें कि यह केवल कार्यात्मक या अनुक्रमिक एपिस का उपयोग करके परिभाषित मॉडलों पर लागू होता है न कि उप-वर्गीकृत मॉडल पर।

अनुक्रमिक मॉडल या कार्यात्मक एपीआई मॉडल का विन्यास

इस प्रकार के मॉडल परतों के स्पष्ट रेखांकन हैं: उनका विन्यास हमेशा एक संरचित रूप में उपलब्ध होता है।

शहद की मक्खी

get_config() और from_config()

कॉलिंग config = model.get_config() मॉडल के विन्यास युक्त एक अजगर dict वापस आ जाएगी। एक ही मॉडल तो के माध्यम से फिर से बनाया जा सकता है Sequential.from_config(config) (एक के लिए Sequential मॉडल) या Model.from_config(config) (एक कार्यात्मक एपीआई मॉडल के लिए)।

वही कार्यप्रवाह किसी भी क्रमागत परत के लिए भी कार्य करता है।

परत उदाहरण:

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

अनुक्रमिक मॉडल उदाहरण:

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

कार्यात्मक मॉडल उदाहरण:

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

इस के समान है get_config / from_config को छोड़कर यह JSON स्ट्रिंग है, जो तब मूल मॉडल वर्ग के बिना लोड किया जा सकता में मॉडल बदल जाता है,। यह मॉडल के लिए भी विशिष्ट है, यह परतों के लिए नहीं है।

उदाहरण:

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

कस्टम ऑब्जेक्ट

मॉडल और परतें

Subclassed मॉडल और परतों की वास्तुकला के तरीकों में परिभाषित कर रहे हैं __init__ और call । वे अजगर बाईटकोड है, जो एक JSON-संगत config में श्रृंखलाबद्ध नहीं किया जा सकता माना जाता है - आप बाईटकोड serializing की कोशिश कर सकते हैं (जैसे के माध्यम से pickle ), लेकिन यह पूरी तरह से असुरक्षित है और अपने मॉडल एक अलग सिस्टम पर लोड नहीं किया जा सकता है।

आदेश को बचाने / कस्टम-निर्धारित परतों के साथ एक मॉडल, या एक subclassed मॉडल लोड करने के लिए, आप के ऊपर लिख चाहिए get_config और वैकल्पिक रूप से from_config तरीकों। इसके अतिरिक्त, आपको कस्टम ऑब्जेक्ट रजिस्टर का उपयोग करना चाहिए ताकि केरस को इसके बारे में पता हो।

कस्टम कार्य

कस्टम-परिभाषित प्रकार्य (जैसे सक्रियण हानि या प्रारंभ) एक की जरूरत नहीं है get_config विधि। फ़ंक्शन नाम तब तक लोड करने के लिए पर्याप्त है जब तक यह एक कस्टम ऑब्जेक्ट के रूप में पंजीकृत है।

केवल TensorFlow ग्राफ़ लोड हो रहा है

केरस द्वारा उत्पन्न TensorFlow ग्राफ को लोड करना संभव है। यदि आप ऐसा करते हैं, तो आप किसी भी प्रदान करने के लिए की जरूरत नहीं होगी custom_objects । आप ऐसा इस तरह कर सकते हैं:

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

ध्यान दें कि इस पद्धति में कई कमियां हैं:

  • ट्रैसेबिलिटी कारणों से, आपके पास हमेशा उपयोग किए गए कस्टम ऑब्जेक्ट्स तक पहुंच होनी चाहिए। आप ऐसे मॉडल का उत्पादन नहीं करना चाहेंगे जिसे आप फिर से नहीं बना सकते।
  • वस्तु द्वारा दिया tf.saved_model.load एक Keras मॉडल नहीं है। तो इसका उपयोग करना उतना आसान नहीं है। उदाहरण के लिए, आप के लिए पहुँच नहीं होगा .predict() या .fit()

यहां तक कि अगर इसके उपयोग को हतोत्साहित किया जाता है, यह आप अगर आप उदाहरण के लिए एक तंग जगह में हैं, मदद कर सकते हैं, अगर आप अपने कस्टम वस्तुओं के कोड खो दिया है या के साथ मॉडल लोड हो रहा मुद्दे हैं tf.keras.models.load_model()

आप में और अधिक जानकारी प्राप्त कर सकते हैं के बारे में पेज tf.saved_model.load

कॉन्फ़िगरेशन विधियों को परिभाषित करना

विशेष विवरण:

  • get_config क्रम में एक JSON-serializable शब्दकोश लौट वास्तुकला और मॉडल की बचत एपीआई Keras के साथ संगत होना करने के लिए करना चाहिए।
  • from_config(config) ( classmethod ) कि config से बनाई गई है एक नई परत या मॉडल ऑब्जेक्ट प्रदान। डिफ़ॉल्ट कार्यान्वयन रिटर्न cls(**config)

उदाहरण:

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

कस्टम ऑब्जेक्ट का पंजीकरण

केरस इस बात का ध्यान रखता है कि किस वर्ग ने config. ऊपर के उदाहरण से, tf.keras.layers.serialize कस्टम परत के एक धारावाहिक रूप उत्पन्न करता है:

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

Keras की एक मास्टर सूची रखता है सब में निर्मित परत, मॉडल, अनुकूलक, और मीट्रिक कक्षाएं, जो कॉल करने के लिए सही वर्ग को खोजने के लिए प्रयोग किया जाता है from_config । वर्ग नहीं पाया जा सकता है, तो एक त्रुटि उठाया है ( Value Error: Unknown layer )। इस सूची में कस्टम कक्षाओं को पंजीकृत करने के कुछ तरीके हैं:

  1. स्थापना custom_objects लोड हो रहा है समारोह में तर्क। ("कॉन्फ़िगरेशन विधियों को परिभाषित करना" के ऊपर अनुभाग में उदाहरण देखें)
  2. tf.keras.utils.custom_object_scope या tf.keras.utils.CustomObjectScope
  3. tf.keras.utils.register_keras_serializable

कस्टम परत और फ़ंक्शन उदाहरण

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)

इन-मेमोरी मॉडल क्लोनिंग

तुम भी के माध्यम से एक मॉडल के नि: स्मृति क्लोनिंग कर सकते हैं tf.keras.models.clone_model() । यह कॉन्फिगरेशन प्राप्त करने के बाद मॉडल को इसके कॉन्फिगरेशन से फिर से बनाने के बराबर है (इसलिए यह संकलन जानकारी या लेयर वेट वैल्यू को संरक्षित नहीं करता है)।

उदाहरण:

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

केवल मॉडल के भार मानों को सहेजना और लोड करना

आप केवल मॉडल के वज़न को सहेजना और लोड करना चुन सकते हैं। यह उपयोगी हो सकता है यदि:

  • आपको केवल अनुमान के लिए मॉडल की आवश्यकता है: इस मामले में आपको प्रशिक्षण को पुनरारंभ करने की आवश्यकता नहीं होगी, इसलिए आपको संकलन जानकारी या अनुकूलक स्थिति की आवश्यकता नहीं है।
  • आप ट्रांसफर लर्निंग कर रहे हैं: इस मामले में आप एक नए मॉडल को पूर्व मॉडल की स्थिति का पुन: उपयोग करने का प्रशिक्षण देंगे, इसलिए आपको पूर्व मॉडल की संकलन जानकारी की आवश्यकता नहीं है।

इन-मेमोरी वेट ट्रांसफर के लिए एपीआई

बाट का उपयोग करके विभिन्न वस्तुओं के बीच कॉपी किया जा सकता get_weights और set_weights :

नीचे उदाहरण।

मेमोरी में वज़न को एक परत से दूसरी परत में स्थानांतरित करना

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

मेमोरी में संगत आर्किटेक्चर के साथ वजन को एक मॉडल से दूसरे मॉडल में स्थानांतरित करना

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

स्टेटलेस लेयर्स का मामला

चूंकि स्टेटलेस परतें क्रम या भार की संख्या को नहीं बदलती हैं, मॉडल में संगत आर्किटेक्चर हो सकते हैं, भले ही अतिरिक्त/लापता स्टेटलेस परतें हों।

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

डिस्क पर वजन बचाने और उन्हें वापस लोड करने के लिए एपीआई

बाट को फोन करके डिस्क को बचाया जा सकता model.save_weights निम्न स्वरूपों में:

  • टेंसरफ्लो चेकपॉइंट
  • एचडीएफ5

के लिए डिफ़ॉल्ट प्रारूप model.save_weights TensorFlow चौकी है। सहेजें प्रारूप को निर्दिष्ट करने के दो तरीके हैं:

  1. save_format तर्क: करने के लिए सेट मूल्य save_format="tf" या save_format="h5"
  2. path तर्क: अगर साथ पथ समाप्त होता है .h5 या .hdf5 , तो HDF5 प्रारूप प्रयोग किया जाता है। अन्य प्रत्यय एक TensorFlow चौकी में परिणाम होगा, जब तक कि save_format निर्धारित है।

इन-मेमोरी numpy arrays के रूप में वज़न पुनर्प्राप्त करने का एक विकल्प भी है। प्रत्येक एपीआई के अपने फायदे और नुकसान हैं जिनका विवरण नीचे दिया गया है।

टीएफ चेकपॉइंट प्रारूप

उदाहरण:

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

प्रारूप विवरण

TensorFlow चेकपॉइंट प्रारूप ऑब्जेक्ट विशेषता नामों का उपयोग करके वज़न को सहेजता है और पुनर्स्थापित करता है। उदाहरण के लिए, पर विचार tf.keras.layers.Dense परत। : परत दो भार होता है dense.kernel और dense.bias । परत में सहेजा जाता है जब tf प्रारूप, जिसके परिणामस्वरूप चौकी कुंजियां मौजूद "kernel" और "bias" और उनके इसी वजन मूल्यों। अधिक जानकारी के लिए देखते हैं "लोड यांत्रिकी" TF चेकप्वाइंट गाइड में

नोट के बाद नाम पैरेंट ऑब्जेक्ट, नहीं चर के नाम में प्रयुक्त उस गुण / ग्राफ बढ़त नाम पर है। पर विचार करें CustomLayer नीचे दिए गए उदाहरण में। चर CustomLayer.var साथ सहेजा गया है "var" कुंजी के भाग के रूप, नहीं "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}

स्थानांतरण सीखने का उदाहरण

अनिवार्य रूप से, जब तक दो मॉडलों में एक ही आर्किटेक्चर होता है, वे एक ही चेकपॉइंट साझा करने में सक्षम होते हैं।

उदाहरण:

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>

मॉडल बनाने के लिए आमतौर पर एक ही एपीआई से चिपके रहने की सिफारिश की जाती है। यदि आप अनुक्रमिक और कार्यात्मक, या कार्यात्मक और उपवर्ग, आदि के बीच स्विच करते हैं, तो हमेशा पूर्व-प्रशिक्षित मॉडल का पुनर्निर्माण करें और उस मॉडल में पूर्व-प्रशिक्षित भार लोड करें।

अगला सवाल यह है कि अगर मॉडल आर्किटेक्चर काफी अलग हैं तो वजन को कैसे बचाया जा सकता है और विभिन्न मॉडलों में लोड किया जा सकता है? समाधान का उपयोग करने के लिए है tf.train.Checkpoint बचाने के लिए और सटीक परतों / चर बहाल करने के लिए।

उदाहरण:

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

एचडीएफ5 प्रारूप

HDF5 प्रारूप में परत नामों द्वारा समूहीकृत भार होते हैं। वजन सूचियों गैर trainable वजन (के रूप में ही की सूची में trainable वजन की सूची श्रृंखलाबद्ध द्वारा आदेश दिया हैं layer.weights )। इस प्रकार, एक मॉडल एक hdf5 चेकपॉइंट का उपयोग कर सकता है यदि उसकी समान परतें और प्रशिक्षण योग्य स्थितियाँ हैं जो चेकपॉइंट में सहेजी गई हैं।

उदाहरण:

# 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 एक अलग में हो सकता है layer.weights आदेश जब मॉडल नेस्टेड परतें हैं।

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

स्थानांतरण सीखने का उदाहरण

HDF5 से पूर्व-प्रशिक्षित वज़न लोड करते समय, वज़न को मूल चेकपॉइंट मॉडल में लोड करने और फिर वांछित वज़न/परतों को एक नए मॉडल में निकालने की अनुशंसा की जाती है।

उदाहरण:

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
_________________________________________________________________