Google I / O, 18-20 Mayıs'ta geri dönüyor! Yer ayırın ve programınızı oluşturun Şimdi kaydolun

Grafiklere ve tf fonksiyonuna giriş

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Defteri indirin

Genel Bakış

Bu kılavuz, TensorFlow'un nasıl çalıştığını görmek için TensorFlow ve Keras yüzeyinin altından geçer. Bunun yerine Keras'ı hemen kullanmaya başlamak istiyorsanız, lütfen Keras kılavuzları koleksiyonumuza bakın.

Bu kılavuzda, TensorFlow'un grafikler elde etmek için kodunuzda basit değişiklikler yapmanıza nasıl izin verdiğini, grafiklerin nasıl saklandığını ve temsil edildiğini ve modellerinizi hızlandırmak için bunları nasıl kullanabileceğinizi göreceksiniz.

Bu, tf.function istekli yürütmeden grafik yürütmeye geçiş yapmanıza nasıl izin verdiğini kapsayan büyük bir resim tf.function . tf.function daha eksiksiz bir özelliği için , tf.function kılavuzuna bakın .

Grafik nedir?

Önceki üç kılavuzda, TensorFlow'un hevesle çalıştığını gördünüz. Bu, TensorFlow işlemlerinin Python tarafından yürütüldüğü, işlem başına işlem yapıldığı ve sonuçları Python'a geri döndürdüğü anlamına gelir.

İstekli yürütmenin birkaç benzersiz avantajı olsa da, grafik yürütme Python dışında taşınabilirliği sağlar ve daha iyi performans sunma eğilimindedir. Grafik yürütme , tensör hesaplamalarının, bazen tf.Graph veya kısaca "grafik" olarak adlandırılan bir TensorFlow grafiği olarak yürütüldüğü anlamına gelir.

Grafikler, hesaplama birimlerini temsil eden bir dizi tf.Operation nesnesi içeren veri yapılarıdır; ve işlemler arasında akan veri birimlerini temsil eden tf.Tensor nesneleri. Bir tf.Graph bağlamında tanımlanırlar. Bu grafikler veri yapıları olduğundan, orijinal Python kodu olmadan kaydedilebilir, çalıştırılabilir ve geri yüklenebilir.

Bu, iki katmanlı bir sinir ağını temsil eden bir TensorFlow grafiği, TensorBoard'da görselleştirildiğinde böyle görünüyor.

Basit bir TensorFlow grafiği

Grafiklerin faydaları

Bir grafikle, büyük bir esnekliğe sahipsiniz. TensorFlow grafiğinizi, mobil uygulamalar, gömülü cihazlar ve arka uç sunucuları gibi Python yorumlayıcısı olmayan ortamlarda kullanabilirsiniz. TensorFlow, grafikleri Python'dan dışa aktardığında kaydedilen modeller için format olarak kullanır.

Grafikler de kolayca optimize edilerek derleyicinin aşağıdaki gibi dönüşümler yapmasına olanak tanır:

  • Hesaplamanızda sabit düğümleri katlayarak ("sabit bölme") tensörlerin değerini statik olarak çıkarın.
  • Bir hesaplamanın bağımsız olan ve bunları iş parçacıkları veya aygıtlar arasında ayıran alt bölümlerini ayırın.
  • Yaygın alt ifadeleri ortadan kaldırarak aritmetik işlemleri basitleştirin.

Bunu ve diğer hızlandırmaları gerçekleştirmek için tam bir optimizasyon sistemi, Grappler var .

Kısacası, grafikler son derece kullanışlıdır ve TensorFlow'unuzun hızlı çalışmasına , paralel çalışmasına ve birden çok cihazda verimli bir şekilde çalışmasına izin verir .

Bununla birlikte, yine de kolaylık sağlamak için makine öğrenimi modellerimizi (veya diğer hesaplamaları) Python'da tanımlamak ve ardından ihtiyacınız olduğunda otomatik olarak grafikler oluşturmak istiyorsunuz.

Grafiklerden yararlanmak

