Tf.function সঙ্গে আরও ভাল পারফরম্যান্স

TensorFlow.org এ দেখুন গুগল কোলাবে চালান GitHub এ উৎস দেখুন নোটবুক ডাউনলোড করুন

TensorFlow 2 সালে উৎসুক সঞ্চালনের ডিফল্টরূপে চালু আছে। ইউজার ইন্টারফেসটি স্বজ্ঞাত এবং নমনীয় (একক অপারেশন চালানো অনেক সহজ এবং দ্রুত), কিন্তু এটি পারফরম্যান্স এবং স্থাপনার খরচে আসতে পারে।

আপনি ব্যবহার করতে পারেন tf.function গ্রাফ আপনার প্রোগ্রাম থেকে বের করা। এটি একটি ট্রান্সফরমেশন টুল যা আপনার পাইথন কোডের বাইরে পাইথন-স্বাধীন ডাটাফ্লো গ্রাফ তৈরি করে। এই আপনি performant এবং বহনীয় মডেল তৈরি করতে সাহায্য করবে, এবং এটি ব্যবহার করতে প্রয়োজন বোধ করা হয় SavedModel

এই সহায়িকার আপনি নজর কিভাবে সাহায্য করবে tf.function ফণা অধীন কাজ করে, তাই আপনি এটি কার্যকরভাবে ব্যবহার করতে পারেন।

প্রধান গ্রহণ এবং সুপারিশ হল:

  • উৎসুক মোডে ডিবাগ, তারপর সঙ্গে সাজাইয়া রাখা @tf.function
  • অবজেক্ট মিউটেশন বা তালিকা সংযোজনের মতো পাইথনের পার্শ্ব প্রতিক্রিয়াগুলির উপর নির্ভর করবেন না।
  • tf.function TensorFlow অপস সঙ্গে ভাল কাজ করে; NumPy এবং Python কল ধ্রুবক রূপান্তরিত হয়।

সেটআপ

import tensorflow as tf

আপনি যে ধরনের ত্রুটির সম্মুখীন হতে পারেন তা প্রদর্শন করতে একটি সহায়ক ফাংশন সংজ্ঞায়িত করুন:

import traceback
import contextlib

# Some helper code to demonstrate the kinds of errors you might encounter.
@contextlib.contextmanager
def assert_raises(error_class):
  try:
    yield
  except error_class as e:
    print('Caught expected exception \n  {}:'.format(error_class))
    traceback.print_exc(limit=2)
  except Exception as e:
    raise e
  else:
    raise Exception('Expected {} to be raised but no error was raised!'.format(
        error_class))

বুনিয়াদি

ব্যবহার

একটি Function আপনি (প্রয়োগের দ্বারা উদাহরণস্বরূপ সংজ্ঞায়িত @tf.function প্রসাধক) শুধু মূল TensorFlow অপারেশন মত হল: আপনি এটি সাগ্রহে নির্বাহ করতে পারেন; আপনি গ্রেডিয়েন্ট গণনা করতে পারেন; এবং তাই।

@tf.function  # The decorator converts `add` into a `Function`.
def add(a, b):
  return a + b

add(tf.ones([2, 2]), tf.ones([2, 2]))  #  [[2., 2.], [2., 2.]]
2021-08-19 01:26:31.359247: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-19 01:26:31.367277: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-19 01:26:31.368263: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-19 01:26:31.370408: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 AVX512F FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-08-19 01:26:31.371033: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-19 01:26:31.372158: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-19 01:26:31.373202: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-19 01:26:32.003755: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-19 01:26:32.004773: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-19 01:26:32.005698: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-19 01:26:32.006564: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1510] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 14648 MB memory:  -> device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0
2021-08-19 01:26:32.343820: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:185] None of the MLIR Optimization Passes are enabled (registered 2)
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[2., 2.],
       [2., 2.]], dtype=float32)>
v = tf.Variable(1.0)
with tf.GradientTape() as tape:
  result = add(v, 1.0)
tape.gradient(result, v)
<tf.Tensor: shape=(), dtype=float32, numpy=1.0>

আপনি ব্যবহার করতে পারেন Function গুলি ভিতরে অন্যান্য Function গুলি।

@tf.function
def dense_layer(x, w, b):
  return add(tf.matmul(x, w), b)

dense_layer(tf.ones([3, 2]), tf.ones([2, 2]), tf.ones([2]))
<tf.Tensor: shape=(3, 2), dtype=float32, numpy=
array([[3., 3.],
       [3., 3.],
       [3., 3.]], dtype=float32)>

Function গুলি বিশেষত অনেক ছোট অপস সঙ্গে গ্রাফ জন্য, উৎসুক কোড তুলনায় দ্রুততর হতে পারে। কিন্তু কয়েকটি ব্যয়বহুল অপস (যেমন কনভোলিউশন) সহ গ্রাফগুলির জন্য, আপনি খুব বেশি গতি দেখতে পাবেন না।

import timeit
conv_layer = tf.keras.layers.Conv2D(100, 3)

@tf.function
def conv_fn(image):
  return conv_layer(image)

image = tf.zeros([1, 200, 200, 100])
# Warm up
conv_layer(image); conv_fn(image)
print("Eager conv:", timeit.timeit(lambda: conv_layer(image), number=10))
print("Function conv:", timeit.timeit(lambda: conv_fn(image), number=10))
print("Note how there's not much difference in performance for convolutions")
2021-08-19 01:26:35.135723: I tensorflow/stream_executor/cuda/cuda_dnn.cc:369] Loaded cuDNN version 8100
Eager conv: 0.004266158999996605
Function conv: 0.004805293000003985
Note how there's not much difference in performance for convolutions
2021-08-19 01:26:40.338397: I tensorflow/core/platform/default/subprocess.cc:304] Start cannot spawn child process: No such file or directory

ট্রেসিং

এই বিভাগে জানা যায় যে Function ফণা অধীন কাজ করে, বাস্তবায়ন বিবরণ যা ভবিষ্যতে পরিবর্তিত হতে পারে সহ। তবে, একবার আপনি বুঝতে কেন এবং কখন ট্রেসিং ঘটে, এটা অনেক ব্যবহার করা আরো সহজ tf.function কার্যকরভাবে!

"ট্রেসিং" কি?

একটি Function একটি আপনার প্রোগ্রাম রান TensorFlow গ্রাফ । তবে tf.Graph সবকিছুর করে যে আপনি একটি উৎসুক TensorFlow প্রোগ্রামে লিখতে চাই প্রতিনিধিত্ব করতে পারবে না। উদাহরণ হিসেবে বলা যায়, পাইথন পলিমরফিজম সমর্থন করে, কিন্তু tf.Graph একটি নির্দিষ্ট ডাটা টাইপ এবং আকারের আছে তার ইনপুট প্রয়োজন। অথবা আপনি কমান্ড-লাইন আর্গুমেন্ট পড়া, একটি ত্রুটি উত্থাপন, অথবা আরো জটিল পাইথন বস্তুর সাথে কাজ করার মতো পার্শ্ব কাজ সম্পাদন করতে পারেন; এসব কেউই একটি চালানো যেতে পারে tf.Graph

Function দুটি পর্যায়ে আপনার কোড পৃথক এই ফাঁক সেতু:

