সাহায্য Kaggle উপর TensorFlow সঙ্গে গ্রেট বেরিয়ার রিফ রক্ষা চ্যালেঞ্জ যোগদান

গ্রাফ এবং tf.function এর ভূমিকা

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

ওভারভিউ

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

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

এটি একটি বড়-ছবি ওভারভিউ যে কভার কেমন tf.function আপনি গ্রাফ সঞ্চালনের আগ্রহী মৃত্যুদন্ড থেকে স্যুইচ করতে পারেন। একটি সম্পূর্ণ স্পেসিফিকেশন জন্য tf.function , এখানে যান tf.function নির্দেশিকা

গ্রাফ কি?

পূর্ববর্তী তিন গাইড, আপনি TensorFlow সাগ্রহে দৌড়ে। এর মানে হল TensorFlow অপারেশনগুলি Python দ্বারা সম্পাদিত হয়, অপারেশন দ্বারা অপারেশন করা হয় এবং ফলাফলগুলি Python-এ ফিরে আসে।

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

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

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

একটি সাধারণ টেনসরফ্লো গ্রাফ

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

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

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

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

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

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

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

সেটআপ

import tensorflow as tf
import timeit
from datetime import datetime

গ্রাফ সুবিধা গ্রহণ

তৈরি এবং ব্যবহার করে TensorFlow একটি গ্রাফ চালানো tf.function , হয় সরাসরি কল হিসাবে বা প্রসাধক হিসাবে। tf.function ইনপুট হিসাবে একটি নিয়মিত ফাংশন লাগে এবং একটি ফেরৎ Functionএকটি Function একটি পাইথন callable যে পাইথন ফাংশন থেকে TensorFlow গ্রাফ তৈরী করে নেই। আপনি একটি ব্যবহার Function তার পাইথন সমতুল্য হিসাবে একই ভাবে।

# Define a Python function.
def a_regular_function(x, y, b):
  x = tf.matmul(x, y)
  x = x + b
  return x

# `a_function_that_uses_a_graph` is a TensorFlow `Function`.
a_function_that_uses_a_graph = tf.function(a_regular_function)

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

orig_value = a_regular_function(x1, y1, b1).numpy()
# Call a `Function` like a Python function.
tf_function_value = a_function_that_uses_a_graph(x1, y1, b1).numpy()
assert(orig_value == tf_function_value)

বাহিরে, একটি Function একটি নিয়মিত ফাংশন মত দেখে মনে হচ্ছে আপনি TensorFlow অপারেশন ব্যবহার লিখ। নিম্নে যদিও, খুব আলাদা। একটি Function encapsulates বিভিন্ন tf.Graph এক এপিআই পিছনে গুলি কেমন করে এমন হলো Function আপনাকে দিতে সক্ষম হয় গ্রাফ সঞ্চালনের সুবিধা , গতি এবং deployability মত।

tf.function একটি ফাংশন এবং সমস্ত অন্যান্য ফাংশন এটা কল প্রযোজ্য:

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

# Use the decorator to make `outer_function` a `Function`.
@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)

আপনি TensorFlow 1.x ব্যবহার করে থাকেন তাহলে আপনি কোন সময়ে আপনি একটি সংজ্ঞায়িত করতে প্রয়োজন ছিল যে লক্ষ্য করবেন Placeholder বা tf.Session

পাইথন ফাংশনগুলিকে গ্রাফে রূপান্তর করা হচ্ছে

কোন ফাংশন আপনি TensorFlow সঙ্গে লিখতে মিশ্রণ উপস্থিত থাকবে বিল্ট-ইন যেমন মেমরি অপারেশন এবং পাইথন যুক্তি, if-then ক্লজ, লুপ, break , return , continue , এবং আরো। TensorFlow অপারেশন সহজেই একটি ক্যাপচার হলেও tf.Graph অর্ডার গ্রাফ অংশ হয়ে করার জন্য একটি অতিরিক্ত পদক্ষেপ ভুগা, পাইথন-নির্দিষ্ট যুক্তিবিজ্ঞান চাহিদা। tf.function একটি লাইব্রেরি অটোগ্রাফ (যাকে বলা হয় ব্যবহার tf.autograph গ্রাফ-উৎপাদিত কোডে পাইথন কোড রূপান্তর করতে)।

def simple_relu(x):
  if tf.greater(x, 0):
    return x
  else:
    return 0

