গুগল আই/ও একটি মোড়ক! TensorFlow সেশনগুলি দেখুন সেশনগুলি দেখুন

সঠিকতা এবং সংখ্যাগত সমতা যাচাই করা

TensorFlow.org-এ দেখুন Google Colab-এ চালান GitHub এ দেখুন নোটবুক ডাউনলোড করুন

আপনার TensorFlow কোড TF1.x থেকে TF2 তে স্থানান্তরিত করার সময়, আপনার স্থানান্তরিত কোডটি TF1.x-এর মতো TF2-তে একইভাবে আচরণ করে তা নিশ্চিত করা একটি ভাল অনুশীলন।

এই নির্দেশিকাটি tf.compat.v1.keras.utils.track_tf1_style_variables মডেলিং শিম tf.keras.layers.Layer পদ্ধতিতে প্রয়োগ করে মাইগ্রেশন কোডের উদাহরণ কভার করে। TF2 মডেলিং শিমস সম্পর্কে আরও জানতে মডেল ম্যাপিং গাইড পড়ুন।

এই নির্দেশিকা বিবরণ পন্থা আপনি ব্যবহার করতে পারেন:

  • মাইগ্রেটেড কোড ব্যবহার করে প্রশিক্ষণ মডেল থেকে প্রাপ্ত ফলাফলের সঠিকতা যাচাই করুন
  • TensorFlow সংস্করণ জুড়ে আপনার কোডের সংখ্যাগত সমতা যাচাই করুন

সেটআপ

pip uninstall -y -q tensorflow
# Install tf-nightly as the DeterministicRandomTestTool is available only in
# Tensorflow 2.8
pip install -q tf-nightly
pip install -q tf_slim
import tensorflow as tf
import tensorflow.compat.v1 as v1

import numpy as np
import tf_slim as slim
import sys