1) প্রথম পর্যায়ের, "ট্রেসিং" বলা সালে Function একটি নতুন সৃষ্টি tf.Graph । পাইথন কোড স্বাভাবিকভাবে চালায়, কিন্তু সব TensorFlow অপারেশন (দুই Tensors যোগ করা) বিলম্বিত হয়: তারা দ্বারা ধরা রয়েছে tf.Graph এবং চালানো।

2) দ্বিতীয় পর্যায়ের, একটি tf.Graph যা সবকিছু যে প্রথম পর্যায়ে ডেফার্ড ছিল ধারণ করে চালানো হয়। এই পর্যায়টি ট্রেসিং পর্যায়ের তুলনায় অনেক দ্রুত।

তার ইনপুট উপর নির্ভর করে, Function সবসময় প্রথম পর্যায়ের যখন এটা বলা হয় চলবে না। দেখুন "ট্রেসিং নিয়ম" নীচের এটি কিভাবে যে সংকল্প করে তোলে একটি ভাল ধারনা পেতে। প্রথম পর্যায়টি এড়িয়ে যাওয়া এবং কেবল দ্বিতীয় পর্যায়টি সম্পাদন করা আপনাকে টেন্সরফ্লোর উচ্চ কার্যকারিতা দেয়।

যখন Function ট্রেস করার সিদ্ধান্ত নেন না, ট্রেসিং পর্যায় অবিলম্বে দ্বিতীয় পর্যায়ের দ্বারা, তাই কলিং অনুসরণ করা হয় Function উভয় তৈরি করে এবং রান tf.Graph । পরবর্তীতে আপনি কেমন শুধুমাত্র আপনার সাথে ট্রেসিং পর্যায় চালাতে পারেন দেখতে হবে get_concrete_function

আমরা যখন একটি মধ্যে বিভিন্ন ধরনের অফ আর্গুমেন্ট পাস Function , উভয় পর্যায়ে চালানো হয়:

@tf.function
def double(a):
  print("Tracing with", a)
  return a + a

print(double(tf.constant(1)))
print()
print(double(tf.constant(1.1)))
print()
print(double(tf.constant("a")))
print()
Tracing with Tensor("a:0", shape=(), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)

Tracing with Tensor("a:0", shape=(), dtype=float32)
tf.Tensor(2.2, shape=(), dtype=float32)

Tracing with Tensor("a:0", shape=(), dtype=string)
tf.Tensor(b'aa', shape=(), dtype=string)

মনে রাখবেন যদি আপনি বারবার কল Function একই যুক্তি ধরনের সঙ্গে, TensorFlow ট্রেসিং পর্যায় এড়িয়ে যান এবং পূর্বে আঁকা গ্রাফ পুনরায় ব্যবহার করতে হবে, যেমন উত্পন্ন গ্রাফ অভিন্ন হতে হবে।

# This doesn't print 'Tracing with ...'
print(double(tf.constant("b")))
tf.Tensor(b'bb', shape=(), dtype=string)

আপনি ব্যবহার করতে পারেন pretty_printed_concrete_signatures() প্রাপ্তিসাধ্য ট্রেস সব দেখতে:

print(double.pretty_printed_concrete_signatures())
double(a)
  Args:
    a: int32 Tensor, shape=()
  Returns:
    int32 Tensor, shape=()

double(a)
  Args:
    a: float32 Tensor, shape=()
  Returns:
    float32 Tensor, shape=()

double(a)
  Args:
    a: string Tensor, shape=()
  Returns:
    string Tensor, shape=()

এ পর্যন্ত, আপনি দেখা করেছি যে tf.function একটি ক্যাশে, TensorFlow এর গ্রাফ যুক্তিবিজ্ঞান ট্রেসিং উপর গতিশীল প্রেরণ স্তর সৃষ্টি করে। পরিভাষা সম্পর্কে আরো সুনির্দিষ্ট হতে:

  • একজন tf.Graph কাঁচা, ভাষা অ্যাগনোস্টিক, পোর্টেবল একটি TensorFlow গুনতি উপস্থাপনা।
  • একজন ConcreteFunction একটি গোপন tf.Graph
  • একটি Function একটি ক্যাশে পরিচালনা ConcreteFunction s এবং আপনার ইনপুট জন্য সঠিক পছন্দ।
  • tf.function একটি পাইথন ফাংশন গোপন, একটি ফিরতি Function অবজেক্ট।
  • ট্রেস একটি সৃষ্টি tf.Graph এবং এটা গোপন ConcreteFunction , এছাড়াও একটি ট্রেস হিসাবে পরিচিত।

ট্রেসিং এর নিয়ম

একটি Function নির্ধারণ করে একটি আঁকা পুনরায় ব্যবহার করা হবে কিনা তা ConcreteFunction একটি ইনপুট এর args এবং kwargs থেকে একটি ক্যাশে কী কম্পিউটিং দ্বারা। একটি ক্যাশে কী কী যে শনাক্ত একটি ConcreteFunction ইনপুট args এবং kwargs উপর ভিত্তি করে Function কল, নিম্নলিখিত নিয়মগুলি (পরিবর্তন পারে) অনুযায়ী:

  • একটি জন্য উত্পন্ন কী tf.Tensor তার আকৃতি এবং dtype হয়।
  • একটি জন্য উত্পন্ন কী tf.Variable একটি অনন্য পরিবর্তনশীল আইডি হল।
  • একটি পাইথন আদিম (যেমন জন্য উত্পন্ন কী int , float , str ) তার মান।
  • জন্য নেস্টেড উত্পন্ন কী dict এস, list S, tuple এস, namedtuple s, এবং attr গুলি পাতার কি-সংকলন (দেখতে একরকমের চ্যাপ্টা tuple হয় nest.flatten )। (এই চ্যাপ্টা করার ফলে, ট্রেসিংয়ের সময় ব্যবহৃত একটি ভিন্ন নেস্টিং কাঠামোর সাথে একটি কংক্রিট ফাংশনকে কল করার ফলে একটি টাইপএরর হবে)
  • অন্যান্য সমস্ত পাইথন প্রকারের জন্য কী বস্তুর জন্য অনন্য। এইভাবে একটি ফাংশন বা পদ্ধতি প্রতিটি উদাহরণের জন্য স্বাধীনভাবে চিহ্নিত করা হয় যার সাথে এটি বলা হয়।

রিট্রেসিং নিয়ন্ত্রণ করা

ফিরে দেখা, যা যখন আপনার Function , একাধিক ট্রেস সৃষ্টি করতে সাহায্য করে নিশ্চিত করে যে TensorFlow ইনপুট প্রতিটি সেট জন্য সঠিক গ্রাফ তৈরি করে। যাইহোক, ট্রেসিং একটি ব্যয়বহুল অপারেশন! আপনার যদি Function প্রতি কলের জন্য একটি নতুন গ্রাফ retraces, আপনাকে খুঁজে পাবেন যে আপনার কোডকে কার্যকর তুলনায় ধীর গতিতে আপনি ব্যবহার না করে থাকলে tf.function

ট্রেসিং আচরণ নিয়ন্ত্রণ করতে, আপনি নিম্নলিখিত কৌশলগুলি ব্যবহার করতে পারেন:

  • নির্দিষ্ট করুন input_signature মধ্যে tf.function সীমা হদিশ করতে।