# `tf_simple_relu` is a TensorFlow `Function` that wraps `simple_relu`.
tf_simple_relu = tf.function(simple_relu)

print("First branch, with graph:", tf_simple_relu(tf.constant(1)).numpy())
print("Second branch, with graph:", tf_simple_relu(tf.constant(-1)).numpy())
First branch, with graph: 1
Second branch, with graph: 0

যদিও এটি অসম্ভাব্য যে আপনাকে সরাসরি গ্রাফগুলি দেখতে হবে, আপনি সঠিক ফলাফলগুলি পরীক্ষা করতে আউটপুটগুলি পরিদর্শন করতে পারেন। এগুলি পড়া সহজ নয়, তাই খুব মনোযোগ দিয়ে দেখার দরকার নেই!

# This is the graph-generating output of AutoGraph.
print(tf.autograph.to_code(simple_relu))
def tf__simple_relu(x):
    with ag__.FunctionScope('simple_relu', '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 (do_return, retval_)

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

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

        def else_body():
            nonlocal retval_, do_return
            try:
                do_return = True
                retval_ = 0
            except:
                do_return = False
                raise
        ag__.if_stmt(ag__.converted_call(ag__.ld(tf).greater, (ag__.ld(x), 0), None, fscope), if_body, else_body, get_state, set_state, ('do_return', 'retval_'), 2)
        return fscope.ret(retval_, do_return)
# This is the graph itself.
print(tf_simple_relu.get_concrete_function(tf.constant(1)).graph.as_graph_def())
node {
  name: "x"
  op: "Placeholder"
  attr {
    key: "_user_specified_name"
    value {
      s: "x"
    }
  }
  attr {
    key: "dtype"
    value {
      type: DT_INT32
    }
  }
  attr {
    key: "shape"
    value {
      shape {
      }
    }
  }
}
node {
  name: "Greater/y"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_INT32
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_INT32
        tensor_shape {
        }
        int_val: 0
      }
    }
  }
}
node {
  name: "Greater"
  op: "Greater"
  input: "x"
  input: "Greater/y"
  attr {
    key: "T"
    value {
      type: DT_INT32
    }
  }
}
node {
  name: "cond"
  op: "StatelessIf"
  input: "Greater"
  input: "x"
  attr {
    key: "Tcond"
    value {
      type: DT_BOOL
    }
  }
  attr {
    key: "Tin"
    value {
      list {
        type: DT_INT32
      }
    }
  }
  attr {
    key: "Tout"
    value {
      list {
        type: DT_BOOL
        type: DT_INT32
      }
    }
  }
  attr {
    key: "_lower_using_switch_merge"
    value {
      b: true
    }
  }
  attr {
    key: "_read_only_resource_inputs"
    value {
      list {
      }
    }
  }
  attr {
    key: "else_branch"
    value {
      func {
        name: "cond_false_34"
      }
    }
  }
  attr {
    key: "output_shapes"
    value {
      list {
        shape {
        }
        shape {
        }
      }
    }
  }
  attr {
    key: "then_branch"
    value {
      func {
        name: "cond_true_33"
      }
    }
  }
}
node {
  name: "cond/Identity"
  op: "Identity"
  input: "cond"
  attr {
    key: "T"
    value {
      type: DT_BOOL
    }
  }
}
node {
  name: "cond/Identity_1"
  op: "Identity"
  input: "cond:1"
  attr {
    key: "T"
    value {
      type: DT_INT32
    }
  }
}
node {
  name: "Identity"
  op: "Identity"
  input: "cond/Identity_1"
  attr {
    key: "T"
    value {
      type: DT_INT32
    }
  }
}
library {
  function {
    signature {
      name: "cond_false_34"
      input_arg {
        name: "cond_placeholder"
        type: DT_INT32
      }
      output_arg {
        name: "cond_identity"
        type: DT_BOOL
      }
      output_arg {
        name: "cond_identity_1"
        type: DT_INT32
      }
    }
    node_def {
      name: "cond/Const"
      op: "Const"
      attr {
        key: "dtype"
        value {
          type: DT_BOOL
        }
      }
      attr {
        key: "value"
        value {
          tensor {
            dtype: DT_BOOL
            tensor_shape {
            }
            bool_val: true
          }
        }
      }
      experimental_debug_info {
        original_node_names: "cond/Const"
      }
    }
    node_def {
      name: "cond/Const_1"
      op: "Const"
      attr {
        key: "dtype"
        value {
          type: DT_BOOL
        }
      }
      attr {
        key: "value"
        value {
          tensor {
            dtype: DT_BOOL
            tensor_shape {
            }
            bool_val: true
          }
        }
      }
      experimental_debug_info {
        original_node_names: "cond/Const_1"
      }
    }
    node_def {
      name: "cond/Const_2"
      op: "Const"
      attr {
        key: "dtype"
        value {
          type: DT_INT32
        }
      }
      attr {
        key: "value"
        value {
          tensor {
            dtype: DT_INT32
            tensor_shape {
            }
            int_val: 0
          }
        }
      }
      experimental_debug_info {
        original_node_names: "cond/Const_2"
      }
    }
    node_def {
      name: "cond/Const_3"
      op: "Const"
      attr {
        key: "dtype"
        value {
          type: DT_BOOL
        }
      }
      attr {
        key: "value"
        value {
          tensor {
            dtype: DT_BOOL
            tensor_shape {
            }
            bool_val: true
          }
        }
      }
      experimental_debug_info {
        original_node_names: "cond/Const_3"
      }
    }
    node_def {
      name: "cond/Identity"
      op: "Identity"
      input: "cond/Const_3:output:0"
      attr {
        key: "T"
        value {
          type: DT_BOOL
        }
      }
      experimental_debug_info {
        original_node_names: "cond/Identity"
      }
    }
    node_def {
      name: "cond/Const_4"
      op: "Const"
      attr {
        key: "dtype"
        value {
          type: DT_INT32
        }
      }
      attr {
        key: "value"
        value {
          tensor {
            dtype: DT_INT32
            tensor_shape {
            }
            int_val: 0
          }
        }
      }
      experimental_debug_info {
        original_node_names: "cond/Const_4"
      }
    }
    node_def {
      name: "cond/Identity_1"
      op: "Identity"
      input: "cond/Const_4:output:0"
      attr {
        key: "T"
        value {
          type: DT_INT32
        }
      }
      experimental_debug_info {
        original_node_names: "cond/Identity_1"
      }
    }
    ret {
      key: "cond_identity"
      value: "cond/Identity:output:0"
    }
    ret {
      key: "cond_identity_1"
      value: "cond/Identity_1:output:0"
    }
    attr {
      key: "_construction_context"
      value {
        s: "kEagerRuntime"
      }
    }
    arg_attr {
      key: 0
      value {
        attr {
          key: "_output_shapes"
          value {
            list {
              shape {
              }
            }
          }
        }
      }
    }
  }
  function {
    signature {
      name: "cond_true_33"
      input_arg {
        name: "cond_identity_1_x"
        type: DT_INT32
      }
      output_arg {
        name: "cond_identity"
        type: DT_BOOL
      }
      output_arg {
        name: "cond_identity_1"
        type: DT_INT32
      }
    }
    node_def {
      name: "cond/Const"
      op: "Const"
      attr {
        key: "dtype"
        value {
          type: DT_BOOL
        }
      }
      attr {
        key: "value"
        value {
          tensor {
            dtype: DT_BOOL
            tensor_shape {
            }
            bool_val: true
          }
        }
      }
      experimental_debug_info {
        original_node_names: "cond/Const"
      }
    }
    node_def {
      name: "cond/Identity"
      op: "Identity"
      input: "cond/Const:output:0"
      attr {
        key: "T"
        value {
          type: DT_BOOL
        }
      }
      experimental_debug_info {
        original_node_names: "cond/Identity"
      }
    }
    node_def {
      name: "cond/Identity_1"
      op: "Identity"
      input: "cond_identity_1_x"
      attr {
        key: "T"
        value {
          type: DT_INT32
        }
      }
      experimental_debug_info {
        original_node_names: "cond/Identity_1"
      }
    }
    ret {
      key: "cond_identity"
      value: "cond/Identity:output:0"
    }
    ret {
      key: "cond_identity_1"
      value: "cond/Identity_1:output:0"
    }
    attr {
      key: "_construction_context"
      value {
        s: "kEagerRuntime"
      }
    }
    arg_attr {
      key: 0
      value {
        attr {
          key: "_output_shapes"
          value {
            list {
              shape {
              }
            }
          }
        }
      }
    }
  }
}
versions {
  producer: 808
  min_consumer: 12
}

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