from contextlib import contextmanager
!git clone --depth=1 https://github.com/tensorflow/models.git
import models.research.slim.nets.inception_resnet_v2 as inception
Cloning into 'models'...
remote: Enumerating objects: 3192, done.[K
remote: Counting objects: 100% (3192/3192), done.[K
remote: Compressing objects: 100% (2696/2696), done.[K
remote: Total 3192 (delta 848), reused 1381 (delta 453), pack-reused 0[K
Receiving objects: 100% (3192/3192), 33.39 MiB | 12.89 MiB/s, done.
Resolving deltas: 100% (848/848), done.

আপনি যদি শিমের মধ্যে ফরওয়ার্ড পাস কোডের একটি অতুচ্ছ অংশ রাখছেন, আপনি জানতে চান যে এটি TF1.x-এর মতো একইভাবে আচরণ করছে। উদাহরণস্বরূপ, শিমের মধ্যে একটি সম্পূর্ণ TF-Slim Inception-Resnet-v2 মডেল রাখার চেষ্টা করার কথা বিবেচনা করুন:

# TF1 Inception resnet v2 forward pass based on slim layers
def inception_resnet_v2(inputs, num_classes, is_training):
  with slim.arg_scope(
    inception.inception_resnet_v2_arg_scope(batch_norm_scale=True)):
    return inception.inception_resnet_v2(inputs, num_classes, is_training=is_training)
class InceptionResnetV2(tf.keras.layers.Layer):
  """Slim InceptionResnetV2 forward pass as a Keras layer"""

  def __init__(self, num_classes, **kwargs):
    super().__init__(**kwargs)
    self.num_classes = num_classes

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs, training=None):
    is_training = training or False 

    # Slim does not accept `None` as a value for is_training,
    # Keras will still pass `None` to layers to construct functional models
    # without forcing the layer to always be in training or in inference.
    # However, `None` is generally considered to run layers in inference.

    with slim.arg_scope(
        inception.inception_resnet_v2_arg_scope(batch_norm_scale=True)):
      return inception.inception_resnet_v2(
          inputs, self.num_classes, is_training=is_training)
WARNING:tensorflow:From /tmp/ipykernel_27382/2131234657.py:8: The name tf.keras.utils.track_tf1_style_variables is deprecated. Please use tf.compat.v1.keras.utils.track_tf1_style_variables instead.

যেহেতু এটি ঘটে, এই স্তরটি আসলে বাক্সের বাইরে পুরোপুরি সূক্ষ্মভাবে কাজ করে (সঠিক নিয়মিতকরণ ক্ষতি ট্র্যাকিংয়ের সাথে সম্পূর্ণ)।

যাইহোক, এটি এমন কিছু নয় যা আপনি মঞ্জুর করতে চান। নিখুঁত সাংখ্যিক সমতা পর্যবেক্ষণ করার জন্য এটি আসলে TF1.x এর মতো আচরণ করছে কিনা তা যাচাই করতে নীচের পদক্ষেপগুলি অনুসরণ করুন৷ এই পদক্ষেপগুলি আপনাকে ফরোয়ার্ড পাসের কোন অংশটি TF1.x থেকে বিচ্ছিন্নতা সৃষ্টি করছে তা ত্রিভুজ করতেও সাহায্য করতে পারে (মডেলের একটি ভিন্ন অংশের বিপরীতে মডেল ফরওয়ার্ড পাসে ভিন্নতা দেখা দেয় কিনা তা সনাক্ত করুন)।

ধাপ 1: যাচাই করুন ভেরিয়েবল শুধুমাত্র একবার তৈরি করা হয়

আপনার প্রথম যে জিনিসটি যাচাই করা উচিত তা হল আপনি সঠিকভাবে মডেলটি এমনভাবে তৈরি করেছেন যা প্রতিটি কলে ভেরিয়েবলগুলিকে ভুলবশত প্রতিবার নতুন ভেরিয়েবল তৈরি এবং ব্যবহার করার পরিবর্তে ব্যবহার করে৷ উদাহরণস্বরূপ, যদি আপনার মডেল একটি নতুন কেরাস লেয়ার তৈরি করে বা প্রতিটি ফরোয়ার্ড পাস কলে tf.Variable . ভ্যারিয়েবলকে কল করে তাহলে এটি সম্ভবত ভেরিয়েবল ক্যাপচার করতে ব্যর্থ হয় এবং প্রতিবার নতুন তৈরি করে।

নীচে দুটি কনটেক্সট ম্যানেজার স্কোপ রয়েছে যা আপনি সনাক্ত করতে ব্যবহার করতে পারেন যখন আপনার মডেল নতুন ভেরিয়েবল তৈরি করছে এবং মডেলের কোন অংশটি এটি করছে তা ডিবাগ করতে।

@contextmanager
def assert_no_variable_creations():
  """Assert no variables are created in this context manager scope."""
  def invalid_variable_creator(next_creator, **kwargs):
    raise ValueError("Attempted to create a new variable instead of reusing an existing one. Args: {}".format(kwargs))

  with tf.variable_creator_scope(invalid_variable_creator):
    yield

@contextmanager
def catch_and_raise_created_variables():
  """Raise all variables created within this context manager scope (if any)."""
  created_vars = []
  def variable_catcher(next_creator, **kwargs):
    var = next_creator(**kwargs)
    created_vars.append(var)
    return var

  with tf.variable_creator_scope(variable_catcher):
    yield
  if created_vars:
    raise ValueError("Created vars:", created_vars)

প্রথম সুযোগ ( assert_no_variable_creations() ) আপনি সুযোগের মধ্যে একটি পরিবর্তনশীল তৈরি করার চেষ্টা করার সাথে সাথেই একটি ত্রুটি উত্থাপন করবে। এটি আপনাকে স্ট্যাকট্রেস পরিদর্শন করতে দেয় (এবং ইন্টারেক্টিভ ডিবাগিং ব্যবহার করে) কোডের কোন লাইনগুলি বিদ্যমান একটিকে পুনরায় ব্যবহার করার পরিবর্তে একটি পরিবর্তনশীল তৈরি করেছে তা নির্ধারণ করতে।

দ্বিতীয় স্কোপ ( catch_and_raise_created_variables() ) স্কোপের শেষে একটি ব্যতিক্রম উত্থাপন করবে যদি কোনো ভেরিয়েবল তৈরি করা হয়। এই ব্যতিক্রমটি সুযোগে তৈরি সমস্ত ভেরিয়েবলের তালিকা অন্তর্ভুক্ত করবে। আপনার মডেল তৈরি করা সমস্ত ওজনের সেটটি কী তা খুঁজে বের করার জন্য এটি কার্যকর যদি আপনি সাধারণ নিদর্শনগুলি দেখতে পারেন। যাইহোক, কোডের সঠিক লাইনগুলি সনাক্ত করার জন্য এটি কম দরকারী যেখানে সেই ভেরিয়েবলগুলি তৈরি হয়েছে।

শিম-ভিত্তিক InceptionResnetV2 স্তর প্রথম কলের পরে (সম্ভবত সেগুলি পুনরায় ব্যবহার করে) কোনো নতুন ভেরিয়েবল তৈরি করে না তা যাচাই করতে নীচের উভয় স্কোপ ব্যবহার করুন।

model = InceptionResnetV2(1000)
height, width = 299, 299
num_classes = 1000

inputs = tf.ones( (1, height, width, 3))
# Create all weights on the first call
model(inputs)

# Verify that no new weights are created in followup calls
with assert_no_variable_creations():
  model(inputs)
with catch_and_raise_created_variables():
  model(inputs)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py:2212: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead.
  warnings.warn('`layer.apply` is deprecated and '
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tf_slim/layers/layers.py:684: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead.
  outputs = layer.apply(inputs, training=is_training)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/keras/legacy_tf_layers/core.py:332: UserWarning: `tf.layers.flatten` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Flatten` instead.
  warnings.warn('`tf.layers.flatten` is deprecated and '

নীচের উদাহরণে, এই সাজসজ্জাকারীরা কীভাবে একটি স্তরে কাজ করে তা পর্যবেক্ষণ করুন যা বিদ্যমানগুলিকে পুনরায় ব্যবহার করার পরিবর্তে প্রতিবার ভুলভাবে নতুন ওজন তৈরি করে।

class BrokenScalingLayer(tf.keras.layers.Layer):
  """Scaling layer that incorrectly creates new weights each time:"""

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs):
    var = tf.Variable(initial_value=2.0)
    bias = tf.Variable(initial_value=2.0, name='bias')
    return inputs * var + bias
model = BrokenScalingLayer()
inputs = tf.ones( (1, height, width, 3))
model(inputs)

try:
  with assert_no_variable_creations():
    model(inputs)
except ValueError as err:
  import traceback
  traceback.print_exc()
Traceback (most recent call last):
  File "/tmp/ipykernel_27382/1128777590.py", line 7, in <module>
    model(inputs)
  File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/utils/traceback_utils.py", line 67, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "/tmp/ipykernel_27382/3224979076.py", line 6, in call
    var = tf.Variable(initial_value=2.0)
  File "/tmp/ipykernel_27382/1829430118.py", line 5, in invalid_variable_creator
    raise ValueError("Attempted to create a new variable instead of reusing an existing one. Args: {}".format(kwargs))
ValueError: Exception encountered when calling layer "broken_scaling_layer" (type BrokenScalingLayer).

Attempted to create a new variable instead of reusing an existing one. Args: {'initial_value': 2.0, 'trainable': None, 'validate_shape': True, 'caching_device': None, 'name': None, 'variable_def': None, 'dtype': None, 'import_scope': None, 'constraint': None, 'synchronization': <VariableSynchronization.AUTO: 0>, 'aggregation': <VariableAggregation.NONE: 0>, 'shape': None}

Call arguments received:
  • inputs=tf.Tensor(shape=(1, 299, 299, 3), dtype=float32)
model = BrokenScalingLayer()
inputs = tf.ones( (1, height, width, 3))
model(inputs)

try:
  with catch_and_raise_created_variables():
    model(inputs)
except ValueError as err:
  print(err)
('Created vars:', [<tf.Variable 'broken_scaling_layer_1/Variable:0' shape=() dtype=float32, numpy=2.0>, <tf.Variable 'broken_scaling_layer_1/bias:0' shape=() dtype=float32, numpy=2.0>])

আপনি এটি নিশ্চিত করে স্তরটি ঠিক করতে পারেন যে এটি শুধুমাত্র একবার ওজন তৈরি করে এবং তারপরে প্রতিবার তাদের পুনরায় ব্যবহার করে।

class FixedScalingLayer(tf.keras.layers.Layer):
  """Scaling layer that incorrectly creates new weights each time:"""
  def __init__(self):
    super().__init__()
    self.var = None
    self.bias = None

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs):
    if self.var is None:
      self.var = tf.Variable(initial_value=2.0)
      self.bias = tf.Variable(initial_value=2.0, name='bias')
    return inputs * self.var + self.bias

model = FixedScalingLayer()
inputs = tf.ones( (1, height, width, 3))
model(inputs)

with assert_no_variable_creations():
  model(inputs)
with catch_and_raise_created_variables():
  model(inputs)

সমস্যা সমাধান

এখানে কিছু সাধারণ কারণ রয়েছে কেন আপনার মডেল ভুলবশত বিদ্যমানগুলিকে পুনরায় ব্যবহার করার পরিবর্তে নতুন ওজন তৈরি করতে পারে:

  1. এটি ইতিমধ্যে তৈরি tf.Variables পুনরায় ব্যবহার না করে একটি স্পষ্ট tf.Variable কল ব্যবহার করে। এটি তৈরি করা হয়নি কিনা তা আগে যাচাই করে তারপর বিদ্যমানগুলি পুনরায় ব্যবহার করে এটি ঠিক করুন।
  2. এটি প্রতিবার ফরওয়ার্ড পাসে সরাসরি কেরাস স্তর বা মডেল তৈরি করে ( tf.compat.v1.layers বিপরীতে)। এটি তৈরি করা হয়নি কিনা তা আগে যাচাই করে তারপর বিদ্যমানগুলি পুনরায় ব্যবহার করে এটি ঠিক করুন।
  3. এটি tf.compat.v1.layers এর উপরে তৈরি করা হয়েছে কিন্তু সমস্ত compat.v1.layers একটি সুস্পষ্ট নাম বরাদ্দ করতে বা আপনার compat.v1.layer ব্যবহারকে একটি নামযুক্ত variable_scope এর ভিতরে মোড়ানো ব্যর্থ হয়, যার ফলে স্বয়ংক্রিয়ভাবে তৈরি হওয়া স্তরের নামগুলি বৃদ্ধি পায় প্রতিটি মডেল কল। আপনার শিম-সজ্জিত পদ্ধতির ভিতরে একটি নামযুক্ত tf.compat.v1.variable_scope রেখে এটি ঠিক করুন যা আপনার সমস্ত tf.compat.v1.layers ব্যবহারকে মোড়ক করে।

ধাপ 2: পরিবর্তনশীল গণনা, নাম এবং আকার মেলে কিনা তা পরীক্ষা করুন

দ্বিতীয় ধাপ হল নিশ্চিত করা যে আপনার লেয়ারটি TF2 তে চলমান একই সংখ্যক ওজন তৈরি করে, একই আকারের সাথে, যেমনটি TF1.x এ সংশ্লিষ্ট কোডটি করে।

আপনি সেগুলিকে ম্যানুয়ালি চেক করে দেখতে পারেন যে তারা মেলে কিনা, এবং নীচে দেখানো হিসাবে একটি ইউনিট পরীক্ষায় প্রোগ্রামেটিকভাবে চেকগুলি করতে পারেন৷

# Build the forward pass inside a TF1.x graph, and 
# get the counts, shapes, and names of the variables
graph = tf.Graph()
with graph.as_default(), tf.compat.v1.Session(graph=graph) as sess:
  height, width = 299, 299
  num_classes = 1000
  inputs = tf.ones( (1, height, width, 3))

  out, endpoints = inception_resnet_v2(inputs, num_classes, is_training=False)

  tf1_variable_names_and_shapes = {
      var.name: (var.trainable, var.shape) for var in tf.compat.v1.global_variables()}
  num_tf1_variables = len(tf.compat.v1.global_variables())
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer_v1.py:1694: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead.
  warnings.warn('`layer.apply` is deprecated and '

এর পরে, TF2 এ শিম-মোড়ানো স্তরের জন্য একই কাজ করুন। লক্ষ্য করুন যে ওজন ধরার আগে মডেলটিকে একাধিকবার বলা হয়। পরিবর্তনশীল পুনঃব্যবহারের জন্য কার্যকরভাবে পরীক্ষা করার জন্য এটি করা হয়।

height, width = 299, 299
num_classes = 1000

model = InceptionResnetV2(num_classes)
# The weights will not be created until you call the model

inputs = tf.ones( (1, height, width, 3))
# Call the model multiple times before checking the weights, to verify variables
# get reused rather than accidentally creating additional variables
out, endpoints = model(inputs, training=False)
out, endpoints = model(inputs, training=False)

# Grab the name: shape mapping and the total number of variables separately,
# because in TF2 variables can be created with the same name
num_tf2_variables = len(model.variables)
tf2_variable_names_and_shapes = {
    var.name: (var.trainable, var.shape) for var in model.variables}
2021-12-04 02:27:27.209445: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
# Verify that the variable counts, names, and shapes all match:
assert num_tf1_variables == num_tf2_variables
assert tf1_variable_names_and_shapes == tf2_variable_names_and_shapes

শিম-ভিত্তিক InceptionResnetV2 স্তরটি এই পরীক্ষায় উত্তীর্ণ হয়। যাইহোক, যেখানে তারা মেলে না, সেখানে পার্থক্যগুলি কোথায় তা দেখতে আপনি এটি একটি ডিফ (টেক্সট বা অন্য) মাধ্যমে চালাতে পারেন।

মডেলের কোন অংশটি প্রত্যাশিতভাবে আচরণ করছে না তা এটি একটি সূত্র প্রদান করতে পারে। উদগ্রীবভাবে সম্পাদনের সাথে আপনি pdb, ইন্টারেক্টিভ ডিবাগিং, এবং ব্রেকপয়েন্ট ব্যবহার করতে পারেন মডেলের যে অংশগুলিকে সন্দেহজনক বলে মনে হচ্ছে সেগুলি খনন করতে, এবং আরও গভীরতায় কী ভুল হচ্ছে তা ডিবাগ করতে পারেন৷

সমস্যা সমাধান

  • স্পষ্ট tf.Variable . ভেরিয়েবল কল এবং কেরাস লেয়ার/মডেল দ্বারা সরাসরি তৈরি যেকোন ভেরিয়েবলের নামের প্রতি গভীর মনোযোগ দিন কারণ তাদের পরিবর্তনশীল নামের জেনারেশনের শব্দার্থবিদ্যা TF1.x গ্রাফ এবং TF2 কার্যকারিতার মধ্যে সামান্য ভিন্ন হতে পারে যেমন উদগ্রীব এক্সিকিউশন এবং tf.function .ফাংশন সবকিছু হলেও অন্য সঠিকভাবে কাজ করছে। যদি এটি আপনার ক্ষেত্রে হয়, তবে সামান্য ভিন্ন নামকরণের শব্দার্থের জন্য আপনার পরীক্ষাটি সামঞ্জস্য করুন।

  • আপনি কখনও কখনও দেখতে পারেন যে আপনার প্রশিক্ষণ লুপের ফরোয়ার্ড পাসে তৈরি tf.Variable s, tf.keras.layers.Layer s, বা tf.keras.Model গুলি আপনার TF2 ভেরিয়েবল তালিকা থেকে অনুপস্থিত রয়েছে এমনকি যদি সেগুলি ভেরিয়েবল সংগ্রহের দ্বারা ধরা হয় TF1.x-এ আপনার ফরওয়ার্ড পাস আপনার মডেলের ইনস্ট্যান্স অ্যাট্রিবিউটের জন্য যে ভেরিয়েবল/স্তর/মডেল তৈরি করে তা নির্ধারণ করে এটি ঠিক করুন। আরও তথ্যের জন্য এখানে দেখুন.

ধাপ 3: সমস্ত ভেরিয়েবল রিসেট করুন, সমস্ত এলোমেলোতা অক্ষম করে সাংখ্যিক সমতা পরীক্ষা করুন

পরবর্তী পদক্ষেপটি হল প্রকৃত আউটপুট এবং নিয়মিতকরণ ক্ষতি ট্র্যাকিং উভয়ের জন্য সংখ্যাসূচক সমতা যাচাই করা যখন আপনি মডেলটি ঠিক করেন যাতে কোনও র্যান্ডম সংখ্যা তৈরি না হয় (যেমন অনুমানের সময়)।

এটি করার সঠিক উপায় আপনার নির্দিষ্ট মডেলের উপর নির্ভর করতে পারে, তবে বেশিরভাগ মডেলে (যেমন এটি), আপনি এটি করতে পারেন:

  1. কোনো এলোমেলোতা ছাড়াই একই মানের ওজন শুরু করা হচ্ছে। এটি তৈরি হওয়ার পরে তাদের একটি নির্দিষ্ট মানতে পুনরায় সেট করে এটি করা যেতে পারে।
  2. ড্রপআউট স্তরগুলিকে ট্রিগার না করার জন্য অনুমান মোডে মডেলটি চালানো যা এলোমেলোতার উত্স হতে পারে।

নিম্নলিখিত কোডটি দেখায় কিভাবে আপনি এইভাবে TF1.x এবং TF2 ফলাফল তুলনা করতে পারেন।

graph = tf.Graph()
with graph.as_default(), tf.compat.v1.Session(graph=graph) as sess:
  height, width = 299, 299
  num_classes = 1000
  inputs = tf.ones( (1, height, width, 3))

  out, endpoints = inception_resnet_v2(inputs, num_classes, is_training=False)

  # Rather than running the global variable initializers,
  # reset all variables to a constant value
  var_reset = tf.group([var.assign(tf.ones_like(var) * 0.001) for var in tf.compat.v1.global_variables()])
  sess.run(var_reset)

  # Grab the outputs & regularization loss
  reg_losses = tf.compat.v1.get_collection(tf.compat.v1.GraphKeys.REGULARIZATION_LOSSES)
  tf1_regularization_loss = sess.run(tf.math.add_n(reg_losses))
  tf1_output = sess.run(out)

print("Regularization loss:", tf1_regularization_loss)
tf1_output[0][:5]
Regularization loss: 0.001182976
array([0.00299837, 0.00299837, 0.00299837, 0.00299837, 0.00299837],
      dtype=float32)

TF2 ফলাফল পান।

height, width = 299, 299
num_classes = 1000

model = InceptionResnetV2(num_classes)

inputs = tf.ones((1, height, width, 3))
# Call the model once to create the weights
out, endpoints = model(inputs, training=False)

# Reset all variables to the same fixed value as above, with no randomness
for var in model.variables:
  var.assign(tf.ones_like(var) * 0.001)
tf2_output, endpoints = model(inputs, training=False)

# Get the regularization loss
tf2_regularization_loss = tf.math.add_n(model.losses)

print("Regularization loss:", tf2_regularization_loss)
tf2_output[0][:5]
Regularization loss: tf.Tensor(0.0011829757, shape=(), dtype=float32)
<tf.Tensor: shape=(5,), dtype=float32, numpy=
array([0.00299837, 0.00299837, 0.00299837, 0.00299837, 0.00299837],
      dtype=float32)>
# Create a dict of tolerance values
tol_dict={'rtol':1e-06, 'atol':1e-05}
# Verify that the regularization loss and output both match
# when we fix the weights and avoid randomness by running inference:
np.testing.assert_allclose(tf1_regularization_loss, tf2_regularization_loss.numpy(), **tol_dict)
np.testing.assert_allclose(tf1_output, tf2_output.numpy(), **tol_dict)

সংখ্যাগুলি TF1.x এবং TF2 এর মধ্যে মেলে যখন আপনি এলোমেলোতার উত্সগুলি সরিয়ে দেন এবং TF2-সামঞ্জস্যপূর্ণ InceptionResnetV2 স্তরটি পরীক্ষায় উত্তীর্ণ হয়৷

আপনি যদি আপনার নিজের মডেলের জন্য ফলাফলগুলিকে বিচ্যুত করতে দেখে থাকেন, তাহলে আপনি প্রিন্টিং বা pdb এবং ইন্টারেক্টিভ ডিবাগিং ব্যবহার করতে পারেন যাতে ফলাফলগুলি কোথায় এবং কেন বিচ্ছিন্ন হতে শুরু করে। আগ্রহী মৃত্যুদন্ড এটি উল্লেখযোগ্যভাবে সহজ করতে পারে। স্থির মধ্যবর্তী ইনপুটগুলিতে মডেলের শুধুমাত্র ছোট অংশগুলি চালানোর জন্য এবং যেখানে বিচ্ছিন্নতা ঘটে সেখানে বিচ্ছিন্ন করার জন্য আপনি একটি অ্যাবলেশন পদ্ধতি ব্যবহার করতে পারেন।

সুবিধামত, অনেক স্লিম নেট (এবং অন্যান্য মডেল) মধ্যবর্তী শেষ পয়েন্টগুলিও প্রকাশ করে যা আপনি অনুসন্ধান করতে পারেন।

ধাপ 4: এলোমেলো সংখ্যা তৈরি করুন, প্রশিক্ষণ এবং অনুমান উভয় ক্ষেত্রেই সংখ্যাগত সমতা পরীক্ষা করুন

ভেরিয়েবল ইনিশিয়ালাইজেশনে এবং ফরোয়ার্ড পাস নিজেই (যেমন ফরোয়ার্ড পাসের সময় ড্রপআউট স্তর) র্যান্ডম সংখ্যা তৈরির জন্য অ্যাকাউন্টিং করার সময়ও, TF2 মডেলটি সংখ্যাগতভাবে TF1.x মডেলের সাথে মেলে কিনা তা যাচাই করা চূড়ান্ত পদক্ষেপ।

TF1.x গ্রাফ/সেশন এবং উদগ্রীব সম্পাদনের মধ্যে র্যান্ডম নম্বর জেনারেশনের শব্দার্থ সামঞ্জস্য করতে আপনি নীচের টেস্টিং টুল ব্যবহার করে এটি করতে পারেন।

TF1 লিগ্যাসি গ্রাফ/সেশন এবং TF2 আগ্রহী এক্সিকিউশন বিভিন্ন স্টেটফুল এলোমেলো সংখ্যা জেনারেশন শব্দার্থ ব্যবহার করে।

tf.compat.v1.Session s-এ, যদি কোনও বীজ নির্দিষ্ট করা না থাকে, র্যান্ডম নম্বর জেনারেশন নির্ভর করে গ্রাফে কতগুলি অপারেশন আছে যখন র্যান্ডম অপারেশন যোগ করা হয় এবং কতবার গ্রাফটি চালানো হয়। উদগ্রীব সঞ্চালনে, স্টেটফুল র্যান্ডম সংখ্যা তৈরি নির্ভর করে গ্লোবাল সিড, অপারেশন এলোমেলো বীজ, এবং কতবার প্রদত্ত এলোমেলো বীজ দিয়ে অপারেশন চালানো হয়। আরও তথ্যের জন্য tf.random.set_seed দেখুন।

নিম্নলিখিত v1.keras.utils.DeterministicRandomTestTool ক্লাস একটি প্রসঙ্গ ব্যবস্থাপক scope() প্রদান করে যা রাষ্ট্রীয় র্যান্ডম অপারেশনগুলিকে TF1 গ্রাফ/সেশন এবং আগ্রহী সম্পাদন উভয় ক্ষেত্রেই একই বীজ ব্যবহার করতে পারে।

টুল দুটি পরীক্ষার মোড প্রদান করে:

  1. constant যা প্রতিটি একক অপারেশনের জন্য একই বীজ ব্যবহার করে তা যতবারই বলা হোক না কেন এবং,
  2. num_random_ops যা অপারেশন বীজ হিসাবে পূর্বে-পর্যবেক্ষিত স্টেটফুল র্যান্ডম অপারেশনের সংখ্যা ব্যবহার করে।

এটি ভেরিয়েবল তৈরি এবং আরম্ভ করার জন্য ব্যবহৃত স্টেটফুল র্যান্ডম অপারেশন এবং গণনায় ব্যবহৃত স্টেটফুল র্যান্ডম অপারেশন উভয় ক্ষেত্রেই প্রযোজ্য (যেমন ড্রপআউট স্তরগুলির জন্য)।

সেশন এবং উদগ্রীব সম্পাদনের মধ্যে স্টেটফুল র্যান্ডম নম্বর জেনারেশন ম্যাচ করতে এই টুলটি কীভাবে ব্যবহার করবেন তা দেখানোর জন্য তিনটি র্যান্ডম টেনসর তৈরি করুন।

random_tool = v1.keras.utils.DeterministicRandomTestTool()
with random_tool.scope():
  graph = tf.Graph()
  with graph.as_default(), tf.compat.v1.Session(graph=graph) as sess:
    a = tf.random.uniform(shape=(3,1))
    a = a * 3
    b = tf.random.uniform(shape=(3,3))
    b = b * 3
    c = tf.random.uniform(shape=(3,3))
    c = c * 3
    graph_a, graph_b, graph_c = sess.run([a, b, c])

graph_a, graph_b, graph_c
(array([[2.5063772],
        [2.7488918],
        [1.4839486]], dtype=float32),
 array([[2.5063772, 2.7488918, 1.4839486],
        [1.5633398, 2.1358476, 1.3693532],
        [0.3598416, 1.8287641, 2.5314465]], dtype=float32),
 array([[2.5063772, 2.7488918, 1.4839486],
        [1.5633398, 2.1358476, 1.3693532],
        [0.3598416, 1.8287641, 2.5314465]], dtype=float32))
random_tool = v1.keras.utils.DeterministicRandomTestTool()
with random_tool.scope():
  a = tf.random.uniform(shape=(3,1))
  a = a * 3
  b = tf.random.uniform(shape=(3,3))
  b = b * 3
  c = tf.random.uniform(shape=(3,3))
  c = c * 3

a, b, c
(<tf.Tensor: shape=(3, 1), dtype=float32, numpy=
 array([[2.5063772],
        [2.7488918],
        [1.4839486]], dtype=float32)>,
 <tf.Tensor: shape=(3, 3), dtype=float32, numpy=
 array([[2.5063772, 2.7488918, 1.4839486],
        [1.5633398, 2.1358476, 1.3693532],
        [0.3598416, 1.8287641, 2.5314465]], dtype=float32)>,
 <tf.Tensor: shape=(3, 3), dtype=float32, numpy=
 array([[2.5063772, 2.7488918, 1.4839486],
        [1.5633398, 2.1358476, 1.3693532],
        [0.3598416, 1.8287641, 2.5314465]], dtype=float32)>)
# Demonstrate that the generated random numbers match
np.testing.assert_allclose(graph_a, a.numpy(), **tol_dict)
np.testing.assert_allclose(graph_b, b.numpy(), **tol_dict)
np.testing.assert_allclose(graph_c, c.numpy(), **tol_dict)

যাইহোক, লক্ষ্য করুন যে constant মোডে, কারণ b এবং c একই বীজ দিয়ে তৈরি হয়েছিল এবং একই আকার রয়েছে, তাদের ঠিক একই মান থাকবে।

np.testing.assert_allclose(b.numpy(), c.numpy(), **tol_dict)

ট্রেস অর্ডার

আপনি যদি constant মোডে মিলে যাওয়া কিছু র্যান্ডম সংখ্যা নিয়ে চিন্তিত হন যা আপনার সংখ্যাসূচক সমতা পরীক্ষায় আপনার আত্মবিশ্বাসকে হ্রাস করে (উদাহরণস্বরূপ যদি একই প্রারম্ভে একাধিক ওজন গ্রহণ করে), আপনি এটি এড়াতে num_random_ops মোড ব্যবহার করতে পারেন। num_random_ops মোডে, জেনারেট হওয়া র্যান্ডম সংখ্যাগুলি প্রোগ্রামে র্যান্ডম অপ্সের অর্ডারের উপর নির্ভর করবে।

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  graph = tf.Graph()
  with graph.as_default(), tf.compat.v1.Session(graph=graph) as sess:
    a = tf.random.uniform(shape=(3,1))
    a = a * 3
    b = tf.random.uniform(shape=(3,3))
    b = b * 3
    c = tf.random.uniform(shape=(3,3))
    c = c * 3
    graph_a, graph_b, graph_c = sess.run([a, b, c])

graph_a, graph_b, graph_c
(array([[2.5063772],
        [2.7488918],
        [1.4839486]], dtype=float32),
 array([[0.45038545, 1.9197761 , 2.4536333 ],
        [1.0371652 , 2.9898582 , 1.924583  ],
        [0.25679827, 1.6579313 , 2.8418403 ]], dtype=float32),
 array([[2.9634383 , 1.0862181 , 2.6042497 ],
        [0.70099247, 2.3920312 , 1.0470468 ],
        [0.18173039, 0.8359269 , 1.0508587 ]], dtype=float32))
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  a = tf.random.uniform(shape=(3,1))
  a = a * 3
  b = tf.random.uniform(shape=(3,3))
  b = b * 3
  c = tf.random.uniform(shape=(3,3))
  c = c * 3

a, b, c
(<tf.Tensor: shape=(3, 1), dtype=float32, numpy=
 array([[2.5063772],
        [2.7488918],
        [1.4839486]], dtype=float32)>,
 <tf.Tensor: shape=(3, 3), dtype=float32, numpy=
 array([[0.45038545, 1.9197761 , 2.4536333 ],
        [1.0371652 , 2.9898582 , 1.924583  ],
        [0.25679827, 1.6579313 , 2.8418403 ]], dtype=float32)>,
 <tf.Tensor: shape=(3, 3), dtype=float32, numpy=
 array([[2.9634383 , 1.0862181 , 2.6042497 ],
        [0.70099247, 2.3920312 , 1.0470468 ],
        [0.18173039, 0.8359269 , 1.0508587 ]], dtype=float32)>)
# Demonstrate that the generated random numbers match
np.testing.assert_allclose(graph_a, a.numpy(), **tol_dict)
np.testing.assert_allclose(graph_b, b.numpy(), **tol_dict )
np.testing.assert_allclose(graph_c, c.numpy(), **tol_dict)
# Demonstrate that with the 'num_random_ops' mode,
# b & c took on different values even though
# their generated shape was the same
assert not np.allclose(b.numpy(), c.numpy(), **tol_dict)

যাইহোক, লক্ষ্য করুন যে এই মোডে র্যান্ডম জেনারেশন প্রোগ্রাম অর্ডারের জন্য সংবেদনশীল, এবং তাই নিম্নলিখিত তৈরি হওয়া র্যান্ডম সংখ্যাগুলি মেলে না।

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  a = tf.random.uniform(shape=(3,1))
  a = a * 3
  b = tf.random.uniform(shape=(3,3))
  b = b * 3

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  b_prime = tf.random.uniform(shape=(3,3))
  b_prime = b_prime * 3
  a_prime = tf.random.uniform(shape=(3,1))
  a_prime = a_prime * 3

assert not np.allclose(a.numpy(), a_prime.numpy())
assert not np.allclose(b.numpy(), b_prime.numpy())

ট্রেসিং অর্ডারের কারণে ডিবাগিং বৈচিত্র্যের জন্য অনুমতি দিতে, num_random_ops মোডে DeterministicRandomTestTool আপনাকে অপারেশন_seed বৈশিষ্ট্যের সাথে কতগুলি র্যান্ডম operation_seed ট্রেস করা হয়েছে তা দেখতে দেয়।

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  print(random_tool.operation_seed)
  a = tf.random.uniform(shape=(3,1))
  a = a * 3
  print(random_tool.operation_seed)
  b = tf.random.uniform(shape=(3,3))
  b = b * 3
  print(random_tool.operation_seed)
0
1
2

আপনি যদি আপনার পরীক্ষায় বিভিন্ন ট্রেস অর্ডারের জন্য অ্যাকাউন্ট করতে চান, আপনি এমনকি স্বয়ংক্রিয়-বৃদ্ধি operation_seed স্পষ্টভাবে সেট করতে পারেন। উদাহরণস্বরূপ, আপনি দুটি ভিন্ন প্রোগ্রাম অর্ডার জুড়ে এলোমেলো সংখ্যা তৈরি করতে এটি ব্যবহার করতে পারেন।

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  print(random_tool.operation_seed)
  a = tf.random.uniform(shape=(3,1))
  a = a * 3
  print(random_tool.operation_seed)
  b = tf.random.uniform(shape=(3,3))
  b = b * 3

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  random_tool.operation_seed = 1
  b_prime = tf.random.uniform(shape=(3,3))
  b_prime = b_prime * 3
  random_tool.operation_seed = 0
  a_prime = tf.random.uniform(shape=(3,1))
  a_prime = a_prime * 3

np.testing.assert_allclose(a.numpy(), a_prime.numpy(), **tol_dict)
np.testing.assert_allclose(b.numpy(), b_prime.numpy(), **tol_dict)
0
1

যাইহোক, DeterministicRandomTestTool ইতিমধ্যে-ব্যবহৃত অপারেশন বীজ পুনরায় ব্যবহার করার অনুমতি দেয় না, তাই নিশ্চিত করুন যে স্বয়ংক্রিয়-বর্ধিত ক্রমগুলি ওভারল্যাপ করতে পারে না। এর কারণ হল আগ্রহী সঞ্চালন একই অপারেশন বীজের ফলো-অন ব্যবহারের জন্য বিভিন্ন সংখ্যা তৈরি করে যখন TF1 গ্রাফ এবং সেশনগুলি তা করে না, তাই একটি ত্রুটি উত্থাপন সেশন এবং আগ্রহী স্টেটফুল র্যান্ডম সংখ্যা তৈরি করতে সাহায্য করে।

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  random_tool.operation_seed = 1
  b_prime = tf.random.uniform(shape=(3,3))
  b_prime = b_prime * 3
  random_tool.operation_seed = 0
  a_prime = tf.random.uniform(shape=(3,1))
  a_prime = a_prime * 3
  try:
    c = tf.random.uniform(shape=(3,1))
    raise RuntimeError("An exception should have been raised before this, " +
                     "because the auto-incremented operation seed will " +
                     "overlap an already-used value")
  except ValueError as err:
    print(err)
This `DeterministicRandomTestTool` object is trying to re-use the already-used operation seed 1. It cannot guarantee random numbers will match between eager and sessions when an operation seed is reused. You most likely set `operation_seed` explicitly but used a value that caused the naturally-incrementing operation seed sequences to overlap with an already-used seed.

অনুমান যাচাই করা হচ্ছে

আপনি এখন DeterministicRandomTestTool ব্যবহার করতে পারেন যাতে InceptionResnetV2 মডেল অনুমানের সাথে মিলে যায়, এমনকি র্যান্ডম ওজন ইনিশিয়ালাইজেশন ব্যবহার করার সময়ও। প্রোগ্রাম অর্ডারের সাথে মিলে যাওয়ার কারণে একটি শক্তিশালী পরীক্ষার শর্তের জন্য, num_random_ops মোড ব্যবহার করুন।

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  graph = tf.Graph()
  with graph.as_default(), tf.compat.v1.Session(graph=graph) as sess:
    height, width = 299, 299
    num_classes = 1000
    inputs = tf.ones( (1, height, width, 3))

    out, endpoints = inception_resnet_v2(inputs, num_classes, is_training=False)

    # Initialize the variables
    sess.run(tf.compat.v1.global_variables_initializer())

    # Grab the outputs & regularization loss
    reg_losses = tf.compat.v1.get_collection(tf.compat.v1.GraphKeys.REGULARIZATION_LOSSES)
    tf1_regularization_loss = sess.run(tf.math.add_n(reg_losses))
    tf1_output = sess.run(out)

  print("Regularization loss:", tf1_regularization_loss)
Regularization loss: 1.2254326
height, width = 299, 299
num_classes = 1000

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  model = InceptionResnetV2(num_classes)

  inputs = tf.ones((1, height, width, 3))
  tf2_output, endpoints = model(inputs, training=False)

  # Grab the regularization loss as well
  tf2_regularization_loss = tf.math.add_n(model.losses)

print("Regularization loss:", tf2_regularization_loss)
Regularization loss: tf.Tensor(1.2254325, shape=(), dtype=float32)
# Verify that the regularization loss and output both match
# when using the DeterministicRandomTestTool:
np.testing.assert_allclose(tf1_regularization_loss, tf2_regularization_loss.numpy(), **tol_dict)
np.testing.assert_allclose(tf1_output, tf2_output.numpy(), **tol_dict)

প্রশিক্ষণ যাচাই

যেহেতু DeterministicRandomTestTool সমস্ত স্টেটফুল র্যান্ডম অপারেশনের জন্য কাজ করে (ওয়েট ইনিশিয়ালাইজেশন এবং ড্রপআউট লেয়ারের মতো কম্পিউটেশন উভয়ই সহ), আপনি ট্রেনিং মোডে মডেলের মিল যাচাই করতেও এটি ব্যবহার করতে পারেন। আপনি আবার num_random_ops মোড ব্যবহার করতে পারেন কারণ স্টেটফুল র্যান্ডম অপ্সের প্রোগ্রামের ক্রম মেলে।

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  graph = tf.Graph()
  with graph.as_default(), tf.compat.v1.Session(graph=graph) as sess:
    height, width = 299, 299
    num_classes = 1000
    inputs = tf.ones( (1, height, width, 3))

    out, endpoints = inception_resnet_v2(inputs, num_classes, is_training=True)

    # Initialize the variables
    sess.run(tf.compat.v1.global_variables_initializer())

    # Grab the outputs & regularization loss
    reg_losses = tf.compat.v1.get_collection(tf.compat.v1.GraphKeys.REGULARIZATION_LOSSES)
    tf1_regularization_loss = sess.run(tf.math.add_n(reg_losses))
    tf1_output = sess.run(out)

  print("Regularization loss:", tf1_regularization_loss)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/layers/normalization/batch_normalization.py:532: _colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Colocations handled automatically by placer.
Regularization loss: 1.22548
height, width = 299, 299
num_classes = 1000

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  model = InceptionResnetV2(num_classes)

  inputs = tf.ones((1, height, width, 3))
  tf2_output, endpoints = model(inputs, training=True)

  # Grab the regularization loss as well
  tf2_regularization_loss = tf.math.add_n(model.losses)

print("Regularization loss:", tf2_regularization_loss)
Regularization loss: tf.Tensor(1.2254798, shape=(), dtype=float32)
# Verify that the regularization loss and output both match
# when using the DeterministicRandomTestTool
np.testing.assert_allclose(tf1_regularization_loss, tf2_regularization_loss.numpy(), **tol_dict)
np.testing.assert_allclose(tf1_output, tf2_output.numpy(), **tol_dict)

আপনি এখন যাচাই করেছেন যে InceptionResnetV2 মডেলটি tf.keras.layers.Layer এর চারপাশে ডেকোরেটরদের সাথে সাগ্রহে চলছে। TF1 গ্রাফ এবং সেশনে চলমান স্লিম নেটওয়ার্কের সাথে সংখ্যাগতভাবে মেলে।

উদাহরণ স্বরূপ, InceptionResnetV2 লেয়ারকে সরাসরি কল করা training=True ইন্টারলিভস ভেরিয়েবল ইনিশিয়ালাইজেশনকে নেটওয়ার্ক তৈরির ক্রম অনুসারে ড্রপআউট অর্ডার সহ।

অন্যদিকে, প্রথমে কেরাস ফাংশনাল মডেলে tf.keras.layers.Layer ডেকোরেটর স্থাপন করা এবং শুধুমাত্র তারপর training=True সমস্ত ভেরিয়েবল শুরু করার সমতুল্য তারপর ড্রপআউট লেয়ার ব্যবহার করে। এটি একটি ভিন্ন ট্রেসিং অর্ডার এবং র্যান্ডম সংখ্যার একটি ভিন্ন সেট তৈরি করে।

যাইহোক, ডিফল্ট mode='constant' ট্রেসিং অর্ডারের এই পার্থক্যগুলির প্রতি সংবেদনশীল নয় এবং কেরাস কার্যকরী মডেলে স্তরটি এমবেড করার সময়ও অতিরিক্ত কাজ ছাড়াই পাস হবে।

random_tool = v1.keras.utils.DeterministicRandomTestTool()
with random_tool.scope():
  graph = tf.Graph()
  with graph.as_default(), tf.compat.v1.Session(graph=graph) as sess:
    height, width = 299, 299
    num_classes = 1000
    inputs = tf.ones( (1, height, width, 3))

    out, endpoints = inception_resnet_v2(inputs, num_classes, is_training=True)

    # Initialize the variables
    sess.run(tf.compat.v1.global_variables_initializer())

    # Get the outputs & regularization losses
    reg_losses = tf.compat.v1.get_collection(tf.compat.v1.GraphKeys.REGULARIZATION_LOSSES)
    tf1_regularization_loss = sess.run(tf.math.add_n(reg_losses))
    tf1_output = sess.run(out)

  print("Regularization loss:", tf1_regularization_loss)
Regularization loss: 1.2239965
height, width = 299, 299
num_classes = 1000

random_tool = v1.keras.utils.DeterministicRandomTestTool()
with random_tool.scope():
  keras_input = tf.keras.Input(shape=(height, width, 3))
  layer = InceptionResnetV2(num_classes)
  model = tf.keras.Model(inputs=keras_input, outputs=layer(keras_input))

  inputs = tf.ones((1, height, width, 3))
  tf2_output, endpoints = model(inputs, training=True)

  # Get the regularization loss
  tf2_regularization_loss = tf.math.add_n(model.losses)

print("Regularization loss:", tf2_regularization_loss)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py:1345: UserWarning: `layer.updates` will be removed in a future version. This property should not be used in TensorFlow 2.0, as `updates` are applied automatically.
  warnings.warn('`layer.updates` will be removed in a future version. '
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/base.py:573: UserWarning: `layer.updates` will be removed in a future version. This property should not be used in TensorFlow 2.0, as `updates` are applied automatically.
  _add_elements_to_collection(self.updates, tf.compat.v1.GraphKeys.UPDATE_OPS)
Regularization loss: tf.Tensor(1.2239964, shape=(), dtype=float32)
# Verify that the regularization loss and output both match
# when using the DeterministicRandomTestTool
np.testing.assert_allclose(tf1_regularization_loss, tf2_regularization_loss.numpy(), **tol_dict)
np.testing.assert_allclose(tf1_output, tf2_output.numpy(), **tol_dict)

ধাপ 3b বা 4b (ঐচ্ছিক): আগে থেকে বিদ্যমান চেকপয়েন্টের সাথে পরীক্ষা করা

উপরের ধাপ 3 বা ধাপ 4 এর পরে, আপনার কাছে কিছু থাকলে পূর্ব-বিদ্যমান নাম-ভিত্তিক চেকপয়েন্ট থেকে শুরু করে আপনার সংখ্যাসূচক সমতা পরীক্ষা চালানোর জন্য এটি কার্যকর হতে পারে। এটি উভয়ই পরীক্ষা করতে পারে যে আপনার উত্তরাধিকার চেকপয়েন্ট লোডিং সঠিকভাবে কাজ করছে এবং মডেল নিজেই সঠিকভাবে কাজ করছে। TF1.x চেকপয়েন্ট পুনঃব্যবহারের নির্দেশিকা কভার করে যে কীভাবে আপনার আগে থেকে বিদ্যমান TF1.x চেকপয়েন্টগুলি পুনরায় ব্যবহার করবেন এবং সেগুলিকে TF2 চেকপয়েন্টে স্থানান্তর করবেন।

অতিরিক্ত পরীক্ষা এবং সমস্যা সমাধান

আপনি আরও সংখ্যাসূচক সমতুল্য পরীক্ষা যোগ করার সাথে সাথে আপনি একটি পরীক্ষা যোগ করতেও বেছে নিতে পারেন যা আপনার গ্রেডিয়েন্ট গণনা (বা এমনকি আপনার অপ্টিমাইজার আপডেট) মিল যাচাই করে।

ব্যাকপ্রোপ্যাগেশন এবং গ্রেডিয়েন্ট কম্পিউটেশন মডেল ফরোয়ার্ড পাসের তুলনায় ফ্লোটিং পয়েন্ট সংখ্যাসূচক অস্থিরতার জন্য বেশি প্রবণ। এর মানে হল যে আপনার সমতুলতা পরীক্ষাগুলি আপনার প্রশিক্ষণের আরও অ-বিচ্ছিন্ন অংশগুলিকে কভার করে, আপনি সম্পূর্ণরূপে সাগ্রহে চালানো এবং আপনার TF1 গ্রাফের মধ্যে অ-তুচ্ছ সংখ্যাগত পার্থক্য দেখতে শুরু করতে পারেন। এটি TensorFlow এর গ্রাফ অপ্টিমাইজেশনের কারণে হতে পারে যা কিছু গাণিতিক ক্রিয়াকলাপ সহ একটি গ্রাফে সাব এক্সপ্রেশন প্রতিস্থাপন করার মতো কাজ করে।

এটি হওয়ার সম্ভাবনা আছে কিনা তা বিচ্ছিন্ন করার জন্য, আপনি আপনার TF1 কোডটিকে একটি সম্পূর্ণরূপে উত্সাহী গণনার পরিবর্তে একটি tf.function (যা আপনার TF1 গ্রাফের মতো গ্রাফ অপ্টিমাইজেশান পাসগুলি প্রয়োগ করে) এর ভিতরে ঘটছে TF2 কম্পিউটেশনের সাথে তুলনা করতে পারেন। বিকল্পভাবে, আপনি আপনার TF1 গণনার আগে অপ্টিমাইজেশন পাসগুলি যেমন "arithmetic_optimization" অক্ষম করতে tf.config.optimizer.set_experimental_options ব্যবহার করে দেখতে পারেন যে ফলাফলটি আপনার TF2 গণনার ফলাফলের সংখ্যাগতভাবে শেষ হয়েছে কিনা। আপনার প্রকৃত প্রশিক্ষণে এটি সুপারিশ করা হয় যে আপনি পারফরম্যান্সের কারণে অপ্টিমাইজেশান পাসগুলি সক্ষম সহ tf.function ব্যবহার করুন, তবে আপনার সংখ্যাসূচক সমতুল্য ইউনিট পরীক্ষায় সেগুলি অক্ষম করা আপনার পক্ষে কার্যকর হতে পারে।

একইভাবে, আপনি এটিও দেখতে পারেন যে tf.compat.v1.train অপ্টিমাইজার এবং TF2 অপ্টিমাইজারগুলির মধ্যে TF2 অপ্টিমাইজারগুলির থেকে সামান্য ভিন্ন ফ্লোটিং পয়েন্ট নিউমেরিক বৈশিষ্ট্য রয়েছে, এমনকি যদি তারা প্রতিনিধিত্ব করছে এমন গাণিতিক সূত্রগুলি একই হয়। এটি আপনার প্রশিক্ষণের ক্ষেত্রে একটি সমস্যা হওয়ার সম্ভাবনা কম, তবে এটি সমতুল্য ইউনিট পরীক্ষায় একটি উচ্চ সংখ্যাগত সহনশীলতার প্রয়োজন হতে পারে।