मॉड्यूल, परतों और मॉडलों का परिचय

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

TensorFlow में मशीन लर्निंग करने के लिए, आपको एक मॉडल को परिभाषित करने, सहेजने और पुनर्स्थापित करने की आवश्यकता हो सकती है।

एक मॉडल, संक्षेप में है:

  • एक फ़ंक्शन जो टेंसर पर कुछ गणना करता है (एक फॉरवर्ड पास )
  • कुछ चर जिन्हें प्रशिक्षण के जवाब में अद्यतन किया जा सकता है

इस गाइड में, आप केरस की सतह के नीचे जाकर देखेंगे कि कैसे TensorFlow मॉडल को परिभाषित किया जाता है। यह देखता है कि कैसे TensorFlow चर और मॉडल एकत्र करता है, साथ ही साथ उन्हें कैसे सहेजा और पुनर्स्थापित किया जाता है।

सेट अप

import tensorflow as tf
from datetime import datetime

%load_ext tensorboard

TensorFlow में मॉडल और परतों को परिभाषित करना

अधिकांश मॉडल परतों से बने होते हैं। परतें एक ज्ञात गणितीय संरचना वाले कार्य हैं जिनका पुन: उपयोग किया जा सकता है और इसमें प्रशिक्षित चर हो सकते हैं। TensorFlow में, परतों और मॉडलों के अधिकांश उच्च-स्तरीय कार्यान्वयन, जैसे कि केरस या सॉनेट , एक ही मूलभूत वर्ग पर बनाए जाते हैं: tf.Module

यहाँ एक बहुत ही सरल tf.Module का एक उदाहरण दिया गया है जो एक अदिश टेंसर पर कार्य करता है:

class SimpleModule(tf.Module):
  def __init__(self, name=None):
    super().__init__(name=name)
    self.a_variable = tf.Variable(5.0, name="train_me")
    self.non_trainable_variable = tf.Variable(5.0, trainable=False, name="do_not_train_me")
  def __call__(self, x):
    return self.a_variable * x + self.non_trainable_variable

simple_module = SimpleModule(name="simple")

simple_module(tf.constant(5.0))
<tf.Tensor: shape=(), dtype=float32, numpy=30.0>

मॉड्यूल और, विस्तार से, परतें "ऑब्जेक्ट्स" के लिए गहरी-सीखने वाली शब्दावली हैं: उनके पास आंतरिक स्थिति है, और उस स्थिति का उपयोग करने वाली विधियां हैं।

पाइथन कॉल करने योग्य की तरह कार्य करने के अलावा __call__ के बारे में कुछ खास नहीं है; आप अपने मॉडलों को अपनी इच्छानुसार किसी भी कार्य के साथ आमंत्रित कर सकते हैं।

आप किसी भी कारण से चरों की प्रशिक्षण योग्यता को चालू और बंद कर सकते हैं, जिसमें फ़ाइन-ट्यूनिंग के दौरान फ़्रीज़िंग परतें और चर शामिल हैं।

tf.Module को tf.Module करके, इस ऑब्जेक्ट के गुणों को निर्दिष्ट कोई भी tf.Variable या tf.Module उदाहरण स्वचालित रूप से एकत्र किए जाते हैं। यह आपको चर को सहेजने और लोड करने की अनुमति देता है, और tf.Module s का संग्रह भी बनाता है।

# All trainable variables
print("trainable variables:", simple_module.trainable_variables)
# Every variable
print("all variables:", simple_module.variables)
trainable variables: (<tf.Variable 'train_me:0' shape=() dtype=float32, numpy=5.0>,)
all variables: (<tf.Variable 'train_me:0' shape=() dtype=float32, numpy=5.0>, <tf.Variable 'do_not_train_me:0' shape=() dtype=float32, numpy=5.0>)
2021-10-26 01:29:45.284549: 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.

यह मॉड्यूल से बने दो-परत रैखिक परत मॉडल का एक उदाहरण है।

पहले एक घनी (रैखिक) परत:

class Dense(tf.Module):
  def __init__(self, in_features, out_features, name=None):
    super().__init__(name=name)
    self.w = tf.Variable(
      tf.random.normal([in_features, out_features]), name='w')
    self.b = tf.Variable(tf.zeros([out_features]), name='b')
  def __call__(self, x):
    y = tf.matmul(x, self.w) + self.b
    return tf.nn.relu(y)