Doğrudan arama veya dekoratör olarak tf.function kullanarak tf.function bir grafik oluşturup çalıştırırsınız. tf.function , girdi olarak normal bir işlevi alır ve bir Function döndürür. Bir Function , Python işlevinden TensorFlow grafikleri oluşturan bir Python çağrılabilirdir. Bir Function Python eşdeğeri ile aynı şekilde kullanırsınız.

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)

Dıştan bakıldığında, bir Function TensorFlow işlemlerini kullanarak yazdığınız normal bir işleve benziyor. Ancak altında durum çok farklı . Bir Function bir API'nin arkasında birkaç tf.Graph kapsüller. Bu, Function size hız ve konuşlandırılabilirlik gibi grafik yürütmenin faydalarını nasıl sağladığını gösterir .

tf.function bir işlev ve çağırdığı diğer tüm işlevler için geçerlidir:

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 kullandıysanız, hiçbir zaman bir Placeholder veya tf.Session tanımlamanız gerekmediğini fark tf.Session .

Python işlevlerini grafiğe dönüştürme

TensorFlow ile yazdığınız herhangi bir işlev, yerleşik TF işlemleri ile Python mantığının bir karışımını içerir; örneğin if-then cümleleri, döngüler, break , return , continue ve daha fazlası. TensorFlow işlemleri bir tf.Graph tarafından kolayca yakalanırken, Python'a özgü mantığın grafiğin bir parçası olabilmesi için fazladan bir adım atması gerekir. tf.function , Python kodunu grafik üreten koda dönüştürmek için AutoGraph ( tf.autograph ) adlı bir kitaplık kullanır.

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

Grafikleri doğrudan görüntülemeniz gerekmeyecek olsa da, kesin sonuçları görmek için çıktıları inceleyebilirsiniz. Bunların okunması kolay değil, bu yüzden çok dikkatli bakmaya gerek yok!

# 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"
    }
    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"
    }
    arg_attr {
      key: 0
      value {
        attr {
          key: "_output_shapes"
          value {
            list {
              shape {
              }
            }
          }
        }
      }
    }
  }
}
versions {
  producer: 561
  min_consumer: 12
}

Çoğu zaman, tf.function özel bir husus olmaksızın çalışacaktır. Bununla birlikte, bazı uyarılar vardır ve tf.function kılavuzu ve eksiksiz AutoGraph referansı burada yardımcı olabilir.

Çok biçimlilik: bir Function , birçok grafik

Bir tf.Graph , belirli bir girdi türüne (örneğin, belirli birdtype sahip tensörler veya aynı id() sahip nesneler)dtype .

dtypes değişkenlerinde yeni dtypes ve şekiller bulunan bir Function her çağırdığınızda, Function yeni argümanlar için yeni bir tf.Graph oluşturur. dtypes a ve şekiller tf.Graph bireyin girişlerin giriş imza ya da sadece bir imza olarak bilinir.

Function , bu imzaya karşılık gelen tf.Graph bir ConcreteFunction depolar. ConcreteFunction , tf.Graph etrafındaki bir tf.Graph .

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

# `my_relu` creates new graphs as it sees 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 bu imzayla zaten çağrılmışsa, Function yeni bir tf.Graph oluşturmaz.

# 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)

Birden çok grafikle desteklendiği için, Function polimorfiktir . Bu, tek bir tf.Graph temsil edebileceğinden daha fazla girdi türünü desteklemesini ve her bir tf.Graph daha iyi performans için optimize tf.Graph sağlar.

# 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)
  Args:
    x: float32 Tensor, shape=(2,)
  Returns:
    float32 Tensor, shape=(2,)

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

tf.function kullanma

Şimdiye kadar, bir Python işlevini bir dekoratör veya sarmalayıcı olarak tf.function işlevini kullanarak bir grafiğe nasıl dönüştürebileceğinizi gördünüz. Ancak pratikte, tf.function doğru çalışması için almak tf.function yanıltıcı olabilir! Aşağıdaki bölümlerde, tf.function ile tf.function beklendiği gibi çalışmasını nasıl sağlayabileceğinizi öğreneceksiniz.

Grafik yürütmeye karşı istekli yürütme

Bir Function kod hem hevesle hem de grafik olarak çalıştırılabilir. Varsayılan olarak, Function kodunu bir grafik olarak yürütür:

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