@tf.function(input_signature=(tf.TensorSpec(shape=[None], dtype=tf.int32),))
def next_collatz(x):
  print("Tracing with", x)
  return tf.where(x % 2 == 0, x // 2, 3 * x + 1)

print(next_collatz(tf.constant([1, 2])))
# You specified a 1-D tensor in the input signature, so this should fail.
with assert_raises(ValueError):
  next_collatz(tf.constant([[1, 2], [3, 4]]))

# You specified an int32 dtype in the input signature, so this should fail.
with assert_raises(ValueError):
  next_collatz(tf.constant([1.0, 2.0]))
Tracing with Tensor("x:0", shape=(None,), dtype=int32)
tf.Tensor([4 1], shape=(2,), dtype=int32)
Caught expected exception 
  <class 'ValueError'>:
Caught expected exception 
  <class 'ValueError'>:
Traceback (most recent call last):
  File "/tmp/ipykernel_25646/3551158538.py", line 8, in assert_raises
    yield
  File "/tmp/ipykernel_25646/1851403433.py", line 9, in <module>
    next_collatz(tf.constant([[1, 2], [3, 4]]))
ValueError: Python inputs incompatible with input_signature:
  inputs: (
    tf.Tensor(
[[1 2]
 [3 4]], shape=(2, 2), dtype=int32))
  input_signature: (
    TensorSpec(shape=(None,), dtype=tf.int32, name=None))
Traceback (most recent call last):
  File "/tmp/ipykernel_25646/3551158538.py", line 8, in assert_raises
    yield
  File "/tmp/ipykernel_25646/1851403433.py", line 13, in <module>
    next_collatz(tf.constant([1.0, 2.0]))
ValueError: Python inputs incompatible with input_signature:
  inputs: (
    tf.Tensor([1. 2.], shape=(2,), dtype=float32))
  input_signature: (
    TensorSpec(shape=(None,), dtype=tf.int32, name=None))
  • আপনাকে একটি [কোনটি] মাত্রা উল্লেখ করুন tf.TensorSpec পুনঃব্যবহারের ট্রেস মধ্যে নমনীয়তার জন্য অনুমতি দেয়।

    যেহেতু TensorFlow একটি ব্যবহার তাদের আকৃতি উপর ভিত্তি করে tensors সাথে মিলে যায়, None পরিবর্তে ওয়াইল্ডকার্ড হিসেবে মাত্রা অনুমতি দেবে Function অসম আকারের ইনপুট জন্য পুনঃব্যবহারের ট্রেস করতে গুলি। যদি আপনি প্রতিটি ব্যাচ (দেখুন জন্য বিভিন্ন দৈর্ঘ্য ক্রমের সাথে, বা বিভিন্ন আকারের চিত্র আছে অসম আকারের ইনপুট ঘটতে পারে ট্রান্সফরমার এবং ডীপ ড্রিম উদাহরণস্বরূপ টিউটোরিয়াল)।

@tf.function(input_signature=(tf.TensorSpec(shape=[None], dtype=tf.int32),))
def g(x):
  print('Tracing with', x)
  return x

# No retrace!
print(g(tf.constant([1, 2, 3])))
print(g(tf.constant([1, 2, 3, 4, 5])))
Tracing with Tensor("x:0", shape=(None,), dtype=int32)
tf.Tensor([1 2 3], shape=(3,), dtype=int32)
tf.Tensor([1 2 3 4 5], shape=(5,), dtype=int32)
  • কাস্ট পাইথন আর্গুমেন্টগুলি টেনসারদের কাছে পুনরুদ্ধার কমাতে।

    উদাহরণস্বরূপ, - প্রায়ই, পাইথন আর্গুমেন্ট নিয়ন্ত্রণ hyperparameters এবং গ্রাফ বাক্য ব্যবহার করা হয় num_layers=10 বা training=True বা nonlinearity='relu' । সুতরাং, যদি পাইথন আর্গুমেন্ট পরিবর্তন হয়, তাহলে এটি বোঝায় যে আপনাকে গ্রাফটি পুনরুদ্ধার করতে হবে।

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

def train_one_step():
  pass

@tf.function
def train(num_steps):
  print("Tracing with num_steps = ", num_steps)
  tf.print("Executing with num_steps = ", num_steps)
  for _ in tf.range(num_steps):
    train_one_step()

print("Retracing occurs for different Python arguments.")
train(num_steps=10)
train(num_steps=20)

print()
print("Traces are reused for Tensor arguments.")
train(num_steps=tf.constant(10))
train(num_steps=tf.constant(20))
Retracing occurs for different Python arguments.
Tracing with num_steps =  10
Executing with num_steps =  10
Tracing with num_steps =  20
Executing with num_steps =  20

Traces are reused for Tensor arguments.
Tracing with num_steps =  Tensor("num_steps:0", shape=(), dtype=int32)
Executing with num_steps =  10
Executing with num_steps =  20

আপনি বল ফিরে দেখা করার প্রয়োজন হলে, একটি নতুন তৈরি Function । পৃথক Function বস্তু ভাগ ট্রেস না নিশ্চিত করা হয়।

def f():
  print('Tracing!')
  tf.print('Executing')

tf.function(f)()
tf.function(f)()
Tracing!
Executing
Tracing!
Executing

কংক্রিট ফাংশন অর্জন

প্রতিবার একটি ফাংশন সনাক্ত করা হয়, একটি নতুন কংক্রিট ফাংশন তৈরি করা হয়। আপনি সরাসরি একটি কংক্রিট ফাংশন প্রাপ্ত করতে পারেন ব্যবহার করে get_concrete_function

print("Obtaining concrete trace")
double_strings = double.get_concrete_function(tf.constant("a"))
print("Executing traced function")
print(double_strings(tf.constant("a")))
print(double_strings(a=tf.constant("b")))
Obtaining concrete trace
Executing traced function
tf.Tensor(b'aa', shape=(), dtype=string)
tf.Tensor(b'bb', shape=(), dtype=string)
# You can also call get_concrete_function on an InputSpec
double_strings_from_inputspec = double.get_concrete_function(tf.TensorSpec(shape=[], dtype=tf.string))
print(double_strings_from_inputspec(tf.constant("c")))
Tracing with Tensor("a:0", shape=(), dtype=string)
tf.Tensor(b'cc', shape=(), dtype=string)

একটি মুদ্রণ ConcreteFunction প্রদর্শন (ধরনের সঙ্গে) তার ইনপুট আর্গুমেন্ট একটি সারসংক্ষেপ এবং তার আউটপুট প্রকার।

print(double_strings)
ConcreteFunction double(a)
  Args:
    a: string Tensor, shape=()
  Returns:
    string Tensor, shape=()

আপনি সরাসরি একটি কংক্রিট ফাংশনের স্বাক্ষর পুনরুদ্ধার করতে পারেন।

print(double_strings.structured_input_signature)
print(double_strings.structured_outputs)
((TensorSpec(shape=(), dtype=tf.string, name='a'),), {})
Tensor("Identity:0", shape=(), dtype=string)

বেমানান ধরনের সঙ্গে একটি কংক্রিট ট্রেস ব্যবহার একটি ত্রুটি নিক্ষেপ করা হবে

with assert_raises(tf.errors.InvalidArgumentError):
  double_strings(tf.constant(1))
Caught expected exception 
  <class 'tensorflow.python.framework.errors_impl.InvalidArgumentError'>:
Traceback (most recent call last):
  File "/tmp/ipykernel_25646/3551158538.py", line 8, in assert_raises
    yield
  File "/tmp/ipykernel_25646/3196284684.py", line 2, in <module>
    double_strings(tf.constant(1))
tensorflow.python.framework.errors_impl.InvalidArgumentError: cannot compute __inference_double_162 as input #0(zero-based) was expected to be a string tensor but is a int32 tensor [Op:__inference_double_162]

আপনি লক্ষ্য করতে পারেন যে পাইথন আর্গুমেন্টগুলিকে কংক্রিট ফাংশনের ইনপুট স্বাক্ষরে বিশেষ চিকিৎসা দেওয়া হয়। TensorFlow 2.3 এর আগে, পাইথন আর্গুমেন্টগুলি কেবল কংক্রিট ফাংশনের স্বাক্ষর থেকে সরানো হয়েছিল। TensorFlow 2.3 দিয়ে শুরু করে, পাইথন আর্গুমেন্টগুলি স্বাক্ষরে থাকে, কিন্তু ট্রেসিংয়ের সময় মান সেট করতে বাধা দেয়।

@tf.function
def pow(a, b):
  return a ** b

square = pow.get_concrete_function(a=tf.TensorSpec(None, tf.float32), b=2)
print(square)
ConcreteFunction pow(a, b=2)
  Args:
    a: float32 Tensor, shape=<unknown>
  Returns:
    float32 Tensor, shape=<unknown>
assert square(tf.constant(10.0)) == 100

with assert_raises(TypeError):
  square(tf.constant(10.0), b=3)
Caught expected exception 
  <class 'TypeError'>:
Traceback (most recent call last):
  File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/function.py", line 1721, in _call_impl
    cancellation_manager)
  File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/function.py", line 1766, in _call_with_flat_signature
    self._flat_signature_summary(), ", ".join(sorted(kwargs))))