और फिर पूरा मॉडल, जो दो परत उदाहरण बनाता है और उन्हें लागू करता है:

class SequentialModule(tf.Module):
  def __init__(self, name=None):
    super().__init__(name=name)

    self.dense_1 = Dense(in_features=3, out_features=3)
    self.dense_2 = Dense(in_features=3, out_features=2)

  def __call__(self, x):
    x = self.dense_1(x)
    return self.dense_2(x)

# You have made a model!
my_model = SequentialModule(name="the_model")

# Call it, with random results
print("Model results:", my_model(tf.constant([[2.0, 2.0, 2.0]])))
Model results: tf.Tensor([[7.706234  3.0919805]], shape=(1, 2), dtype=float32)

tf.Module इंस्टेंस स्वचालित रूप से, पुनरावर्ती रूप से, किसी भी tf.Variable या tf.Module इंस्टेंस को असाइन किया जाएगा। यह आपको एकल मॉडल उदाहरण के साथ tf.Module s के संग्रह को प्रबंधित करने और पूरे मॉडल को सहेजने और लोड करने की अनुमति देता है।

print("Submodules:", my_model.submodules)
Submodules: (<__main__.Dense object at 0x7f7ab2391290>, <__main__.Dense object at 0x7f7b6869ea10>)
for var in my_model.variables:
  print(var, "\n")
<tf.Variable 'b:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)> 

<tf.Variable 'w:0' shape=(3, 3) dtype=float32, numpy=
array([[ 0.05711935,  0.22440144,  0.6370985 ],
       [ 0.3136791 , -1.7006774 ,  0.7256515 ],
       [ 0.16120772, -0.8412193 ,  0.5250952 ]], dtype=float32)> 

<tf.Variable 'b:0' shape=(2,) dtype=float32, numpy=array([0., 0.], dtype=float32)> 

<tf.Variable 'w:0' shape=(3, 2) dtype=float32, numpy=
array([[-0.5353216 ,  1.2815404 ],
       [ 0.62764466,  0.47087234],
       [ 2.19187   ,  0.45777202]], dtype=float32)>

चर बनाने की प्रतीक्षा कर रहा है

आपने यहां देखा होगा कि आपको परत के लिए इनपुट और आउटपुट आकार दोनों को परिभाषित करना होगा। ऐसा इसलिए है कि w चर का एक ज्ञात आकार है और इसे आवंटित किया जा सकता है।

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

class FlexibleDenseModule(tf.Module):
  # Note: No need for `in_features`
  def __init__(self, out_features, name=None):
    super().__init__(name=name)
    self.is_built = False
    self.out_features = out_features

  def __call__(self, x):
    # Create variables on first call.
    if not self.is_built:
      self.w = tf.Variable(
        tf.random.normal([x.shape[-1], self.out_features]), name='w')
      self.b = tf.Variable(tf.zeros([self.out_features]), name='b')
      self.is_built = True

    y = tf.matmul(x, self.w) + self.b
    return tf.nn.relu(y)
# Used in a module
class MySequentialModule(tf.Module):
  def __init__(self, name=None):
    super().__init__(name=name)

    self.dense_1 = FlexibleDenseModule(out_features=3)
    self.dense_2 = FlexibleDenseModule(out_features=2)

  def __call__(self, x):
    x = self.dense_1(x)
    return self.dense_2(x)

my_model = MySequentialModule(name="the_model")
print("Model results:", my_model(tf.constant([[2.0, 2.0, 2.0]])))
Model results: tf.Tensor([[4.0598335 0.       ]], shape=(1, 2), dtype=float32)

यही कारण है कि TensorFlow परतों को अक्सर केवल अपने आउटपुट के आकार को निर्दिष्ट करने की आवश्यकता होती है, जैसे कि tf.keras.layers.Dense में, न कि इनपुट और आउटपुट आकार दोनों में।

वजन बचाना

आप tf.Module को चेकपॉइंट और tf.Module दोनों के रूप में सहेज सकते हैं।

चेकपॉइंट केवल वज़न हैं (अर्थात, मॉड्यूल और उसके सबमॉड्यूल के अंदर चर के सेट के मान):

