![]() | ![]() | ![]() | ![]() |
परिचय
एक केरस मॉडल में कई घटक होते हैं:
- आर्किटेक्चर, या कॉन्फ़िगरेशन, जो निर्दिष्ट करता है कि मॉडल में क्या परतें हैं और वे कैसे जुड़े हैं।
- वजन मूल्यों का एक सेट ("मॉडल की स्थिति")।
- एक अनुकूलक (मॉडल को संकलित करके परिभाषित)।
- घाटे और मैट्रिक्स का एक सेट (मॉडल को
add_loss()
याadd_loss()
याadd_metric()
) को कॉल करके परिभाषित किया गया है।
केरस एपीआई इन सभी टुकड़ों को एक ही बार में डिस्क पर सहेजना संभव बनाता है, या केवल उनमें से कुछ को बचाने के लिए संभव है:
- TensorFlow SavedModel प्रारूप में (या पुराने केरस 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()
थी) - आशावादी और उसकी स्थिति, यदि कोई हो (यह आपको प्रशिक्षण को फिर से शुरू करने में सक्षम बनाता है जहाँ आपने छोड़ा था)
शहद की मक्खी
-
model.save()
याtf.keras.models.save_model()
-
tf.keras.models.load_model()
ऐसे दो प्रारूप हैं जिनका उपयोग आप एक संपूर्ण मॉडल को डिस्क पर सहेजने के लिए कर सकते हैं: TensorFlow SavedModel प्रारूप और पुराने Keras H5 प्रारूप । अनुशंसित प्रारूप SavedModel है। जब आप model.save()
उपयोग करते हैं तो यह डिफ़ॉल्ट होता है।
आप H5 प्रारूप में स्विच कर सकते हैं:
-
save_format='h5'
पासsave_format='h5'
save()
लिएsave_format='h5'
save()
। - एक फ़ाइलनाम पास करना जो
.h5
या.keras
मेंsave()
लिए समाप्त होता हैsave()
।
SavedModel प्रारूप
SavedModel अधिक व्यापक रूप से सहेजने वाला प्रारूप है, जो मॉडल आर्किटेक्चर, वेट और कॉल कार्यों के टेंसरोफ़्लो सबग्राफ को बचाता है। यह केरस को अंतर्निहित परतों और साथ ही कस्टम ऑब्जेक्ट्स को पुनर्स्थापित करने में सक्षम बनाता है।
उदाहरण:
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 शामिल हैं
कॉलिंग model.save('my_model')
my_model
नामक फ़ोल्डर बनाता है, जिसमें निम्न शामिल हैं:
ls my_model
assets saved_model.pb variables
मॉडल आर्किटेक्चर, और प्रशिक्षण कॉन्फ़िगरेशन (ऑप्टिमाइज़र, नुकसान और मैट्रिक्स सहित) saved_model.pb
में संग्रहीत हैं। वजन variables/
निर्देशिका में सहेजे जाते हैं।
SavedModel प्रारूप पर विस्तृत जानकारी के लिए, SavedModel गाइड ( डिस्क पर SavedModel प्रारूप ) देखें ।
SavedModel कस्टम ऑब्जेक्ट्स को कैसे संभालता है
मॉडल और इसकी परतों को सहेजते समय, SavedModel प्रारूप वर्ग नाम, कॉल फ़ंक्शन , हानियों और भार (और यदि लागू हो, तो कॉन्फ़िगरेशन) को संग्रहीत करता है। कॉल फ़ंक्शन मॉडल / परत की गणना ग्राफ को परिभाषित करता है।
मॉडल / परत विन्यास की अनुपस्थिति में, कॉल फ़ंक्शन का उपयोग एक मॉडल बनाने के लिए किया जाता है जो मूल मॉडल की तरह मौजूद होता है जिसे प्रशिक्षण के लिए मूल्यांकन, मूल्यांकन और उपयोग किया जा सकता है।
फिर भी, कस्टम मॉडल या लेयर क्लास लिखते समय 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 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>
पहले लोड किए गए मॉडल को कॉन्फ़िगर और CustomModel
वर्ग का उपयोग करके लोड किया गया है। मूल मॉडल की तरह काम करने वाले मॉडल वर्ग को गतिशील रूप से बनाकर दूसरा मॉडल लोड किया जाता है।
सेव्डमॉडल को कॉन्फ़िगर करना
नई TensoFlow 2.4 में तर्क save_traces
में जोड़ा गया है model.save
, जो आप टॉगल SavedModel समारोह ट्रेसिंग करने के लिए अनुमति देता है। save_traces=False
को मूल वर्ग निश्चित के बिना कस्टम ऑब्जेक्ट्स को फिर से लोड करने की अनुमति देने के लिए सहेजा जाता है, इसलिए जब save_traces=False
, तो सभी कस्टम ऑब्जेक्ट्स ने get_config
/ from_config
विधियों को परिभाषित किया होगा। लोड करते समय, कस्टम ऑब्जेक्ट्स को custom_objects
तर्क में पास किया जाना चाहिए। save_traces=False
SavedModel और समय बचाने के लिए उपयोग किए जाने वाले डिस्क स्थान को कम करता है।
केरस H5 प्रारूप
केरस मॉडल की वास्तुकला, भार मान और compile()
जानकारी वाले एकल HDF5 फ़ाइल को बचाने का भी समर्थन करता है। यह 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.0153 4/4 [==============================] - 0s 1ms/step - loss: 0.9104 <tensorflow.python.keras.callbacks.History at 0x7fd1455c66a0>
सीमाओं
SavedModel प्रारूप की तुलना में, दो चीजें हैं जो H5 फाइल में शामिल नहीं होती हैं:
- बाहरी घाटे और मीट्रिक के माध्यम से शामिल की
model.add_loss()
औरmodel.add_metric()
(SavedModel के विपरीत) बचाया नहीं गया है। यदि आपके मॉडल पर इस तरह के नुकसान और मैट्रिक्स हैं और आप प्रशिक्षण फिर से शुरू करना चाहते हैं, तो आपको मॉडल को लोड करने के बाद इन नुकसानों को स्वयं वापस जोड़ना होगा। ध्यान दें कि यहself.add_loss()
औरself.add_metric()
माध्यम से परतों के अंदर बनाए गए नुकसान / मैट्रिक्स पर लागू नहीं होता है। जब तक परत भरी जाती है, ये नुकसान और मैट्रिक्स रखे जाते हैं, क्योंकि वे परत कीcall
विधि का हिस्सा हैं। - सहेजे गए फ़ाइल में कस्टम ऑब्जेक्ट्स जैसे कस्टम ऑब्जेक्ट्स की गणना ग्राफ़ शामिल नहीं है। लोडिंग के समय, केर को मॉडल को फिर से संगठित करने के लिए इन वस्तुओं के पायथन वर्गों / कार्यों तक पहुंच की आवश्यकता होगी। कस्टम ऑब्जेक्ट देखें।
वास्तुकला को बचाते हुए
मॉडल का कॉन्फ़िगरेशन (या आर्किटेक्चर) निर्दिष्ट करता है कि मॉडल में कौन सी परतें हैं और ये परतें कैसे जुड़ी हुई हैं *। यदि आपके पास एक मॉडल का कॉन्फ़िगरेशन है, तो मॉडल को वजन और कोई संकलन जानकारी के लिए एक ताज़ा प्रारंभिक स्थिति के साथ बनाया जा सकता है।
* ध्यान दें कि यह केवल कार्यात्मक या अनुक्रमिक एप का उपयोग करके परिभाषित मॉडल पर लागू होता है जो उपवर्गित मॉडल नहीं हैं।
एक अनुक्रमिक मॉडल या कार्यात्मक एपीआई मॉडल का विन्यास
इस प्रकार के मॉडल परतों के स्पष्ट ग्राफ़ हैं: उनका कॉन्फ़िगरेशन हमेशा संरचित रूप में उपलब्ध होता है।
शहद की मक्खी
-
get_config()
औरfrom_config()
-
tf.keras.models.model_to_json()
औरtf.keras.models.model_from_json()
get_config()
और from_config()
कॉलिंग config = model.get_config()
मॉडल के कॉन्फ़िगरेशन वाले पायथन को वापस लौटा देगा। फिर उसी मॉडल को 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)
कस्टम ऑब्जेक्ट्स
मॉडल और परतें
उप-वर्गित मॉडल और परतों की वास्तुकला को __init__
और call
के तरीकों में परिभाषित किया गया है। उन्हें पायथन बाइटकोड माना जाता है, जिसे JSON- संगत कॉन्फ़िगरेशन में अनुक्रमित नहीं किया जा सकता है - आप बायटेकोड (जैसे pickle
माध्यम से) को क्रमबद्ध करने की कोशिश कर सकते हैं, लेकिन यह पूरी तरह से असुरक्षित है और इसका मतलब है कि आपका मॉडल एक अलग सिस्टम पर लोड नहीं किया जा सकता है।
कस्टम-परिभाषित परतों, या एक get_config
मॉडल के साथ एक मॉडल को बचाने / लोड करने के लिए, आपको 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()
INFO:tensorflow:Assets written to: my_model/assets
ध्यान दें कि इस विधि में कई कमियां हैं:
- ट्रैसेबिलिटी कारणों से, आपको हमेशा उन कस्टम ऑब्जेक्ट्स तक पहुंच होनी चाहिए जो उपयोग किए गए थे। आप एक ऐसे मॉडल का निर्माण नहीं करना चाहेंगे जिसे आप फिर से नहीं बना सकते।
- ऑब्जेक्ट
tf.saved_model.load
द्वारा लौटाया गया कोईtf.saved_model.load
मॉडल नहीं है। इसलिए इसका इस्तेमाल करना उतना आसान नहीं है। उदाहरण के लिए, आप के लिए पहुँच नहीं होगा.predict()
या.fit()
यहां तक कि अगर इसका उपयोग हतोत्साहित किया जाता है, तो यह आपकी मदद कर सकता है यदि आप एक तंग जगह पर हैं, उदाहरण के लिए, यदि आपने अपनी कस्टम ऑब्जेक्ट का कोड खो दिया है या मॉडल को tf.keras.models.load_model()
साथ लोड करने में समस्या है।
आप पृष्ठ में tf.saved_model.load
बारे में अधिक जानकारी प्राप्त कर सकते हैं
विन्यास विधियों को परिभाषित करना
विशेष विवरण:
-
get_config
आर्किटेक्चर और मॉडल-सेविंग APIs के साथ संगत होने के लिएget_config
को JSON-serializable शब्दकोश वापस करना चाहिए। -
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}
)
कस्टम ऑब्जेक्ट को पंजीकृत करना
केरस ने इस बात पर ध्यान दिया कि किस वर्ग ने विन्यास उत्पन्न किया। उपरोक्त उदाहरण से, tf.keras.layers.serialize
कस्टम लेयर का क्रमबद्ध रूप उत्पन्न करता है:
{'class_name': 'CustomLayer', 'config': {'a': 2} }
केरस सभी अंतर्निहित परत, मॉडल, अनुकूलक, और मीट्रिक कक्षाओं की एक मास्टर सूची रखता है, जिसका उपयोग from_config
पर कॉल करने के लिए सही वर्ग खोजने के लिए किया जाता है। यदि वर्ग नहीं मिल सकता है, तो एक त्रुटि उठाई जाती है ( Value Error: Unknown layer
)। इस सूची में कस्टम कक्षाओं को पंजीकृत करने के कुछ तरीके हैं:
- लोडिंग फ़ंक्शन में
custom_objects
तर्क सेट करना। ("विन्यास विधियों को परिभाषित करना" से ऊपर के अनुभाग में उदाहरण देखें) -
tf.keras.utils.custom_object_scope
याtf.keras.utils.CustomObjectScope
-
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
का उपयोग करके वजन को विभिन्न वस्तुओं के बीच कॉपी किया जा सकता है:
-
tf.keras.layers.Layer.get_weights()
: संख्यात्मक सरणियों की सूची लौटाता है। -
tf.keras.layers.Layer.set_weights()
: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
को कॉल करके डिस्क को बचाया जा सकता है:
- TensorFlow चेकपॉइंट
- HDF5
के लिए डिफ़ॉल्ट प्रारूप model.save_weights
TensorFlow चौकी है। सहेजें प्रारूप को निर्दिष्ट करने के दो तरीके हैं:
-
save_format
तर्क:save_format="tf"
याsave_format="h5"
का मान सेट करें। -
path
तर्क: यदि पथ.h5
या.hdf5
साथ समाप्त होता है, तो.hdf5
प्रारूप का उपयोग किया जाता है। जब तकsave_format
सेट नहींsave_format
है, अन्य प्रत्यय TensorFlow चेकपॉइंट में परिणाम करेंगे।
इन-मेमोरी सुपीरियर एरेज़ के रूप में वज़न पुनः प्राप्त करने का एक विकल्प भी है। प्रत्येक एपीआई के पास अपने पेशेवरों और विपक्ष हैं जो नीचे विस्तृत हैं।
TF चेकपॉइंट प्रारूप
उदाहरण:
# 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>
प्रारूप विवरण
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 0x7fd144b20b38>
यह आमतौर पर मॉडल बनाने के लिए उसी एपीआई से चिपके रहने की सिफारिश की जाती है। यदि आप अनुक्रमिक और कार्यात्मक, या कार्यात्मक और उपवर्ग इत्यादि के बीच स्विच करते हैं, तो हमेशा पूर्व प्रशिक्षित मॉडल का पुनर्निर्माण करें और उस मॉडल के लिए पूर्व-प्रशिक्षित भार को लोड करें।
अगला सवाल यह है कि यदि मॉडल आर्किटेक्चर काफी अलग हैं तो वज़न को अलग-अलग मॉडल में कैसे बचाया और लोड किया जा सकता है? इसका समाधान सटीक परतों / चर को बचाने और पुनर्स्थापित करने के लिए tf.train.Checkpoint
का उपयोग 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.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 प्रारूप
HDF5 प्रारूप में परत नामों के आधार पर भार होता है। भार-सूची वे सूची हैं जिन्हें ट्रेन किए गए भार की सूची को गैर-ट्रेन योग्य भार ( layer.weights
रूप में layer.weights
) की सूची के अनुसार 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 _________________________________________________________________