TypeError: pow(a) got unexpected keyword arguments: b.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/tmp/ipykernel_25646/3551158538.py", line 8, in assert_raises
    yield
  File "/tmp/ipykernel_25646/2310937119.py", line 4, in <module>
    square(tf.constant(10.0), b=3)
TypeError: ConcreteFunction pow(a, b) was constructed with int value 2 in b, but was called with int value 3

গ্রাফ পাওয়া

প্রতিটি কংক্রিট ফাংশন একটি কাছাকাছি একটি callable মোড়কের হয় tf.Graph । যদিও প্রকৃত পুনরুদ্ধারের tf.Graph বস্তুর কিছু আপনি সাধারণত এটি করতে হবে না হয় তবে আপনি এটিকে সহজে কোনো কংক্রিট ফাংশন থেকে পেতে পারেন।

graph = double_strings.graph
for node in graph.as_graph_def().node:
  print(f'{node.input} -> {node.name}')
[] -> a
['a', 'a'] -> add
['add'] -> Identity

ডিবাগিং

সাধারণভাবে, ডিবাগ কোড ভিতরে চেয়ে উৎসুক মোডে সহজ tf.function । আপনি নিশ্চিত করতে হবে যে আপনার কোড সহ শোভাকর সামনে ত্রুটি মুক্ত উৎসুক মোডে executes tf.function । ডিবাগিং প্রক্রিয়ায় সহায়তা করার জন্য, আপনি কল করতে পারেন tf.config.run_functions_eagerly(True) বিশ্বব্যাপী অক্ষম এবং পুনরায় সক্ষম tf.function

যখন বিষয় যে শুধুমাত্র মধ্যে প্রদর্শিত নিচে ট্র্যাকিং tf.function , এখানে কিছু টিপস দেওয়া হল:

  • প্লেইন পুরানো পাইথন print কল শুধুমাত্র ট্রেসিং সময় চালানো, আপনার ফাংশন (পুনরায়) আঁকা পায় যখন আপনি খুঁজিয়া বাহির সাহায্য।
  • tf.print কল প্রত্যেক সময় চালানো হবে, এবং আপনি সম্পাদনের সময় অন্তর্বর্তী মান খুঁজিয়া বাহির সাহায্য করতে পারেন।
  • tf.debugging.enable_check_numerics খুঁজিয়া বাহির যেখানে Nans এবং INF নির্মিত একটি সহজ উপায়।
  • pdb ( পাইথন ডিবাগার ) সাহায্য করতে পারেন তা বুঝতে ট্রেসিং সময় ঘটছে। (সতর্কীকরণ: pdb অটোগ্রাফ-রুপান্তরিত উৎস কোডে আপনি ড্রপ হবে।)

অটোগ্রাফ রূপান্তর

অটোগ্রাফ একটি লাইব্রেরি ডিফল্টভাবে চালু আছে যে হয় tf.function , এবং গ্রাফ সামঞ্জস্যপূর্ণ TensorFlow অপস মধ্যে পাইথন উৎসুক কোডের একটি উপসেট রূপান্তরিত করে। এই মত নিয়ন্ত্রণ প্রবাহ অন্তর্ভুক্ত if , for , while

মত TensorFlow অপস tf.cond এবং tf.while_loop কাজ চালিয়ে, কিন্তু নিয়ন্ত্রণ প্রবাহ প্রায়ই লিখতে এবং যখন পাইথন লেখা বুঝতে সহজ।

# A simple loop

@tf.function
def f(x):
  while tf.reduce_sum(x) > 1:
    tf.print(x)
    x = tf.tanh(x)
  return x

f(tf.random.uniform([5]))
[0.680332422 0.0791739225 0.0669257641 0.701964378 0.535618901]
[0.591735482 0.0790088922 0.0668260083 0.605613232 0.489664495]
[0.531142652 0.0788449 0.0667267069 0.541031778 0.453950107]
[0.486254066 0.078681916 0.0666278452 0.493768573 0.425140589]
[0.451238334 0.0785199404 0.0665294155 0.457202375 0.40125224]
[0.422916353 0.0783589631 0.0664314255 0.427801341 0.38101992]
[0.399384439 0.0781989694 0.0663338676 0.403482229 0.363592863]
[0.379422128 0.0780399516 0.0662367418 0.382924527 0.348374784]
[0.362205505 0.0778819 0.0661400482 0.365244567 0.3349334]
[0.347155213 0.0777248144 0.0660437644 0.349825174 0.322946697]
[0.333850235 0.0775686726 0.0659479052 0.336220473 0.312168896]
[0.321976125 0.0774134621 0.0658524558 0.324099 0.302408934]
[0.311292648 0.0772591755 0.0657574236 0.31320855 0.293515563]
[0.301612616 0.0771058127 0.0656628 0.30335319 0.28536731]
[0.292787671 0.0769533589 0.0655685887 0.294378221 0.27786532]
<tf.Tensor: shape=(5,), dtype=float32, numpy=
array([0.28469858, 0.07680181, 0.06547478, 0.28615952, 0.27092823],
      dtype=float32)>

যদি আপনি কৌতূহলী হন তবে আপনি কোড অটোগ্রাফ জেনারেট করতে পারেন।