chkp_path = "my_checkpoint"
checkpoint = tf.train.Checkpoint(model=my_model)
checkpoint.write(chkp_path)
'my_checkpoint'
प्लेसहोल्डर17

चेकपॉइंट में दो तरह की फाइलें होती हैं: डेटा ही और मेटाडेटा के लिए एक इंडेक्स फाइल। इंडेक्स फ़ाइल वास्तव में सहेजी गई चीज़ों और चौकियों की संख्या का ट्रैक रखती है, जबकि चेकपॉइंट डेटा में चर मान और उनके विशेषता लुकअप पथ होते हैं।

ls my_checkpoint*
my_checkpoint.data-00000-of-00001  my_checkpoint.index

आप यह सुनिश्चित करने के लिए एक चेकपॉइंट के अंदर देख सकते हैं कि चर का पूरा संग्रह सहेजा गया है, जो उन्हें शामिल पायथन ऑब्जेक्ट द्वारा क्रमबद्ध किया गया है।

tf.train.list_variables(chkp_path)
[('_CHECKPOINTABLE_OBJECT_GRAPH', []),
 ('model/dense_1/b/.ATTRIBUTES/VARIABLE_VALUE', [3]),
 ('model/dense_1/w/.ATTRIBUTES/VARIABLE_VALUE', [3, 3]),
 ('model/dense_2/b/.ATTRIBUTES/VARIABLE_VALUE', [2]),
 ('model/dense_2/w/.ATTRIBUTES/VARIABLE_VALUE', [3, 2])]

वितरित (मल्टी-मशीन) प्रशिक्षण के दौरान उन्हें शार्प किया जा सकता है, यही वजह है कि उन्हें क्रमांकित किया जाता है (जैसे, '00000-ऑफ़-00001')। इस मामले में, हालांकि, केवल एक ही शार्क है।

जब आप मॉडल को वापस लोड करते हैं, तो आप अपने पायथन ऑब्जेक्ट में मानों को अधिलेखित कर देते हैं।

new_model = MySequentialModule()
new_checkpoint = tf.train.Checkpoint(model=new_model)
new_checkpoint.restore("my_checkpoint")

# Should be the same result as above
new_model(tf.constant([[2.0, 2.0, 2.0]]))
<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[4.0598335, 0.       ]], dtype=float32)>

बचत कार्य

TensorFlow मूल पायथन ऑब्जेक्ट्स के बिना मॉडल चला सकता है, जैसा कि TensorFlow Serving और TensorFlow Lite द्वारा प्रदर्शित किया गया है, तब भी जब आप TensorFlow हब से एक प्रशिक्षित मॉडल डाउनलोड करते हैं।

TensorFlow को यह जानने की जरूरत है कि पायथन में वर्णित गणना कैसे करें, लेकिन मूल कोड के बिना । ऐसा करने के लिए, आप एक ग्राफ़ बना सकते हैं, जिसका वर्णन ग्राफ़ और फ़ंक्शन गाइड के परिचय में किया गया है।

इस ग्राफ़ में संचालन, या ops शामिल हैं, जो फ़ंक्शन को कार्यान्वित करते हैं।

आप उपरोक्त मॉडल में @tf.function डेकोरेटर जोड़कर एक ग्राफ परिभाषित कर सकते हैं यह इंगित करने के लिए कि यह कोड एक ग्राफ के रूप में चलना चाहिए।

class MySequentialModule(tf.Module):
  def __init__(self, name=None):
    super().__init__(name=name)

    self.dense_1 = Dense(in_features=3, out_features=3)
    self.dense_2 = Dense(in_features=3, out_features=2)

  @tf.function
  def __call__(self, x):
    x = self.dense_1(x)
    return self.dense_2(x)

# You have made a model with a graph!
my_model = MySequentialModule(name="the_model")

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

print(my_model([[2.0, 2.0, 2.0]]))
print(my_model([[[2.0, 2.0, 2.0], [2.0, 2.0, 2.0]]]))
tf.Tensor([[0.62891716 0.        ]], shape=(1, 2), dtype=float32)
tf.Tensor(
[[[0.62891716 0.        ]
  [0.62891716 0.        ]]], shape=(1, 2, 2), dtype=float32)