পলিমরফিজ্ম: এক Function অনেক গ্রাফ

একজন tf.Graph ইনপুট একটি নির্দিষ্ট ধরনের বিশেষজ্ঞ (উদাহরণস্বরূপ, একটি নির্দিষ্ট সঙ্গে tensors dtype অথবা একই সঙ্গে বস্তু id() )।

প্রতিবার আপনি একটি ডাকা Function নতুন dtypes এর আর্গুমেন্টগুলি এবং আকৃতি, Function একটি নতুন সৃষ্টি tf.Graph নতুন আর্গুমেন্ট জন্য। dtypes এবং এর আকার tf.Graph এর ইনপুট একটি ইনপুট স্বাক্ষর বা শুধু একটি স্বাক্ষর হিসাবে পরিচিত হয়।

Function দোকানে tf.Graph একটি স্বাক্ষর সংশ্লিষ্ট ConcreteFunctionএকজন ConcreteFunction একটি কাছাকাছি একটি লেফাফা হয় tf.Graph

@tf.function
def my_relu(x):
  return tf.maximum(0., x)

# `my_relu` creates new graphs as it observes more signatures.
print(my_relu(tf.constant(5.5)))
print(my_relu([1, -1]))
print(my_relu(tf.constant([3., -3.])))
tf.Tensor(5.5, shape=(), dtype=float32)
tf.Tensor([1. 0.], shape=(2,), dtype=float32)
tf.Tensor([3. 0.], shape=(2,), dtype=float32)

