This page was translated by the Cloud Translation API.
Switch to English

গ্রাফ এবং tf.function পরিচিতি

টেনসরফ্লো.আর.জে দেখুন গুগল কোলাবে চালান গিটহাবের উত্স দেখুন নোটবুক ডাউনলোড করুন

ওভারভিউ

টেনসরফ্লো কীভাবে কাজ করে তা দেখতে এই গাইড টেনসরফ্লো এবং কেরাসের পৃষ্ঠের নীচে যায়। আপনি যদি পরিবর্তে কেরাস দিয়ে শুরু করতে চান তবে দয়া করে আমাদের কেরাস গাইডের সংগ্রহ দেখুন collection

এই গাইডটিতে আপনি কীভাবে টেনসরফ্লো আপনাকে গ্রাফগুলি পেতে আপনার কোডে সাধারণ পরিবর্তন করতে দেয় এবং সেগুলি কীভাবে সংরক্ষণ এবং উপস্থাপিত হয় এবং আপনি কীভাবে এগুলি আপনার মডেলগুলি ত্বরান্বিত ও রফতানি করতে পারবেন তা দেখতে পাবেন of

এটি একটি স্বল্প-ফর্ম পরিচিতি; এই ধারণাগুলির সম্পূর্ণ tf.function জন্য tf.function গাইডটি দেখুন

গ্রাফ কি?

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

কিছু ব্যবহারকারীর জন্য পাইথন আপনার কখনও প্রয়োজন বা ত্যাগ করতে নাও পারে।

তবে পাইথনে টেনসরফ্লো অপ-বাই-ওপ চালানো অন্যথায় উপলব্ধ প্রচুর ত্বরণকে বাধা দেয়। যদি আপনি পাইথন থেকে টেনসর গণনা বের করতে পারেন তবে এগুলি একটি গ্রাফে পরিণত করতে পারেন।

গ্রাফগুলি ডেটা স্ট্রাকচার যা tf.Operation অবজেক্টের একটি সেট থাকে, যা গণনার ইউনিট উপস্থাপন করে; এবং tf.Tensor অবজেক্টস, যা অপারেশনের মধ্যে প্রবাহিত ডেটার ইউনিটগুলির প্রতিনিধিত্ব করে। এগুলি একটি tf.Graph . tf.Graph প্রসঙ্গে সংজ্ঞায়িত করা হয়। যেহেতু এই গ্রাফগুলি ডেটা স্ট্রাকচার, সেগুলি মূল পাইথন কোড ব্যতীত সেভ, চালানো এবং পুনরুদ্ধার করা যায়।

টেনসরবোর্ডে ভিজ্যুয়ালাইজ করার সময় এটি একটি সাধারণ দ্বি-স্তরের গ্রাফের মতো দেখাবে।

একটি দ্বি-স্তর টেনসরফ্লো গ্রাফ

গ্রাফের সুবিধা

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

গ্রাফগুলি সহজেই অনুকূলিত করা হয়, সংকলককে যেমন রূপান্তর করতে দেয়:

  • আপনার গণনায় ধ্রুবক নোডগুলি ভাঁজ করে ("ধ্রুবক ভাঁজ") স্থায়ীভাবে টেঞ্জারগুলির মান নির্ধারণ করুন।
  • কোনও গণনার যে উপ-অংশগুলি পৃথক পৃথক করুন এবং সেগুলি থ্রেড বা ডিভাইসের মধ্যে বিভক্ত করুন।
  • সাধারণ subexpressions অপসারণ করে পাটিগণিত অপারেশনগুলিকে সহজ করুন।

সেখানে একটি সম্পূর্ণ অপ্টিমাইজেশান সিস্টেম, হয় Grappler , এটি এবং অন্যান্য speedups সঞ্চালন।