प्लेसहोल्डर26

आप ग्राफ़ को TensorBoard सारांश के भीतर ट्रेस करके कल्पना कर सकते हैं।

# Set up logging.
stamp = datetime.now().strftime("%Y%m%d-%H%M%S")
logdir = "logs/func/%s" % stamp
writer = tf.summary.create_file_writer(logdir)

# Create a new model to get a fresh trace
# Otherwise the summary will not see the graph.
new_model = MySequentialModule()

# Bracket the function call with
# tf.summary.trace_on() and tf.summary.trace_export().
tf.summary.trace_on(graph=True)
tf.profiler.experimental.start(logdir)
# Call only one tf.function when tracing.
z = print(new_model(tf.constant([[2.0, 2.0, 2.0]])))
with writer.as_default():
  tf.summary.trace_export(
      name="my_func_trace",
      step=0,
      profiler_outdir=logdir)
tf.Tensor([[0.         0.01750386]], shape=(1, 2), dtype=float32)

परिणामी ट्रेस देखने के लिए TensorBoard लॉन्च करें:

#docs_infra: no_execute
%tensorboard --logdir logs/func

TensorBoard में ग्राफ़ का स्क्रीनशॉट

एक SavedModel गया मॉडल बनाना

पूरी तरह से प्रशिक्षित मॉडल को साझा करने का अनुशंसित तरीका SavedModel का उपयोग करना है। SavedModel में फ़ंक्शंस का संग्रह और वज़न का संग्रह दोनों शामिल हैं।

आप जिस मॉडल को अभी-अभी प्रशिक्षित किया है, उसे आप इस प्रकार सहेज सकते हैं:

tf.saved_model.save(my_model, "the_saved_model")
INFO:tensorflow:Assets written to: the_saved_model/assets
# Inspect the SavedModel in the directory
ls -l the_saved_model
प्लेसहोल्डर32 l10n-प्लेसहोल्डर
total 24
drwxr-sr-x 2 kbuilder kokoro  4096 Oct 26 01:29 assets
-rw-rw-r-- 1 kbuilder kokoro 14702 Oct 26 01:29 saved_model.pb
drwxr-sr-x 2 kbuilder kokoro  4096 Oct 26 01:29 variables
# The variables/ directory contains a checkpoint of the variables
ls -l the_saved_model/variables
total 8
-rw-rw-r-- 1 kbuilder kokoro 408 Oct 26 01:29 variables.data-00000-of-00001
-rw-rw-r-- 1 kbuilder kokoro 356 Oct 26 01:29 variables.index

saved_model.pb फ़ाइल एक प्रोटोकॉल बफर है जो कार्यात्मक tf.Graph का वर्णन करता है।

मॉडल और परतों को इस प्रतिनिधित्व से वास्तव में उस वर्ग का उदाहरण बनाए बिना लोड किया जा सकता है जिसने इसे बनाया है। यह उन स्थितियों में वांछित है जहां आपके पास पाइथन दुभाषिया नहीं है (या चाहते हैं), जैसे स्केल पर या किनारे डिवाइस पर सेवा करना, या ऐसी परिस्थितियों में जहां मूल पायथन कोड उपलब्ध नहीं है या उपयोग करने के लिए व्यावहारिक नहीं है।

आप मॉडल को नई वस्तु के रूप में लोड कर सकते हैं:

new_model = tf.saved_model.load("the_saved_model")

new_model , एक सहेजे गए मॉडल को लोड करने से बनाया गया है, जो किसी भी वर्ग ज्ञान के बिना एक आंतरिक TensorFlow उपयोगकर्ता ऑब्जेक्ट है। यह SequentialModule प्रकार का नहीं है।

isinstance(new_model, SequentialModule)
False

यह नया मॉडल पहले से परिभाषित इनपुट सिग्नेचर पर काम करता है। आप इस तरह पुनर्स्थापित किए गए मॉडल में अधिक हस्ताक्षर नहीं जोड़ सकते।