যদি Function ইতিমধ্যে যে স্বাক্ষর সহ বলা হয়েছে, Function একটি নতুন তৈরি করে না tf.Graph

# These two calls do *not* create new graphs.
print(my_relu(tf.constant(-2.5))) # Signature matches `tf.constant(5.5)`.
print(my_relu(tf.constant([-1., 1.]))) # Signature matches `tf.constant([3., -3.])`.
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor([0. 1.], shape=(2,), dtype=float32)

কারণ এটা একাধিক গ্রাফ সমর্থন, একটি Function বহুরুপী হয়। এটা আরো ইনপুট ধরনের একটি একক চেয়ে সমর্থন সক্ষম tf.Graph প্রতিনিধিত্ব করতে পারে, সেইসাথে প্রতিটি নিখুত tf.Graph ভাল কার্য সম্পাদনার জন্য।

# There are three `ConcreteFunction`s (one for each graph) in `my_relu`.
# The `ConcreteFunction` also knows the return type and shape!
print(my_relu.pretty_printed_concrete_signatures())
my_relu(x)
  Args:
    x: float32 Tensor, shape=()
  Returns:
    float32 Tensor, shape=()

my_relu(x=[1, -1])
  Returns:
    float32 Tensor, shape=(2,)

my_relu(x)
  Args:
    x: float32 Tensor, shape=(2,)
  Returns:
    float32 Tensor, shape=(2,)

ব্যবহার tf.function

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

গ্রাফ এক্সিকিউশন বনাম আগ্রহী মৃত্যুদন্ড

একটি কোড Function উভয় সাগ্রহে এবং একটি গ্রাফ হিসাবে সম্পাদন করতে পারে। ডিফল্টরূপে, Function গ্রাফ হিসাবে এটির কোড executes:

@tf.function
def get_MSE(y_true, y_pred):
  sq_diff = tf.pow(y_true - y_pred, 2)
  return tf.reduce_mean(sq_diff)
y_true = tf.random.uniform([5], maxval=10, dtype=tf.int32)
y_pred = tf.random.uniform([5], maxval=10, dtype=tf.int32)
print(y_true)
print(y_pred)
tf.Tensor([6 1 7 8 0], shape=(5,), dtype=int32)
tf.Tensor([6 0 1 8 6], shape=(5,), dtype=int32)
get_MSE(y_true, y_pred)
<tf.Tensor: shape=(), dtype=int32, numpy=14>

তা যাচাই করতে আপনার Function এর গ্রাফ তার সমতুল্য পাইথন ফাংশন হিসাবে একই গণনার করছে, আপনি এটি দিয়ে সাগ্রহে চালানো করতে পারেন tf.config.run_functions_eagerly(True) । এই সুইচ বন্ধ করিয়া হয় Function এর তৈরি করার ক্ষমতা এবং চালানোর গ্রাফ, পরিবর্তে স্বাভাবিকভাবে কোড নির্বাহ।

tf.config.run_functions_eagerly(True)
get_MSE(y_true, y_pred)
<tf.Tensor: shape=(), dtype=int32, numpy=14>
# Don't forget to set it back when you are done.
tf.config.run_functions_eagerly(False)

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