print(tf.autograph.to_code(f.python_function))
def tf__f(x):
    with ag__.FunctionScope('f', '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 (x,)

        def set_state(vars_):
            nonlocal x
            (x,) = vars_

        def loop_body():
            nonlocal x
            ag__.converted_call(ag__.ld(tf).print, (ag__.ld(x),), None, fscope)
            x = ag__.converted_call(ag__.ld(tf).tanh, (ag__.ld(x),), None, fscope)

        def loop_test():
            return (ag__.converted_call(ag__.ld(tf).reduce_sum, (ag__.ld(x),), None, fscope) > 1)
        ag__.while_stmt(loop_test, loop_body, get_state, set_state, ('x',), {})
        try:
            do_return = True
            retval_ = ag__.ld(x)
        except:
            do_return = False
            raise
        return fscope.ret(retval_, do_return)

শর্তাবলী

অটোগ্রাফ কিছু রূপান্তর করবে if <condition> সমতুল্য মধ্যে বিবৃতি tf.cond কল। যদি এই প্রতিকল্পন তৈরি করা হয় <condition> একটি টেন্সর হয়। অন্যথায়, if বক্তব্য পাইথন শর্তসাপেক্ষ যেমন মৃত্যুদন্ড কার্যকর করা হয়।

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

tf.cond ট্রেস এবং পরিবর্তনশীল সঞ্চালনের সময়ে একটি শাখা নির্বাচন গ্রাফ থেকে শর্তসাপেক্ষ উভয় শাখা যোগ করা হয়েছে। ট্রেসিং এর অনিচ্ছাকৃত পার্শ্বপ্রতিক্রিয়া থাকতে পারে; খুঁজে বার করো অটোগ্রাফ ট্রেসিং প্রভাব আরও তথ্যের জন্য।

@tf.function
def fizzbuzz(n):
  for i in tf.range(1, n + 1):
    print('Tracing for loop')
    if i % 15 == 0:
      print('Tracing fizzbuzz branch')
      tf.print('fizzbuzz')
    elif i % 3 == 0:
      print('Tracing fizz branch')
      tf.print('fizz')
    elif i % 5 == 0:
      print('Tracing buzz branch')
      tf.print('buzz')
    else:
      print('Tracing default branch')
      tf.print(i)

fizzbuzz(tf.constant(5))
fizzbuzz(tf.constant(20))
Tracing for loop
Tracing fizzbuzz branch
Tracing fizz branch
Tracing buzz branch
Tracing default branch
1
2
fizz
4
buzz
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz
16
17
fizz
19
buzz

দেখুন রেফারেন্স ডকুমেন্টেশন অতিরিক্ত সীমাবদ্ধতা জন্য বিবৃতি যদি অটোগ্রাফ-রূপান্তরিত।

লুপ

অটোগ্রাফ কিছু রূপান্তর করবে for এবং while সমতুল্য TensorFlow মধ্যে বিবৃতি অপস লুপিং মত tf.while_loop । তাহলে রূপান্তর করা, for বা while লুপ একটি পাইথন লুপ হিসাবে মৃত্যুদন্ড কার্যকর করা হয়।

এই প্রতিস্থাপন নিম্নলিখিত পরিস্থিতিতে তৈরি করা হয়:

  • for x in y : যদি y একটি টেন্সর হয়, রূপান্তর করতে tf.while_loop । বিশেষ ক্ষেত্রে যেখানে সালে y একটি হল tf.data.Dataset , সংমিশ্রণ tf.data.Dataset অপস তৈরি হয়।
  • while <condition> : যদি <condition> একটি টেন্সর হয়, রূপান্তর করতে tf.while_loop

হদিশ সময় একটি পাইথন লুপ, executes অতিরিক্ত অপস যোগ tf.Graph লুপ প্রতি পুনরাবৃত্তির।

একটি টেনসারফ্লো লুপ লুপের দেহটি সনাক্ত করে এবং কার্যকরী সময়ে কতগুলি পুনরাবৃত্তি চালাতে হবে তা গতিশীলভাবে নির্বাচন করে। লুপ শরীরের শুধুমাত্র উত্পন্ন একবার মনে হচ্ছে, tf.Graph

দেখুন রেফারেন্স ডকুমেন্টেশন উপর অটোগ্রাফ-রূপান্তরিত অতিরিক্ত বিধিনিষেধ জন্য for এবং while বিবৃতি।

পাইথন ডেটার উপর লুপিং

একটি সাধারণ ফাঁদ একটি মধ্যে পাইথন / NumPy ডেটার উপর লুপ হয় tf.function । এই লুপ ট্রেসিং প্রক্রিয়ার সময় চালানো, এর আপনার মডেল একটি কপি যোগ হবে tf.Graph লুপ প্রতিটি পুনরাবৃত্তির জন্য।

আপনি সমগ্র প্রশিক্ষণ লুপ মোড়ানো চান tf.function , এই কাজ করতে সবচেয়ে নিরাপদ উপায় হিসেবে আপনার ডেটা মোড়ানো হয় tf.data.Dataset যে অটোগ্রাফ হবে পরিবর্তনশীল উদ্ঘাটিত করা প্রশিক্ষণ লুপ তাই।

def measure_graph_size(f, *args):
  g = f.get_concrete_function(*args).graph
  print("{}({}) contains {} nodes in its graph".format(
      f.__name__, ', '.join(map(str, args)), len(g.as_graph_def().node)))

@tf.function
def train(dataset):
  loss = tf.constant(0)
  for x, y in dataset:
    loss += tf.abs(y - x) # Some dummy computation.
  return loss

small_data = [(1, 1)] * 3
big_data = [(1, 1)] * 10
measure_graph_size(train, small_data)
measure_graph_size(train, big_data)

measure_graph_size(train, tf.data.Dataset.from_generator(
    lambda: small_data, (tf.int32, tf.int32)))
measure_graph_size(train, tf.data.Dataset.from_generator(
    lambda: big_data, (tf.int32, tf.int32)))
train([(1, 1), (1, 1), (1, 1)]) contains 11 nodes in its graph
train([(1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)]) contains 32 nodes in its graph
train(<FlatMapDataset shapes: (<unknown>, <unknown>), types: (tf.int32, tf.int32)>) contains 6 nodes in its graph
train(<FlatMapDataset shapes: (<unknown>, <unknown>), types: (tf.int32, tf.int32)>) contains 6 nodes in its graph

যখন একটি ডেটাসেটে পাইথন / NumPy তথ্য মোড়কে, খেয়াল রাখবেন tf.data.Dataset.from_generator বনাম tf.data.Dataset.from_tensors । সাবেক পাইথন ডাটা রাখা এবং মাধ্যমে এটি আনা হবে tf.py_function কর্মক্ষমতা প্রভাবিত করতে পারে যা, যেহেতু আধুনিক এক বড় হিসাবে ডেটার একটি অনুলিপি বান্ডেল হবে tf.constant() গ্রাফে নোড, মেমরি উপর প্রভাব ফেলতে সক্ষম হয়।

মাধ্যমে ফাইল থেকে ডেটা পড়া TFRecordDataset , CsvDataset , ইত্যাদি তথ্য গ্রাস, তারপর যেমন TensorFlow নিজেই, অ্যাসিঙ্ক্রোনাস লোড হচ্ছে এবং ডেটার পূর্বে আনা পরিচালনা করতে পারেন পাইথন জড়িত না করেও সবচেয়ে কার্যকর উপায়। আরো জানতে, দেখুন tf.data : TensorFlow বিল্ড ইনপুট পাইপলাইনগুলি গাইড।

একটি লুপে মান জমা

একটি সাধারণ প্যাটার্ন হল একটি লুপ থেকে মধ্যবর্তী মান সংগ্রহ করা। সাধারনত, এটি একটি পাইথন তালিকায় যুক্ত করে বা একটি পাইথন অভিধানে এন্ট্রি যোগ করে সম্পন্ন করা হয়। যাইহোক, যেহেতু এগুলি পাইথনের পার্শ্বপ্রতিক্রিয়া, তারা গতিশীলভাবে আনরোল্ড লুপে প্রত্যাশিতভাবে কাজ করবে না। ব্যবহারের tf.TensorArray একটি পরিবর্তনশীল unrolled লুপ থেকে ফলাফল স্তূপাকার।

batch_size = 2
seq_len = 3
feature_size = 4

def rnn_step(inp, state):
  return inp + state

@tf.function
def dynamic_rnn(rnn_step, input_data, initial_state):
  # [batch, time, features] -> [time, batch, features]
  input_data = tf.transpose(input_data, [1, 0, 2])
  max_seq_len = input_data.shape[0]

  states = tf.TensorArray(tf.float32, size=max_seq_len)
  state = initial_state
  for i in tf.range(max_seq_len):
    state = rnn_step(input_data[i], state)
    states = states.write(i, state)
  return tf.transpose(states.stack(), [1, 0, 2])

dynamic_rnn(rnn_step,
            tf.random.uniform([batch_size, seq_len, feature_size]),
            tf.zeros([batch_size, feature_size]))
<tf.Tensor: shape=(2, 3, 4), dtype=float32, numpy=
array([[[0.9311646 , 0.23201597, 0.27760983, 0.50749147],
        [1.9157217 , 0.73632634, 1.2418742 , 1.3936795 ],
        [2.2432408 , 0.80746305, 1.2652718 , 2.0350993 ]],

       [[0.6350479 , 0.57744336, 0.1134994 , 0.49145043],
        [1.4704436 , 1.2057934 , 0.6300938 , 1.1418717 ],
        [2.2552116 , 1.7597941 , 1.3745583 , 1.9007651 ]]], dtype=float32)>

সীমাবদ্ধতা

TensorFlow Function নকশা যে আপনি যখন একটি একটি পাইথন ফাংশন রূপান্তর সচেতন হওয়া উচিত দ্বারা কয়েক সীমাবদ্ধতা উপস্থিত রয়েছে Function

পাইথনের পার্শ্বপ্রতিক্রিয়া চালানো

পার্শ্ব প্রতিক্রিয়া, মুদ্রণ তালিকাতে সংযোজন এবং globals mutating মতো ভিতরে অপ্রত্যাশিতভাবে আচরণ করতে Function , কখনও কখনও দুইবার বা সব না নির্বাহ। তারা শুধুমাত্র প্রথমবার আপনি একটি কল ঘটতে Function ইনপুট একটি সেট। পরবর্তীতে আঁকা tf.Graph পাইথন কোড নির্বাহ ছাড়া reexecuted হয়।

থাম্বের সাধারণ নিয়ম হল আপনার যুক্তিতে পাইথনের পার্শ্ব প্রতিক্রিয়াগুলির উপর নির্ভর করা এড়ানো এবং কেবলমাত্র আপনার চিহ্নগুলি ডিবাগ করার জন্য সেগুলি ব্যবহার করুন। তা না হলে, মত TensorFlow API গুলি tf.data , tf.print , tf.summary , tf.Variable.assign এবং tf.TensorArray সবচেয়ে ভালো উপায় প্রতিটি কলের সঙ্গে TensorFlow রানটাইম দ্বারা নিষ্পন্ন করা হবে আপনার কোড নিশ্চিত করা।

@tf.function
def f(x):
  print("Traced with", x)
  tf.print("Executed with", x)

f(1)
f(1)
f(2)
Traced with 1
Executed with 1
Executed with 1
Traced with 2
Executed with 2

আপনি যদি একটি প্রতিটি আবাহন সময় পাইথন কোড এক্সিকিউট করতে চান তাহলে Function , tf.py_function একটি প্রস্থান ডিম পাড়া হয়। এর অপূর্ণতা tf.py_function এটা পোর্টেবল বা বিশেষ করে performant, SavedModel সঙ্গে সংরক্ষণ করা যাবে না, এবং বিতরণ করা (বহু-জিপিইউ, নমনীয়) স্থাপনার মধ্যে ভাল কাজ করে না করে। এছাড়াও, যেহেতু tf.py_function গ্রাফ মধ্যে ওয়্যার্ড করা হয়েছে, এটা সব ইনপুট / আউটপুট tensors করতে কাস্ট।

পাইথন গ্লোবাল এবং ফ্রি ভেরিয়েবল পরিবর্তন করা

পরিবর্তন করা হচ্ছে পাইথন বিশ্বব্যাপী এবং বিনামূল্যে ভেরিয়েবল একটি পাইথন পার্শ্ব প্রতিক্রিয়া হিসাবে সংখ্যা, তাই এটি শুধুমাত্র ট্রেসিং সময় ঘটবে।

external_list = []

@tf.function
def side_effect(x):
  print('Python side effect')
  external_list.append(x)

side_effect(1)
side_effect(1)
side_effect(1)
# The list append only happened once!
assert len(external_list) == 1
Python side effect

আপনি তালিকা, dicts, অন্যান্য যে বস্তু বাইরে বসবাস মত পাত্রে mutating এড়িয়ে চলা উচিত Function । পরিবর্তে, যুক্তি এবং TF বস্তু ব্যবহার করুন। উদাহরণস্বরূপ, অধ্যায় "একটি লুপ মান আহরণের" কিভাবে তালিকা মত অপারেশন প্রয়োগ করা যেতে পারে একটি উদাহরণ রয়েছে।

আপনি কিছু কিছু ক্ষেত্রে, ক্যাপচার এবং রাষ্ট্র নিপূণভাবে পারেন যদি এটি একটি হল tf.Variable । এভাবেই Keras মডেলের ওজন একই পুনরাবৃত্তি কল সহ আপডেট করা হয় ConcreteFunction

পাইথন ইটারারেটর এবং জেনারেটর ব্যবহার করে

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

@tf.function
def buggy_consume_next(iterator):
  tf.print("Value:", next(iterator))

iterator = iter([1, 2, 3])
buggy_consume_next(iterator)
# This reuses the first value from the iterator, rather than consuming the next value.
buggy_consume_next(iterator)
buggy_consume_next(iterator)
Value: 1
Value: 1
Value: 1

শুধু কিভাবে TensorFlow একটি বিশেষ করেছে tf.TensorArray তালিকা নির্মান জন্য, এটি একটি বিশেষ করেছে tf.data.Iterator পুনরাবৃত্তির নির্মান জন্য। বিভাগে দেখুন অটোগ্রাফ রূপান্তরের একটি ওভারভিউ জন্য। এছাড়াও, tf.data এপিআই সাহায্য করতে পারেন জেনারেটরের নিদর্শন বাস্তবায়ন:

@tf.function
def good_consume_next(iterator):
  # This is ok, iterator is a tf.data.Iterator
  tf.print("Value:", next(iterator))

ds = tf.data.Dataset.from_tensor_slices([1, 2, 3])
iterator = iter(ds)
good_consume_next(iterator)
good_consume_next(iterator)
good_consume_next(iterator)
Value: 1
Value: 2
Value: 3

মধ্যে tf.Variables মোছা Function কল

আরেকটি ত্রুটির সম্মুখীন হতে পারেন একটি আবর্জনা-সংগৃহীত পরিবর্তনশীল। ConcreteFunction শুধুমাত্র বজায় রাখা র WeakRefs তারা ঘনিষ্ঠ উপর ভেরিয়েবল, তাই যদি আপনি কোন ভেরিয়েবল একটি রেফারেন্স রাখা আবশ্যক।

external_var = tf.Variable(3)
@tf.function
def f(x):
  return x * external_var

traced_f = f.get_concrete_function(4)
print("Calling concrete function...")
print(traced_f(4))

# The original variable object gets garbage collected, since there are no more
# references to it.
external_var = tf.Variable(4)
print()
print("Calling concrete function after garbage collecting its closed Variable...")
with assert_raises(tf.errors.FailedPreconditionError):
  traced_f(4)
Calling concrete function...
tf.Tensor(12, shape=(), dtype=int32)

Calling concrete function after garbage collecting its closed Variable...
Caught expected exception 
  <class 'tensorflow.python.framework.errors_impl.FailedPreconditionError'>:
Traceback (most recent call last):
  File "/tmp/ipykernel_25646/3551158538.py", line 8, in assert_raises
    yield
  File "/tmp/ipykernel_25646/3862898592.py", line 16, in <module>
    traced_f(4)
tensorflow.python.framework.errors_impl.FailedPreconditionError: 2 root error(s) found.
  (0) Failed precondition:  Could not find variable _AnonymousVar3. This could mean that the variable has been deleted. In TF1, it can also mean the variable is uninitialized. Debug info: container=localhost, status=Not found: Resource localhost/_AnonymousVar3/N10tensorflow3VarE does not exist.
     [[node ReadVariableOp (defined at tmp/ipykernel_25646/3862898592.py:4) ]]
  (1) Failed precondition:  Could not find variable _AnonymousVar3. This could mean that the variable has been deleted. In TF1, it can also mean the variable is uninitialized. Debug info: container=localhost, status=Not found: Resource localhost/_AnonymousVar3/N10tensorflow3VarE does not exist.
     [[node ReadVariableOp (defined at tmp/ipykernel_25646/3862898592.py:4) ]]
     [[ReadVariableOp/_2]]
0 successful operations.
0 derived errors ignored. [Op:__inference_f_772]

Function call stack:
f -> f

জ্ঞাত সমস্যা

আপনার যদি Function সঠিকভাবে মূল্যায়ন করা হয় না, ত্রুটি এই জ্ঞাত সমস্যাগুলি যা ভবিষ্যতে সংশোধন করা করার পরিকল্পনা নেওয়া হয়েছে দ্বারা ব্যাখ্যা করা যেতে পারে।

পাইথন গ্লোবাল এবং ফ্রি ভেরিয়েবলের উপর নির্ভর করে

Function একটি নতুন সৃষ্টি ConcreteFunction যখন একটি পাইথন আর্গুমেন্টের একটি নতুন মান সঙ্গে বলা হয়। যাইহোক, এটা যে কি করে না পাইথন বন্ধ, globals, বা যে এর nonlocals জন্য Function । তাদের মূল্য কল মধ্যে পরিবর্তন Function , Function এখনও মান তারা ছিল যখন এটি আঁকা ছিল ব্যবহার করবে। এটি কিভাবে নিয়মিত পাইথন ফাংশন কাজ করে তার থেকে আলাদা।

সেই কারণে, আমরা একটি কার্যকরী প্রোগ্রামিং স্টাইলের সুপারিশ করি যা বাইরের নামগুলি বন্ধ করার পরিবর্তে আর্গুমেন্ট ব্যবহার করে।

@tf.function
def buggy_add():
  return 1 + foo

@tf.function
def recommended_add(foo):
  return 1 + foo

foo = 1
print("Buggy:", buggy_add())
print("Correct:", recommended_add(foo))
Buggy: tf.Tensor(2, shape=(), dtype=int32)
Correct: tf.Tensor(2, shape=(), dtype=int32)
print("Updating the value of `foo` to 100!")
foo = 100
print("Buggy:", buggy_add())  # Did not change!
print("Correct:", recommended_add(foo))
Updating the value of `foo` to 100!
Buggy: tf.Tensor(2, shape=(), dtype=int32)
Correct: tf.Tensor(101, shape=(), dtype=int32)

আপনি বাইরের নাম বন্ধ করতে পারেন, যতক্ষণ না আপনি তাদের মান আপডেট করেন।

পাইথন বস্তুর উপর নির্ভর করে

সুপারিশ পাইথন বস্তু পাস হিসাবে মধ্যে আর্গুমেন্ট tf.function পরিচিত বিষয়, যা ভবিষ্যতে সমাধান করা আশা করা যায় একটি নম্বর আছে। সাধারণভাবে, আপনি সামঞ্জস্যপূর্ণ হদিশ উপর নির্ভর আপনি একটি পাইথন আদিম বা ব্যবহার করতে পারেন tf.nest একটি আর্গুমেন্ট হিসাবে -compatible কাঠামো বা একটি মধ্যে একটি বস্তুর একটি ভিন্ন উদাহরণস্বরূপ মধ্যে পাস Function । যাইহোক, Function একটি নতুন ট্রেস তৈরি করতে হবে যখন আপনি একই বস্তুর পাস এবং শুধুমাত্র তার গুণাবলী পরিবর্তন করুন।

class SimpleModel(tf.Module):
  def __init__(self):
    # These values are *not* tf.Variables.
    self.bias = 0.
    self.weight = 2.

@tf.function
def evaluate(model, x):
  return model.weight * x + model.bias

simple_model = SimpleModel()
x = tf.constant(10.)
print(evaluate(simple_model, x))
tf.Tensor(20.0, shape=(), dtype=float32)
print("Adding bias!")
simple_model.bias += 5.0
print(evaluate(simple_model, x))  # Didn't change :(
Adding bias!
tf.Tensor(20.0, shape=(), dtype=float32)

একই ব্যবহার Function মডেলের আপডেট উদাহরণস্বরূপ নির্ণয় করা বগী হতে হবে যেহেতু আপডেট মডেল আছে একই ক্যাশে কী মূল মডেল হিসেবে।

যে কারণে, আমরা সুপারিশ করছি যে আপনি আপনার লেখার Function চপল বস্তুর বৈশিষ্ট্যাবলী উপর নির্ভর করে এড়ানো বা নতুন বস্তু তৈরি করুন।

যদি সেটা সম্ভব না হয়, এক কার্যসংক্রান্ত নতুন করা হয় Function প্রতিটি সময় আপনি বল ফিরে দেখা করার জন্য আপনার বস্তুর পরিবর্তন S:

def evaluate(model, x):
  return model.weight * x + model.bias

new_model = SimpleModel()
evaluate_no_bias = tf.function(evaluate).get_concrete_function(new_model, x)
# Don't pass in `new_model`, `Function` already captured its state during tracing.
print(evaluate_no_bias(x))
tf.Tensor(20.0, shape=(), dtype=float32)
print("Adding bias!")
new_model.bias += 5.0
# Create new Function and ConcreteFunction since you modified new_model.
evaluate_with_bias = tf.function(evaluate).get_concrete_function(new_model, x)
print(evaluate_with_bias(x)) # Don't pass in `new_model`.
Adding bias!
tf.Tensor(25.0, shape=(), dtype=float32)

হিসাবে ফিরে দেখা ব্যয়বহুল হতে পারে , আপনি ব্যবহার করতে পারেন tf.Variable একটি প্রত্যনুসরণ ছাড়াই বস্তুর বৈশিষ্ট্যাবলী, যা ভাবে পরিবর্তিত করা যেতে পারে (কিন্তু বদলে সাবধান!) একটি অনুরূপ প্রভাবের জন্য যেমন সে।

class BetterModel:

  def __init__(self):
    self.bias = tf.Variable(0.)
    self.weight = tf.Variable(2.)

@tf.function
def evaluate(model, x):
  return model.weight * x + model.bias

better_model = BetterModel()
print(evaluate(better_model, x))
tf.Tensor(20.0, shape=(), dtype=float32)
print("Adding bias!")
better_model.bias.assign_add(5.0)  # Note: instead of better_model.bias += 5
print(evaluate(better_model, x))  # This works!
Adding bias!
tf.Tensor(25.0, shape=(), dtype=float32)

টিএফ তৈরি করা হচ্ছে

Function শুধুমাত্র সমর্থন Singleton tf.Variable প্রথম কল একবার সৃষ্টি এবং পরবর্তী ফাংশান কল জুড়ে পুনঃব্যবহৃত। কোড নিচে snippet একটি নতুন তৈরি করবে tf.Variable যে ফাংশন কল, একটি যা ফলাফলে ValueError ব্যতিক্রম।

উদাহরণ:

@tf.function
def f(x):
  v = tf.Variable(1.0)
  return v

with assert_raises(ValueError):
  f(1.0)
Caught expected exception 
  <class 'ValueError'>:
Traceback (most recent call last):
  File "/tmp/ipykernel_25646/3551158538.py", line 8, in assert_raises
    yield
  File "/tmp/ipykernel_25646/3018268426.py", line 7, in <module>
    f(1.0)
ValueError: in user code:

    /tmp/ipykernel_25646/3018268426.py:3 f  *
        v = tf.Variable(1.0)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/variables.py:268 __call__  **
        return cls._variable_v2_call(*args, **kwargs)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/variables.py:262 _variable_v2_call
        shape=shape)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/variables.py:67 getter
        return captured_getter(captured_previous, **kwargs)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py:765 invalid_creator_scope
        "tf.function-decorated function tried to create "

    ValueError: tf.function-decorated function tried to create variables on non-first call.