সংক্ষেপে, গ্রাফগুলি অত্যন্ত দরকারী এবং আপনার টেনসরফ্লো দ্রুত চালাতে দিন , সমান্তরালভাবে চলতে দিন এবং একাধিক ডিভাইসে দক্ষতার সাথে চালাতে দিন।

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

গ্রাফ ট্র্যাকিং

tf.function আপনি tf.function গ্রাফ তৈরি করবেন তা tf.function সরাসরি কল হিসাবে বা tf.function হিসাবে tf.function ব্যবহার করা।

import tensorflow as tf
import timeit
from datetime import datetime
# Define a Python function
def function_to_get_faster(x, y, b):
  x = tf.matmul(x, y)
  x = x + b
  return x

# Create a `Function` object that contains a graph
a_function_that_uses_a_graph = tf.function(function_to_get_faster)

# Make some tensors
x1 = tf.constant([[1.0, 2.0]])
y1 = tf.constant([[2.0], [3.0]])
b1 = tf.constant(4.0)

# It just works!
a_function_that_uses_a_graph(x1, y1, b1).numpy()
array([[12.]], dtype=float32)

tf.function আকারযুক্ত ফাংশনগুলি পাইথন কলযোগ্য যা তাদের পাইথন সমতুল্য হিসাবে একই কাজ করে। তাদের একটি নির্দিষ্ট বর্গ রয়েছে ( python.eager.def_function.Function ) তবে আপনার কাছে তারা কেবল অ- python.eager.def_function.Function সংস্করণ হিসাবে কাজ করে।

tf.function পুনরাবৃত্তভাবে যেকোন পাইথন ফাংশন এটি কল করে।

def inner_function(x, y, b):
  x = tf.matmul(x, y)
  x = x + b
  return x

# Use the decorator
@tf.function
def outer_function(x):
  y = tf.constant([[2.0], [3.0]])
  b = tf.constant(4.0)

  return inner_function(x, y, b)

# Note that the callable will create a graph that
# includes inner_function() as well as outer_function()
outer_function(tf.constant([[1.0, 2.0]])).numpy()
array([[12.]], dtype=float32)

আপনি যদি টেনসরফ্লো 1.x ব্যবহার করেছেন তবে আপনি লক্ষ্য করবেন যে কোনও সময় আপনার কোনও Placeholder বা tf.Sesssion সংজ্ঞায়িত করার প্রয়োজন ছিল না।

প্রবাহ নিয়ন্ত্রণ এবং পার্শ্ব প্রতিক্রিয়া

ফ্লো নিয়ন্ত্রণ এবং লুপগুলি ডিফল্টরূপে tf.autograph মাধ্যমে tf.autograph রূপান্তরিত হয়। অটোগ্রাফ পদ্ধতিগুলির সংমিশ্রণটি ব্যবহার করে, মান লুপ কনস্ট্রাক্টসগুলি আনারোলিং, এবং এএসটি ম্যানিপুলেশন সহ।

def my_function(x):
  if tf.reduce_sum(x) <= 1:
    return x * x
  else:
    return x-1

a_function = tf.function(my_function)

print("First branch, with graph:", a_function(tf.constant(1.0)).numpy())
print("Second branch, with graph:", a_function(tf.constant([5.0, 5.0])).numpy())
First branch, with graph: 1.0
Second branch, with graph: [4. 4.]

পাইথন কীভাবে টেনসরফ্লো অপ্সে রূপান্তরিত হয় তা দেখতে আপনি সরাসরি অটোগ্রাফ রূপান্তরকে কল করতে পারেন। এটি বেশিরভাগই অপঠনযোগ্য, তবে আপনি রূপান্তরটি দেখতে পাচ্ছেন।