print(my_model([[2.0, 2.0, 2.0]]))
print(my_model([[[2.0, 2.0, 2.0], [2.0, 2.0, 2.0]]]))
tf.Tensor([[0.62891716 0.        ]], shape=(1, 2), dtype=float32)
tf.Tensor(
[[[0.62891716 0.        ]
  [0.62891716 0.        ]]], shape=(1, 2, 2), dtype=float32)

इस प्रकार, SavedModel का उपयोग करके tf.Module वज़न और ग्राफ़ को सहेजने में सक्षम हैं, और फिर उन्हें फिर से लोड कर सकते हैं।

केरस मॉडल और परतें

ध्यान दें कि इस बिंदु तक, केरस का कोई उल्लेख नहीं है। आप tf.Module के शीर्ष पर अपना स्वयं का उच्च-स्तरीय API बना सकते हैं, और लोगों के पास है।

इस खंड में, आप जांच करेंगे कि tf.Module का उपयोग कैसे करता है। Keras मॉडल के लिए एक संपूर्ण उपयोगकर्ता मार्गदर्शिका Keras मार्गदर्शिका में पाई जा सकती है।

केरस परतें

tf.keras.layers.Layer सभी Keras परतों का आधार वर्ग है, और यह tf.Module से इनहेरिट करता है।

आप माता-पिता को स्वैप करके और फिर __call__ को call में बदलकर मॉड्यूल को केरस परत में परिवर्तित कर सकते हैं:

class MyDense(tf.keras.layers.Layer):
  # Adding **kwargs to support base Keras layer arguments
  def __init__(self, in_features, out_features, **kwargs):
    super().__init__(**kwargs)

    # This will soon move to the build step; see below
    self.w = tf.Variable(
      tf.random.normal([in_features, out_features]), name='w')
    self.b = tf.Variable(tf.zeros([out_features]), name='b')
  def call(self, x):
    y = tf.matmul(x, self.w) + self.b
    return tf.nn.relu(y)

simple_layer = MyDense(name="simple", in_features=3, out_features=3)

केरस परतों का अपना __call__ होता है जो अगले भाग में वर्णित कुछ बहीखाता पद्धति करता है और फिर कॉल call() को कॉल करता है। आपको कार्यक्षमता में कोई बदलाव नहीं दिखना चाहिए।

simple_layer([[2.0, 2.0, 2.0]])
<tf.Tensor: shape=(1, 3), dtype=float32, numpy=array([[0.      , 0.179402, 0.      ]], dtype=float32)>

build कदम

जैसा कि कहा गया है, जब तक आप इनपुट आकार के बारे में सुनिश्चित नहीं हो जाते, तब तक चर बनाने के लिए प्रतीक्षा करना कई मामलों में सुविधाजनक होता है।

केरस परतें एक अतिरिक्त जीवनचक्र चरण के साथ आती हैं जो आपको अपनी परतों को परिभाषित करने के तरीके में अधिक लचीलेपन की अनुमति देती है। इसे build फंक्शन में परिभाषित किया गया है।

build को ठीक एक बार कहा जाता है, और इसे इनपुट के आकार के साथ कहा जाता है। यह आमतौर पर चर (वजन) बनाने के लिए उपयोग किया जाता है।

आप ऊपर MyDense परत को फिर से लिख सकते हैं ताकि इसके इनपुट के आकार के लिए लचीला हो:

class FlexibleDense(tf.keras.layers.Layer):
  # Note the added `**kwargs`, as Keras supports many arguments
  def __init__(self, out_features, **kwargs):
    super().__init__(**kwargs)
    self.out_features = out_features

  def build(self, input_shape):  # Create the state of the layer (weights)
    self.w = tf.Variable(
      tf.random.normal([input_shape[-1], self.out_features]), name='w')
    self.b = tf.Variable(tf.zeros([self.out_features]), name='b')

  def call(self, inputs):  # Defines the computation from inputs to outputs
    return tf.matmul(inputs, self.w) + self.b

# Create the instance of the layer
flexible_dense = FlexibleDense(out_features=3)

इस बिंदु पर, मॉडल नहीं बनाया गया है, इसलिए कोई चर नहीं हैं:

flexible_dense.variables
[]

फ़ंक्शन को कॉल करना उचित आकार के चर आवंटित करता है:

