مقدمه ای بر نمودارها و عملکرد tf

مشاهده در TensorFlow.org در Google Colab اجرا کنید مشاهده منبع در GitHub دانلود دفترچه یادداشت

بررسی اجمالی

این راهنما به زیر سطح TensorFlow و Keras می رود تا نحوه عملکرد TensorFlow را نشان دهد. اگر می خواهید بلافاصله با Keras شروع به کار کنید ، مجموعه راهنماهای Keras را بررسی کنید .

در این راهنما خواهید آموخت که چگونه TensorFlow به شما امکان می دهد برای بدست آوردن نمودار ، تغییر ساده کد ، نحوه ذخیره و نمایش نمودار ، و چگونگی استفاده از آنها برای تسریع مدل های خود ، اقدام کنید.

این یک نمای کلی است که شامل چگونگی tf.function که به شما امکان می دهد از اجرای مشتاق به اجرای نمودار تغییر وضعیت دهید. برای مشخصات tf.function ، به راهنمای tf.function .

نمودارها چیست؟

در سه راهنمای قبلی ، TensorFlow را با اشتیاق اجرا کردید. این بدان معناست که عملیات TensorFlow توسط پایتون ، عملیاتی با عملکرد و بازگشت نتایج به پایتون اجرا می شود.

در حالی که اجرای مشتاق چندین مزیت منحصر به فرد دارد ، اجرای نمودار قابلیت جابجایی در خارج از پایتون را فراهم می کند و تمایل به ارائه عملکرد بهتر دارد. اجرای نمودار به این معنی است که محاسبات تنسور به صورت نمودار tf.Graph اجرا می شود که گاهی اوقات به آن tf.Graph یا به سادگی "نمودار" گفته می شود.

نمودارها ساختارهای داده ای هستند که حاوی مجموعه ای از اشیا tf.Operation که واحد های محاسبه را نشان می دهد. و tf.Tensor اجسام tf.Tensor ، که واحدهای داده ای را نشان می دهد که بین عملیات جریان دارند. آنها در متن tf.Graph تعریف می شوند. از آنجا که این نمودارها ساختار داده ای هستند ، می توان همه آنها را بدون کد اصلی Python ذخیره ، اجرا و بازیابی کرد.

این نمودار TensorFlow است که نمایانگر یک شبکه عصبی دو لایه است که در TensorBoard تجسم می یابد.

یک نمودار ساده TensorFlow

مزایای نمودارها

با نمودار ، انعطاف پذیری زیادی دارید. شما می توانید از نمودار TensorFlow خود در محیط هایی که مفسر Python ندارند ، مانند برنامه های تلفن همراه ، دستگاه های جاسازی شده و سرورهای Backend استفاده کنید. TensorFlow از نمودارها به عنوان قالب مدلهای ذخیره شده هنگام صادرات از پایتون استفاده می کند.

نمودارها نیز به راحتی بهینه می شوند ، و به کامپایلر اجازه می دهد تحولاتی مانند:

  • آماری ارزش تانسورها توسط تاشو گره ثابت در محاسبات خود را ( "تاشو ثابت") استنباط است.
  • بخشهای فرعی مستقل را از هم جدا کرده و آنها را بین رشته ها یا دستگاه ها تقسیم کنید.
  • با از بین بردن زیر عبارات رایج ، عملیات حساب را ساده کنید.

یک سیستم بهینه سازی کامل ، Grappler ، برای انجام این سرعت و سرعت های دیگر وجود دارد.

به طور خلاصه ، نمودارها بسیار مفید هستند و به شما اجازه می دهند TensorFlow سریع اجرا شود ، به صورت موازی اجرا شود و به صورت کارآمد روی چندین دستگاه اجرا شود .

با این حال ، شما هنوز هم می خواهید مدل های یادگیری ماشین خود (یا سایر محاسبات) را در پایتون برای راحتی کار تعریف کنید ، و سپس در صورت نیاز به طور خودکار نمودارها را بسازید.

استفاده از نمودارها

شما با استفاده از tf.function ، یا به عنوان تماس مستقیم یا به عنوان دکوراتور ، tf.function ایجاد و اجرا می کنید. tf.function یک تابع منظم را به عنوان ورودی می گیرد و یک Function برمی گرداند. یک Function یک فراخوانی پایتون است که نمودارهای TensorFlow را از تابع پایتون می سازد. شما از یک Function به همان روشی که معادل پایتون آن است استفاده می کنید.