# Don't read the output too carefully.
print(tf.autograph.to_code(my_function))
def tf__my_function(x):
    with ag__.FunctionScope('my_function', 'fscope', ag__.ConversionOptions(recursive=True, user_requested=True, optional_features=(), internal_convert_user_code=True)) as fscope:
        do_return = False
        retval_ = ag__.UndefinedReturnValue()

        def get_state():
            return (retval_, do_return)

        def set_state(vars_):
            nonlocal retval_, do_return
            (retval_, do_return) = vars_

        def if_body():
            nonlocal retval_, do_return
            try:
                do_return = True
                retval_ = (ag__.ld(x) * ag__.ld(x))
            except:
                do_return = False
                raise

        def else_body():
            nonlocal retval_, do_return
            try:
                do_return = True
                retval_ = (ag__.ld(x) - 1)
            except:
                do_return = False
                raise
        ag__.if_stmt((ag__.converted_call(ag__.ld(tf).reduce_sum, (ag__.ld(x),), None, fscope) <= 1), if_body, else_body, get_state, set_state, ('retval_', 'do_return'), 2)
        return fscope.ret(retval_, do_return)


অটোগ্রাফ স্বয়ংক্রিয়ভাবে if-then দফার, লুপস, break , return , continue এবং আরও অনেক কিছু রূপান্তর করে।

বেশিরভাগ সময়, অটোগ্রাফ বিশেষ বিবেচনা ছাড়াই কাজ করবে। তবে এখানে কিছু সাবধানতা রয়েছে এবং tf.function গাইড এখানে সম্পূর্ণ অটোগ্রাফ রেফারেন্স হিসাবে সহায়তা করতে পারে

গতি দেখছি

শুধু tf.function একটি টেনসর-ব্যবহারের ফাংশন মোড়ানো আপনার কোডটি স্বয়ংক্রিয়ভাবে গতিবেগে যায় না। একটি একক মেশিনে কয়েকবার কল করা ছোট ফাংশনগুলির জন্য, গ্রাফ বা গ্রাফের টুকরো কল করার ওভারহেড রানটাইমকে প্রাধান্য দিতে পারে। এছাড়াও, যদি জিপিইউ-ভারী কনভোলিউশনের স্ট্যাকের মতো বেশিরভাগ গণনা ইতিমধ্যে একটি ত্বরণকারীটিতে ঘটত তবে গ্রাফের গতিবেগ বড় হবে না।

জটিল গণনার জন্য, গ্রাফগুলি একটি উল্লেখযোগ্য গতিবেগ সরবরাহ করতে পারে। এটি কারণ গ্রাফগুলি পাইথন থেকে ডিভাইস যোগাযোগ হ্রাস করে এবং কিছু স্পিডআপ করে।

এই কোডটি কয়েকটি ছোট ঘন স্তরগুলিতে কয়েকবার রান করে।

# Create an oveerride model to classify pictures
class SequentialModel(tf.keras.Model):
  def __init__(self, **kwargs):
    super(SequentialModel, self).__init__(**kwargs)
    self.flatten = tf.keras.layers.Flatten(input_shape=(28, 28))
    self.dense_1 = tf.keras.layers.Dense(128, activation="relu")
    self.dropout = tf.keras.layers.Dropout(0.2)
    self.dense_2 = tf.keras.layers.Dense(10)

  def call(self, x):
    x = self.flatten(x)
    x = self.dense_1(x)
    x = self.dropout(x)
    x = self.dense_2(x)
    return x

input_data = tf.random.uniform([60, 28, 28])

eager_model = SequentialModel()
graph_model = tf.function(eager_model)

print("Eager time:", timeit.timeit(lambda: eager_model(input_data), number=10000))
print("Graph time:", timeit.timeit(lambda: graph_model(input_data), number=10000))
Eager time: 5.330957799000316
Graph time: 3.0375442899999143

পলিমারফিক ফাংশন

আপনি যখন কোনও ফাংশনটি সন্ধান করেন, আপনি একটি Function অবজেক্ট তৈরি করেন যা বহুবর্ষীয় । পলিমারফিক ফাংশন হল পাইথন কলযোগ্য যা একটি API এর পিছনে বেশ কয়েকটি কংক্রিট ফাংশন গ্রাফকে আবদ্ধ করে।