একটি সাধারণ এই সীমাবদ্ধতা প্রায় কাজ করার জন্য ব্যবহার করা প্যাটার্ন একটি পাইথন কোনটি মান দিয়ে শুরু, তারপর শর্তসাপেক্ষে তৈরি করা tf.Variable যদি মান কোনটি হল:

class Count(tf.Module):
  def __init__(self):
    self.count = None

  @tf.function
  def __call__(self):
    if self.count is None:
      self.count = tf.Variable(0)
    return self.count.assign_add(1)

c = Count()
print(c())
print(c())
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)

একাধিক কেরাস অপটিমাইজার ব্যবহার করে

আপনি সম্মুখীন হতে পারে ValueError: tf.function only supports singleton tf.Variables created on the first call. যখন একটি সঙ্গে একটির বেশি Keras অপ্টিমাইজার ব্যবহার করে tf.function । এই সমস্যাটি ঘটে থাকে কারণ optimizers অভ্যন্তরীণভাবে তৈরি tf.Variables যখন তারা প্রথমবারের মত গ্রেডিয়েন্ট প্রয়োগ করুন।

opt1 = tf.keras.optimizers.Adam(learning_rate = 1e-2)
opt2 = tf.keras.optimizers.Adam(learning_rate = 1e-3)

@tf.function
def train_step(w, x, y, optimizer):
   with tf.GradientTape() as tape:
       L = tf.reduce_sum(tf.square(w*x - y))
   gradients = tape.gradient(L, [w])
   optimizer.apply_gradients(zip(gradients, [w]))