import tensorflow as tf
import timeit
from datetime import datetime
# 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 چندین tf.Graph پشت یک API محصور می کند . به این ترتیب Function قادر است مزایای اجرای نمودار مانند سرعت و قابلیت استفاده را به شما ارائه دهد.

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 بنویسید شامل ترکیبی از عملیات TF داخلی و منطق پایتون خواهد بود ، مانند جمله های if-then ، حلقه ها ، break ، return ، continue و موارد دیگر. در حالی که عملیات tf.Graph به راحتی توسط tf.Graph ، منطق خاص پایتون برای تبدیل شدن به بخشی از نمودار نیاز به یک مرحله اضافی دارد. tf.function از کتابخانه ای به نام AutoGraph ( 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 do_return, retval_
            (do_return, retval_) = vars_

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

        def else_body():
            nonlocal do_return, retval_
            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: 716
  min_consumer: 12
}

بیشتر اوقات ، tf.function بدون ملاحظات خاص کار خواهد کرد. با این حال ، برخی از هشدارها وجود دارد و راهنمای tf.function می تواند در اینجا و همچنین مرجع کامل AutoGraph به شما کمک کند.

چندشکلی: یک Function ، نمودارهای زیاد

tf.Graph به نوع خاصی از ورودی ها اختصاص دارد (به عنوان مثال ،dtype با نوع خاص یا اشیا id() با همان 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 می تواند نشان دهد و همچنین هر 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

تا کنون ، شما یاد گرفته اید که چگونه یک تابع Python را به سادگی با استفاده از tf.function به عنوان دکوراتور یا لفاف تبدیل کنید. اما در عمل ، عملکرد صحیح tf.function می تواند مشکل باشد! در بخش های بعدی ، شما خواهید tf.function که چگونه می توانید با tf.function کد خود را مطابق انتظار کار کنید.

اجرای نمودار در مقابل اعدام مشتاقانه

کد موجود در یک Function می توان با اشتیاق و به صورت نمودار اجرا کرد. به طور پیش فرض ، Function کد خود را به صورت نمودار اجرا می کند:

@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([1 1 0 0 5], shape=(5,), dtype=int32)
tf.Tensor([9 1 4 9 0], shape=(5,), dtype=int32)
get_MSE(y_true, y_pred)
<tf.Tensor: shape=(), dtype=int32, numpy=37>

برای بررسی اینکه نمودار 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=37>
# 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 کد اصلی را اجرا می کند ، به منظور ایجاد نمودار در فرآیندی که به عنوان "ردیابی" شناخته می شود ، اجرا می شود. Tracing عملیات 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.function بهترین عملکردها

ممکن است مدتی طول بکشد تا به رفتار Function عادت کنید. برای شروع سریع ، کاربران برای اولین بار باید با استفاده از عملکرد @tf.function با اسباب بازی های تزئینی بازی کنند تا تجربه رفتن از اجرای اشتیاق به نمودار را تجربه کنند.

طراحی برای tf.function ممکن است بهترین شرط شما برای نوشتن برنامه های TensorFlow سازگار با نمودار باشد. در اینجا چند نکته وجود دارد:

  • بین اجرای اشتیاق و نمودار زودهنگام و اغلب با tf.config.run_functions_eagerly تا مشخص کنید اگر و یا دو حالت از هم جدا هستند.
  • tf.Variable ها را خارج از تابع Python ایجاد کنید و آنها را از داخل تغییر دهید. همین امر برای اشیایی که از tf.Variable استفاده می کنند tf.Variable ، مانندkeras.layers ، keras.Model s و tf.optimizers .
  • از نوشتن توابع وابسته به متغیرهای خارجی پایتون ، به استثنای tf.Variable t tf.Variable و Keras tf.Variable کنید.
  • ترجیح می دهید توابعی را بنویسید که سنسورها و انواع دیگر TensorFlow را به عنوان ورودی در نظر بگیرند. می توانید در انواع دیگر اشیا pass عبور کنید اما مراقب باشید !
  • برای به حداکثر رساندن افزایش عملکرد ، تا حد امکان محاسبه را در زیر یک 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: 1.8956256799999665
power_as_graph = tf.function(power)
print("Graph execution:", timeit.timeit(lambda: power_as_graph(x, 100), number=1000))
Graph execution: 0.5566363650000312

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 می توانید اطلاعات بیشتری در مورد tf.function در صفحه مرجع API tf.function .