Function grafiğinin eşdeğer Python işlevi ile aynı hesaplamayı yaptığını doğrulamak için, tf.config.run_functions_eagerly(True) ile hevesle çalışmasını tf.config.run_functions_eagerly(True) . Bu, kodu normal şekilde yürütmek yerine, Function grafik oluşturma ve çalıştırma yeteneğini kapatan bir anahtardır.

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

Bununla birlikte, Function grafik ve istekli yürütme altında farklı davranabilir. Python print işlevi, bu iki modun nasıl farklılaştığına dair bir örnektir. Bakalım fonksiyonumuza bir print cümlesi ekleyip tekrar tekrar çağırdığınızda ne olacak.

@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)

Neyin yazdırıldığını gözlemleyin:

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

Çıktı şaşırtıcı mı? get_MSE üç kez çağrılmasına rağmen yalnızca bir kez yazdırılır.

Açıklamak gerekirse, print deyimi, "izleme" olarak bilinen bir işlemde grafiği oluşturmak için Function orijinal kodu çalıştırdığında çalıştırılır. İzleme, TensorFlow işlemlerini bir grafikte yakalar ve grafikte print yakalanmaz. Bu grafik daha sonra Python kodunu tekrar çalıştırmadan üç çağrı için de çalıştırılır .

Akıl sağlığı kontrolü olarak, aşağıdakileri karşılaştırmak için grafik yürütmeyi kapatalım:

# 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 bir Python yan etkisidir ve bir işlevi bir Function dönüştürürken bilmeniz gereken başka farklılıklar da vardır.

tf.function en iyi uygulamaları

Function davranışına alışmak biraz zaman alabilir. Hızlı bir başlangıç ​​yapmak için, ilk kez kullananlar, istekli bir durumdan grafik uygulamasına @tf.function konusunda deneyim @tf.function için @tf.function işleviyle oyuncak işlevlerini dekore etmelidir.

tf.function için tf.function , grafik uyumlu TensorFlow programları yazmak için en iyitf.function olabilir. İşte bazı ipuçları:

Hızlanmayı görmek

tf.function genellikle kodunuzun performansını artırır, ancak hızlanma miktarı çalıştırdığınız hesaplama türüne bağlıdır. Küçük hesaplamalara grafik çağırmanın ek yükü hakim olabilir. Performanstaki farkı şu şekilde ölçebilirsiniz:

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.777665522999996
power_as_graph = tf.function(power)
print("Graph execution:", timeit.timeit(lambda: power_as_graph(x, 100), number=1000))
Graph execution: 0.5308018169999968

tf.function Gördüğünüz gibi yaygın eğitim döngüler hızlandırmak için kullanılır Burada keras ile.

Performans ve ödünleşmeler

Grafikler kodunuzu hızlandırabilir, ancak bunları oluşturma sürecinin bazı ek yükleri vardır. Bazı işlevler için grafiğin oluşturulması, grafiğin yürütülmesinden daha fazla zaman alır. Bu yatırım, genellikle sonraki uygulamaların performans artışı ile hızlı bir şekilde geri ödenir, ancak herhangi bir büyük model eğitiminin ilk birkaç adımının izleme nedeniyle daha yavaş olabileceğinin farkında olmak önemlidir.

Modeliniz ne kadar büyük olursa olsun, sık sık takip etmekten kaçınmak istersiniz. tf.function kılavuzu, giriş özelliklerinin nasıl ayarlanacağını ve yeniden tf.function önlemek için tensör argümanlarının nasıl kullanılacağını tf.function . Alışılmadık derecede düşük performans aldığınızı fark ederseniz, kazayla izini sürüp takip etmediğinizi kontrol etmek iyi bir fikirdir.

Bir Function zaman izlenir?

Function ne zaman izlediğini anlamak için, koduna bir print cümlesi ekleyin. Genel bir kural olarak, Function her izlediğinde print deyimini çalıştıracaktır.

@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)

Burada ekstra izleme görüyorsunuz çünkü yeni Python argümanları her zaman yeni bir grafiğin oluşturulmasını tetikliyor.

Sonraki adımlar

Sen hem de daha derinlemesine tartışma okuyabilir tf.function API başvuru sayfası ve en rehber .