w = tf.Variable(2.)
x = tf.constant([-1.])
y = tf.constant([2.])

train_step(w, x, y, opt1)
print("Calling `train_step` with different optimizer...")
with assert_raises(ValueError):
  train_step(w, x, y, opt2)
Calling `train_step` with different optimizer...
Caught expected exception 
  <class 'ValueError'>:
Traceback (most recent call last):
  File "/tmp/ipykernel_25646/3551158538.py", line 8, in assert_raises
    yield
  File "/tmp/ipykernel_25646/3167358578.py", line 18, in <module>
    train_step(w, x, y, opt2)
ValueError: in user code:

    /tmp/ipykernel_25646/3167358578.py:9 train_step  *
        optimizer.apply_gradients(zip(gradients, [w]))
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/optimizer_v2.py:628 apply_gradients  **
        self._create_all_weights(var_list)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/optimizer_v2.py:813 _create_all_weights
        _ = self.iterations
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/optimizer_v2.py:820 __getattribute__
        return super(OptimizerV2, self).__getattribute__(name)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/optimizer_v2.py:980 iterations
        aggregation=tf.VariableAggregation.ONLY_FIRST_REPLICA)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/optimizer_v2.py:1186 add_weight
        aggregation=aggregation)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/training/tracking/base.py:818 _add_variable_with_custom_getter
        **kwargs_for_getter)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/engine/base_layer_utils.py:129 make_variable
        shape=variable_shape if variable_shape else None)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/variables.py:266 __call__
        return cls._variable_v1_call(*args, **kwargs)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/variables.py:227 _variable_v1_call
        shape=shape)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/variables.py:67 getter
        return captured_getter(captured_previous, **kwargs)
    /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py:765 invalid_creator_scope
        "tf.function-decorated function tried to create "

    ValueError: tf.function-decorated function tried to create variables on non-first call.