আপনি এই ব্যবহার করতে পারেন Function এর সব বিভিন্ন ধরণের উপর dtypes এবং আকার। প্রতিবার আপনি যখন নতুন আর্গুমেন্ট স্বাক্ষর সহ এটির অনুরোধ করবেন তখন মূল ফাংশনটি নতুন যুক্তি দিয়ে পুনরায় সন্ধান করবে। Function তারপর সঞ্চয় করে tf.Graph একটি যে ট্রেস সংশ্লিষ্ট concrete_function । যদি ফাংশনটি ইতিমধ্যে সেই ধরণের আর্গুমেন্টের সাথে সন্ধান করা থাকে তবে আপনি কেবল আপনার প্রাক-ট্রেস করা গ্রাফটি পাবেন।

ধারণা অনুসারে, তারপর:

  • একটি tf.Graph হ'ল কাঁচা, বহনযোগ্য ডেটা স্ট্রাকচার যা একটি গণনা বর্ণনা করে
  • একটি Function হ'ল একটি ক্যাচিং, ট্রেসিং, কনক্রিট Function প্রেরণকারী
  • একটি ConcreteFunction হ'ল গ্রাফের চারপাশে একটি আগ্রহী-সামঞ্জস্যপূর্ণ মোড়ক যা আপনাকে পাইথন থেকে গ্রাফটি কার্যকর করতে দেয়

পলিমারফিক ফাংশন পরিদর্শন করা হচ্ছে

আপনি a_function পরিদর্শন করতে পারেন, এটি পাইথন ফাংশন my_function tf.function কল করার ফলাফল। এই উদাহরণস্বরূপ, তিন ধরণের আর্গুমেন্টের সাথে a_function কল করার a_function তিনটি পৃথক কংক্রিটের ফাংশন হয়।

print(a_function)

print("Calling a `Function`:")
print("Int:", a_function(tf.constant(2)))
print("Float:", a_function(tf.constant(2.0)))
print("Rank-1 tensor of floats", a_function(tf.constant([2.0, 2.0, 2.0])))
<tensorflow.python.eager.def_function.Function object at 0x7f7d342602b0>
Calling a `Function`:
Int: tf.Tensor(1, shape=(), dtype=int32)
Float: tf.Tensor(1.0, shape=(), dtype=float32)
Rank-1 tensor of floats tf.Tensor([1. 1. 1.], shape=(3,), dtype=float32)

# Get the concrete function that works on floats
print("Inspecting concrete functions")
print("Concrete function for float:")
print(a_function.get_concrete_function(tf.TensorSpec(shape=[], dtype=tf.float32)))
print("Concrete function for tensor of floats:")
print(a_function.get_concrete_function(tf.constant([2.0, 2.0, 2.0])))
Inspecting concrete functions
Concrete function for float:
ConcreteFunction my_function(x)
  Args:
    x: float32 Tensor, shape=()
  Returns:
    float32 Tensor, shape=()
Concrete function for tensor of floats:
ConcreteFunction my_function(x)
  Args:
    x: float32 Tensor, shape=(3,)
  Returns:
    float32 Tensor, shape=(3,)

# Concrete functions are callable
# Note: You won't normally do this, but instead just call the containing `Function`
cf = a_function.get_concrete_function(tf.constant(2))
print("Directly calling a concrete function:", cf(tf.constant(2)))
Directly calling a concrete function: tf.Tensor(1, shape=(), dtype=int32)

এই উদাহরণে, আপনি স্ট্যাকের মধ্যে বেশ দূরে দেখছেন। আপনি নির্দিষ্টভাবে ট্রেসিং পরিচালনা না করা হলে আপনি এখানে প্রদর্শিত হিসাবে সাধারণত কংক্রিট ফাংশন কল করতে হবে না।

আগ্রহী মৃত্যুদন্ড কার্যকর করা