# Call it, with predictably random results
print("Model results:", flexible_dense(tf.constant([[2.0, 2.0, 2.0], [3.0, 3.0, 3.0]])))
Model results: tf.Tensor(
[[-1.6998017  1.6444504 -1.3103955]
 [-2.5497022  2.4666753 -1.9655929]], shape=(2, 3), dtype=float32)
flexible_dense.variables
[<tf.Variable 'flexible_dense/w:0' shape=(3, 3) dtype=float32, numpy=
 array([[ 1.277462  ,  0.5399406 , -0.301957  ],
        [-1.6277349 ,  0.7374014 , -1.7651852 ],
        [-0.49962795, -0.45511687,  1.4119445 ]], dtype=float32)>,
 <tf.Variable 'flexible_dense/b:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>]

चूंकि build को केवल एक बार कहा जाता है, इनपुट को अस्वीकार कर दिया जाएगा यदि इनपुट आकार परत के चर के साथ संगत नहीं है:

try:
  print("Model results:", flexible_dense(tf.constant([[2.0, 2.0, 2.0, 2.0]])))
except tf.errors.InvalidArgumentError as e:
  print("Failed:", e)
Failed: In[0] mismatch In[1] shape: 4 vs. 3: [1,4] [3,3] 0 0 [Op:MatMul]

केरस परतों में बहुत अधिक अतिरिक्त विशेषताएं शामिल हैं:

  • वैकल्पिक नुकसान
  • मेट्रिक्स के लिए समर्थन
  • प्रशिक्षण और अनुमान के उपयोग के बीच अंतर करने के लिए वैकल्पिक training तर्क के लिए अंतर्निहित समर्थन
  • get_config और from_config विधियाँ जो आपको पायथन में मॉडल क्लोनिंग की अनुमति देने के लिए कॉन्फ़िगरेशन को सटीक रूप से संग्रहीत करने की अनुमति देती हैं

उनके बारे में कस्टम परतों और मॉडलों की पूरी मार्गदर्शिका में पढ़ें।

केरस मॉडल

आप अपने मॉडल को नेस्टेड केरस परतों के रूप में परिभाषित कर सकते हैं।

हालांकि, tf.keras.Model नामक एक पूर्ण विशेषताओं वाला मॉडल वर्ग भी प्रदान करता है। यह tf.keras.layers.Layer से विरासत में मिला है, इसलिए एक केरस मॉडल का उपयोग, नेस्टेड और केरस परतों की तरह ही सहेजा जा सकता है। केरस मॉडल अतिरिक्त कार्यक्षमता के साथ आते हैं जो उन्हें कई मशीनों पर प्रशिक्षित करना, मूल्यांकन करना, लोड करना, सहेजना और यहां तक ​​कि ट्रेन करना आसान बनाता है।

आप ऊपर से SequentialModule मॉड्यूल को लगभग समान कोड के साथ परिभाषित कर सकते हैं, फिर से __call__ को call() में परिवर्तित कर सकते हैं और माता-पिता को बदल सकते हैं:

class MySequentialModel(tf.keras.Model):
  def __init__(self, name=None, **kwargs):
    super().__init__(**kwargs)

    self.dense_1 = FlexibleDense(out_features=3)
    self.dense_2 = FlexibleDense(out_features=2)
  def call(self, x):
    x = self.dense_1(x)
    return self.dense_2(x)

# You have made a Keras model!
my_sequential_model = MySequentialModel(name="the_model")

# Call it on a tensor, with random results
print("Model results:", my_sequential_model(tf.constant([[2.0, 2.0, 2.0]])))
Model results: tf.Tensor([[5.5604653 3.3511646]], shape=(1, 2), dtype=float32)

ट्रैकिंग चर और सबमॉड्यूल सहित सभी समान सुविधाएं उपलब्ध हैं।

my_sequential_model.variables
[<tf.Variable 'my_sequential_model/flexible_dense_1/w:0' shape=(3, 3) dtype=float32, numpy=
 array([[ 0.05627853, -0.9386015 , -0.77410126],
        [ 0.63149   ,  1.0802224 , -0.37785745],
        [-0.24788402, -1.1076807 , -0.5956209 ]], dtype=float32)>,
 <tf.Variable 'my_sequential_model/flexible_dense_1/b:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>,
 <tf.Variable 'my_sequential_model/flexible_dense_2/w:0' shape=(3, 2) dtype=float32, numpy=
 array([[-0.93912166,  0.77979285],
        [ 1.4049559 , -1.9380962 ],
        [-2.6039495 ,  0.30885765]], dtype=float32)>,
 <tf.Variable 'my_sequential_model/flexible_dense_2/b:0' shape=(2,) dtype=float32, numpy=array([0., 0.], dtype=float32)>]
my_sequential_model.submodules
(<__main__.FlexibleDense at 0x7f7b48525550>,
 <__main__.FlexibleDense at 0x7f7b48508d10>)

TensorFlow मॉडल बनाने के लिए tf.keras.Model को ओवरराइड करना एक बहुत ही पाइथोनिक तरीका है। यदि आप अन्य ढांचे से मॉडल माइग्रेट कर रहे हैं, तो यह बहुत सीधा हो सकता है।

यदि आप ऐसे मॉडल का निर्माण कर रहे हैं जो मौजूदा परतों और इनपुट के सरल संयोजन हैं, तो आप कार्यात्मक एपीआई का उपयोग करके समय और स्थान बचा सकते हैं, जो मॉडल पुनर्निर्माण और वास्तुकला के आसपास अतिरिक्त सुविधाओं के साथ आता है।

यहाँ कार्यात्मक एपीआई के साथ एक ही मॉडल है:

inputs = tf.keras.Input(shape=[3,])

x = FlexibleDense(3)(inputs)
x = FlexibleDense(2)(x)

my_functional_model = tf.keras.Model(inputs=inputs, outputs=x)

my_functional_model.summary()
Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 3)]               0         
_________________________________________________________________
flexible_dense_3 (FlexibleDe (None, 3)                 12        
_________________________________________________________________
flexible_dense_4 (FlexibleDe (None, 2)                 8         
=================================================================
Total params: 20
Trainable params: 20
Non-trainable params: 0
_________________________________________________________________
my_functional_model(tf.constant([[2.0, 2.0, 2.0]]))
<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[8.219393, 4.511119]], dtype=float32)>