আপনি প্রশিক্ষণের সময় অপটিমাইজার পরিবর্তন করার প্রয়োজন হলে, একটি ওয়ার্কঅ্যারাউন্ড একটি নতুন তৈরি করা Function প্রতিটি অপটিমাইজার জন্য, কলিং ConcreteFunction সরাসরি।

opt1 = tf.keras.optimizers.Adam(learning_rate = 1e-2)
opt2 = tf.keras.optimizers.Adam(learning_rate = 1e-3)

# Not a tf.function.
def train_step(w, x, y, optimizer):
   with tf.GradientTape() as tape:
       L = tf.reduce_sum(tf.square(w*x - y))
   gradients = tape.gradient(L, [w])
   optimizer.apply_gradients(zip(gradients, [w]))

w = tf.Variable(2.)
x = tf.constant([-1.])
y = tf.constant([2.])

# Make a new Function and ConcreteFunction for each optimizer.
train_step_1 = tf.function(train_step).get_concrete_function(w, x, y, opt1)
train_step_2 = tf.function(train_step).get_concrete_function(w, x, y, opt2)
for i in range(10):
  if i % 2 == 0:
    train_step_1(w, x, y) # `opt1` is not used as a parameter. 
  else:
    train_step_2(w, x, y) # `opt2` is not used as a parameter.

একাধিক কেরাস মডেল ব্যবহার করে

এছাড়াও আপনি সম্মুখীন হতে পারে ValueError: tf.function only supports singleton tf.Variables created on the first call. যখন একই বিভিন্ন মডেল দৃষ্টান্ত ক্ষণস্থায়ী Function

এই সমস্যাটি ঘটে থাকে কারণ Keras মডেল (যা তাদের ইনপুট আকৃতি সংজ্ঞায়িত না থাকে ) এবং Keras স্তর তৈরি tf.Variables গুলি যখন তারা প্রথম বলা হয়। আপনি একটি ভিতরে যারা ভেরিয়েবল আরম্ভ করার চেষ্টা করা যেতে পারে Function যা ইতিমধ্যেই বলা হয়েছে। এই ত্রুটি এড়ানোর জন্য, কল করার চেষ্টা model.build(input_shape) মডেল প্রশিক্ষণ সামনে সব ওজন আরম্ভ করতে।

আরও পড়া

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