@tf.function
def get_MSE(y_true, y_pred):
  print("Calculating MSE!")
  sq_diff = tf.pow(y_true - y_pred, 2)
  return tf.reduce_mean(sq_diff)

কি মুদ্রিত হয় তা পর্যবেক্ষণ করুন:

error = get_MSE(y_true, y_pred)
error = get_MSE(y_true, y_pred)
error = get_MSE(y_true, y_pred)
Calculating MSE!

আউটপুট আশ্চর্যজনক? get_MSE শুধুমাত্র একবার মুদ্রিত যদিও এটি তিনবার ডাকা হয়।

ব্যাখ্যা, print যখন বিবৃতি কার্যকর Function অর্ডার নামে পরিচিত প্রক্রিয়ায় গ্রাফ তৈরি করার জন্য মূল কোড রান "ট্রেসিং"গ্রাফ মধ্যে যেমনটি ট্রেস TensorFlow অপারেশন, এবং print গ্রাফ বন্দী করা হয় না। যে গ্রাফ তারপর কি কখনো পাইথন কোড পুনরায় চলমান ছাড়া সব তিনটি কলের জন্য মৃত্যুদন্ড কার্যকর করা হয়।

একটি স্যানিটি চেক হিসাবে, তুলনা করতে গ্রাফ এক্সিকিউশন বন্ধ করা যাক:

# Now, globally set everything to run eagerly to force eager execution.
tf.config.run_functions_eagerly(True)
# Observe what is printed below.
error = get_MSE(y_true, y_pred)
error = get_MSE(y_true, y_pred)
error = get_MSE(y_true, y_pred)
Calculating MSE!
Calculating MSE!
Calculating MSE!
tf.config.run_functions_eagerly(False)

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

অ-কঠোর মৃত্যুদন্ড

গ্রাফ এক্সিকিউশন শুধুমাত্র পর্যবেক্ষণযোগ্য প্রভাব তৈরি করার জন্য প্রয়োজনীয় ক্রিয়াকলাপগুলি সম্পাদন করে, যার মধ্যে রয়েছে:

  • ফাংশনের রিটার্ন মান
  • নথিভুক্ত সুপরিচিত পার্শ্ব-প্রতিক্রিয়া যেমন:
    • ইনপুট / আউটপুট অপারেশন, মত tf.print
    • যেমন জাহির ফাংশন হিসাবে ডিবাগ অভিযান tf.debugging
    • এর পরিব্যক্তি tf.Variable

এই আচরণটি সাধারণত "নন-স্ট্রিক এক্সিকিউশন" নামে পরিচিত, এবং এটি উদগ্রীবভাবে কার্যকর করা থেকে ভিন্ন, যা প্রয়োজন বা না থাকা সমস্ত প্রোগ্রাম অপারেশনের মধ্য দিয়ে যায়।

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

নিম্নলিখিত উদাহরণে, "অপ্রয়োজনীয়" অপারেশন tf.gather হয়, গ্রাফ সম্পাদনের সময় এড়ানো তাই রানটাইম এরর InvalidArgumentError উত্থাপিত না হয় যেমন অধীর ফাঁসি হবে। একটি গ্রাফ কার্যকর করার সময় উত্থাপিত একটি ত্রুটির উপর নির্ভর করবেন না।

def unused_return_eager(x):
  # Get index 1 will fail when `len(x) == 1`
  tf.gather(x, [1]) # unused 
  return x

try:
  print(unused_return_eager(tf.constant([0.0])))
except tf.errors.InvalidArgumentError as e:
  # All operations are run during eager execution so an error is raised.
  print(f'{type(e).__name__}: {e}')
tf.Tensor([0.], shape=(1,), dtype=float32)
@tf.function
def unused_return_graph(x):
  tf.gather(x, [1]) # unused
  return x

# Only needed operations are run during graph exection. The error is not raised.
print(unused_return_graph(tf.constant([0.0])))
tf.Tensor([0.], shape=(1,), dtype=float32)

tf.function সর্বোত্তম কার্যাভ্যাস

এটা কিছু সময় লাগতে আচরণকে ব্যবহার করতে পারে Function । দ্রুত শুরু করার জন্য, প্রথমবার ব্যবহারকারীদের সাথে শোভাকর খেলনা ফাংশন সঙ্গে চারপাশে খেলা উচিত @tf.function উৎসুক থেকে গ্রাফ সঞ্চালনের যাচ্ছে সঙ্গে অভিজ্ঞতা জন্য।