यहां मुख्य अंतर यह है कि कार्यात्मक निर्माण प्रक्रिया के हिस्से के रूप में इनपुट आकार को सामने निर्दिष्ट किया जाता है। इस मामले में input_shape तर्क को पूरी तरह से निर्दिष्ट करने की आवश्यकता नहीं है; आप कुछ आयामों को None के रूप में छोड़ सकते हैं।

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

केरस मॉडल को चेकपॉइंट किया जा सकता है, और यह tf.Module जैसा ही दिखेगा।

केरस मॉडल को tf.saved_model.save() के साथ भी सहेजा जा सकता है, क्योंकि वे मॉड्यूल हैं। हालांकि, केरस मॉडल में सुविधा के तरीके और अन्य कार्यक्षमताएं हैं:

my_sequential_model.save("exname_of_file")
INFO:tensorflow:Assets written to: exname_of_file/assets

जितनी आसानी से, उन्हें वापस इसमें लोड किया जा सकता है:

reconstructed_model = tf.keras.models.load_model("exname_of_file")
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.

SavedModels मीट्रिक, हानि और अनुकूलक स्थिति को भी बचाता है।

इस पुनर्निर्मित मॉडल का उपयोग किया जा सकता है और उसी डेटा पर कॉल करने पर वही परिणाम देगा:

reconstructed_model(tf.constant([[2.0, 2.0, 2.0]]))
<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[5.5604653, 3.3511646]], dtype=float32)>

सुविधा समर्थन के लिए कस्टम परतों के लिए कॉन्फ़िगरेशन विधियों को प्रदान करने सहित, केरस मॉडल को सहेजने और क्रमबद्ध करने के बारे में जानने के लिए और भी बहुत कुछ है। बचत और क्रमांकन के लिए मार्गदर्शिका देखें।

आगे क्या होगा

यदि आप केरस के बारे में अधिक जानकारी जानना चाहते हैं, तो आप यहां मौजूदा केरस गाइड का अनुसरण कर सकते हैं।

tf.module पर निर्मित उच्च-स्तरीय API का एक अन्य उदाहरण tf.module का सॉनेट है, जो उनकी साइट पर कवर किया गया है।