আপনি নিজেকে দীর্ঘ স্ট্যাক tf.Graph দিকে তাকিয়ে দেখতে পারেন, বিশেষত যেগুলি tf.Graph বা with tf.Graph().as_default() উল্লেখ করে tf.Graph with tf.Graph().as_default() । এর অর্থ আপনি সম্ভবত কোনও গ্রাফ প্রসঙ্গে চলেছেন। model.fit() মূল ফাংশনগুলি গ্রাফ প্রসঙ্গে যেমন model.fit()

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

গ্রাফ ডিবাগিংকে জটিল করে তোলে এমন পরিস্থিতিতে আপনি ডিবাগ করার জন্য আগ্রহী এক্সিকিউশন ব্যবহার করে ফিরে যেতে পারেন।

আপনি আগ্রহীভাবে চলছেন তা নিশ্চিত করার জন্য এখানে উপায় রয়েছে:

  • কলযোগ্য হিসাবে সরাসরি মডেল এবং স্তরগুলিকে কল করুন

  • কেরাস সংকলন / ফিট ব্যবহার করার সময়, সংকলনের সময় model.compile(run_eagerly=True) ব্যবহার model.compile(run_eagerly=True)

  • tf.config.run_functions_eagerly(True) মাধ্যমে গ্লোবাল এক্সিকিউশন মোড সেট করুন

run_eagerly=True ব্যবহার run_eagerly=True

# Define an identity layer with an eager side effect
class EagerLayer(tf.keras.layers.Layer):
  def __init__(self, **kwargs):
    super(EagerLayer, self).__init__(**kwargs)
    # Do some kind of initialization here

  def call(self, inputs):
    print("\nCurrently running eagerly", str(datetime.now()))
    return inputs
# Create an override model to classify pictures, adding the custom layer
class SequentialModel(tf.keras.Model):
  def __init__(self):
    super(SequentialModel, self).__init__()
    self.flatten = tf.keras.layers.Flatten(input_shape=(28, 28))
    self.dense_1 = tf.keras.layers.Dense(128, activation="relu")
    self.dropout = tf.keras.layers.Dropout(0.2)
    self.dense_2 = tf.keras.layers.Dense(10)
    self.eager = EagerLayer()

  def call(self, x):
    x = self.flatten(x)
    x = self.dense_1(x)
    x = self.dropout(x)
    x = self.dense_2(x)
    return self.eager(x)

# Create an instance of this model
model = SequentialModel()

# Generate some nonsense pictures and labels
input_data = tf.random.uniform([60, 28, 28])
labels = tf.random.uniform([60])

loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

প্রথমে উত্সাহ ছাড়াই মডেলটি সংকলন করুন। নোট করুন যে মডেলটি সনাক্ত করা হয়নি; এর নাম সত্ত্বেও, compile কেবল ক্ষতির ফাংশন, অনুকূলকরণ এবং অন্যান্য প্রশিক্ষণের প্যারামিটার সেট করে।

model.compile(run_eagerly=False, loss=loss_fn)

এখন, fit কল করুন এবং দেখুন যে ফাংশনটি (দুইবার) সন্ধান করা হয়েছে এবং তারপরে উত্সাহী প্রভাব আর কখনও চলবে না।

model.fit(input_data, labels, epochs=3)
Epoch 1/3

Currently running eagerly 2020-11-04 02:22:28.114630

Currently running eagerly 2020-11-04 02:22:28.233822
2/2 [==============================] - 0s 2ms/step - loss: 0.9890
Epoch 2/3
2/2 [==============================] - 0s 1ms/step - loss: 0.0017
Epoch 3/3
2/2 [==============================] - 0s 1ms/step - loss: 5.4478e-04

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

আপনি যদি উত্সাহে এমনকি একটি একক যুগেও চালনা করেন তবে, আপনি দু'বার উত্সাহী পার্শ্ব প্রতিক্রিয়া দেখতে পাবেন।