জন্য ডিজাইনিং tf.function গ্রাফ সামঞ্জস্যপূর্ণ TensorFlow প্রোগ্রাম লেখার জন্য আপনার সেরা বাজি হতে পারে। এখানে কিছু টিপস আছে:

  • উৎসুক এবং গ্রাফ সঞ্চালনের মধ্যে টগল করুন তাড়াতাড়ি এবং প্রায়ই সঙ্গে tf.config.run_functions_eagerly দিতে পিনপয়েন্ট যদি / যখন দুটি মোড বিকিরণ ঘটে।
  • তৈরি করুন tf.Variable গুলি বাহিরে পাইথন ফাংশন এবং ভেতরের তাদের পরিবর্তন। একই বস্তু যা ব্যবহার জন্য যায় tf.Variable মত keras.layers , keras.Model s এবং tf.optimizers
  • ফাংশন যে লেখা এড়িয়ে চলুন বাইরের পাইথন ভেরিয়েবল উপর নির্ভর করে , ব্যতীত tf.Variable s এবং Keras অবজেক্ট।
  • ফাংশন লিখতে পছন্দ করুন যা টেনসর এবং অন্যান্য টেনসরফ্লো প্রকারকে ইনপুট হিসাবে গ্রহণ করে। আপনি অন্যান্য বস্তুর ধরনের মধ্যে পাস দিতে পারেন, সতর্কতা অবলম্বন করা আবশ্যক !
  • একটি অধীনে যতটা সম্ভব গণনার হিসাবে অন্তর্ভুক্ত করুন tf.function কর্মক্ষমতা লাভ পূর্ণবিস্তার। উদাহরণস্বরূপ, একটি সম্পূর্ণ প্রশিক্ষণ ধাপ বা সম্পূর্ণ প্রশিক্ষণ লুপ সাজাইয়া.

স্পিড-আপ দেখে

tf.function সাধারণত আপনার কোডের উন্নত কর্মক্ষমতা কিন্তু গতি-আপ পরিমাণ গণনার ধরনের আপনি চালাতে উপর নির্ভর করে। একটি গ্রাফ কল করার ওভারহেড দ্বারা ছোট গণনা প্রাধান্য পেতে পারে। আপনি এই মত কর্মক্ষমতা পার্থক্য পরিমাপ করতে পারেন:

x = tf.random.uniform(shape=[10, 10], minval=-1, maxval=2, dtype=tf.dtypes.int32)

def power(x, y):
  result = tf.eye(10, dtype=tf.dtypes.int32)
  for _ in range(y):
    result = tf.matmul(x, result)
  return result
print("Eager execution:", timeit.timeit(lambda: power(x, 100), number=1000))
Eager execution: 2.0122516460000384
power_as_graph = tf.function(power)
print("Graph execution:", timeit.timeit(lambda: power_as_graph(x, 100), number=1000))
Graph execution: 0.6084441319999883

tf.function সাধারণভাবে প্রশিক্ষণ লুপ গতি বাড়াতে ব্যবহার করা হয়, এবং আপনি এটা সম্পর্কে আরও জানতে পারেন স্ক্র্যাচ থেকে একটি প্রশিক্ষণ লুপ লেখা Keras সঙ্গে।

কর্মক্ষমতা এবং ট্রেড-অফ

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

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

যখন একটি হয় Function ট্রেসিং?

জিনিসটা যখন আপনার Function ট্রেসিং, একটি যোগ print তার কোডে বিবৃতি। একটি চলতি নিয়ম অনুযায়ী, Function চালানো হবে print বিবৃতি প্রত্যেক সময় এটা ট্রেস।

@tf.function
def a_function_with_python_side_effect(x):
  print("Tracing!") # An eager-only side effect.
  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)))
Tracing!
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(11, shape=(), dtype=int32)
# 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)
Tracing!
tf.Tensor(11, shape=(), dtype=int32)

নতুন পাইথন আর্গুমেন্ট সবসময় একটি নতুন গ্রাফ তৈরি করে, তাই অতিরিক্ত ট্রেসিং।

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

আপনি সম্পর্কে আরও জানতে পারেন tf.function এপিআই রেফারেন্স পৃষ্ঠা এবং অনুসরণ করে সঙ্গে উন্নত কর্মক্ষমতা tf.function গাইড।