print("Running eagerly")
# When compiling the model, set it to run eagerly
model.compile(run_eagerly=True, loss=loss_fn)

model.fit(input_data, labels, epochs=1)
Running eagerly

Currently running eagerly 2020-11-04 02:22:28.449835
1/2 [==============>...............] - ETA: 0s - loss: 7.8712e-04
Currently running eagerly 2020-11-04 02:22:28.472645
2/2 [==============================] - 0s 6ms/step - loss: 4.1988e-04

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

run_functions_eagerly ব্যবহার করা

আপনি বিশ্বস্তভাবে উত্সাহিতভাবে চালানোর জন্য সবকিছু সেট করতে পারেন। এটি এমন একটি স্যুইচ যা পলিমারফিক ফাংশনের ট্রেসড ফাংশনগুলিকে বাইপাস করে এবং মূল ফাংশনটিকে সরাসরি কল করে। আপনি এটি ডিবাগিংয়ের জন্য ব্যবহার করতে পারেন।

# Now, globally set everything to run eagerly
tf.config.run_functions_eagerly(True)
print("Run all functions eagerly.")

# Create a polymorphic function
polymorphic_function = tf.function(model)

print("Tracing")
# This does, in fact, trace the function
print(polymorphic_function.get_concrete_function(input_data))

print("\nCalling twice eagerly")
# When you run the function again, you will see the side effect
# twice, as the function is running eagerly.
result = polymorphic_function(input_data)
result = polymorphic_function(input_data)
Run all functions eagerly.
Tracing

Currently running eagerly 2020-11-04 02:22:28.502694
ConcreteFunction function(self)
  Args:
    self: float32 Tensor, shape=(60, 28, 28)
  Returns:
    float32 Tensor, shape=(60, 10)

Calling twice eagerly

Currently running eagerly 2020-11-04 02:22:28.507036

Currently running eagerly 2020-11-04 02:22:28.508331

# Don't forget to set it back when you are done
tf.config.experimental_run_functions_eagerly(False)
WARNING:tensorflow:From <ipython-input-1-782fe9ce7b18>:2: experimental_run_functions_eagerly (from tensorflow.python.eager.def_function) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.config.run_functions_eagerly` instead of the experimental version.

ট্র্যাকিং এবং কর্মক্ষমতা

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

আপনার মডেলটি যত বড় হোক না কেন, আপনি ঘন ঘন ট্রেসিং এড়াতে চান। Tf.function গাইডের এই বিভাগটি কীভাবে ইনপুট স্পেসিফিকেশন সেট করতে হবে এবং retracing এড়াতে টেনসর আর্গুমেন্টগুলি কীভাবে ব্যবহার করবে তা আলোচনা করে। আপনি যদি দেখেন যে আপনি অস্বাভাবিকভাবে পারফরম্যান্স পাচ্ছেন, আপনি দুর্ঘটনাক্রমে পিছনে যাচ্ছেন কিনা তা যাচাই করে নেওয়া ভাল।

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

# Use @tf.function decorator
@tf.function
def a_function_with_python_side_effect(x):
  print("Tracing!")  # This eager
  return x * x + tf.constant(2)

# This is traced the first time
print(a_function_with_python_side_effect(tf.constant(2)))
# The second time through, you won't see the side effect
print(a_function_with_python_side_effect(tf.constant(3)))

# This retraces each time the Python argument changes,
# as a Python argument could be an epoch count or other
# hyperparameter
print(a_function_with_python_side_effect(2))
print(a_function_with_python_side_effect(3))
Tracing!
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(11, shape=(), dtype=int32)
Tracing!
tf.Tensor(6, shape=(), dtype=int32)
Tracing!
tf.Tensor(11, shape=(), dtype=int32)

পরবর্তী পদক্ষেপ

আপনি উভয় tf.function এপিআই রেফারেন্স পৃষ্ঠা এবং গাইড এ আরও গভীরতর আলোচনা পড়তে পারেন।