TensorFlow.org'da görüntüleyin | Google Colab'da çalıştırın | Kaynağı GitHub'da görüntüleyin | Not defterini indir |
genel bakış
Bu kılavuz, TensorFlow'un nasıl çalıştığını göstermek için TensorFlow ve Keras'ın yüzeyinin altına iner. Bunun yerine Keras'ı hemen kullanmaya başlamak istiyorsanız , Keras kılavuzları koleksiyonuna göz atın .
Bu kılavuzda, TensorFlow'un grafikler almak 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 öğreneceksiniz.
Bu, tf.function
hevesli yürütmeden grafik yürütmeye geçmenize nasıl izin verdiğini kapsayan büyük resmi bir genel bakıştır. tf.function ile ilgili daha eksiksiz bir belirtim için, tf.function
tf.function
gidin.
grafikler nedir?
Önceki üç kılavuzda, TensorFlow'u hevesle çalıştırdınız. Bu, TensorFlow işlemlerinin Python tarafından yürütüldüğü, operasyondan operasyona ve sonuçların Python'a geri döndürüldüğü anlamına gelir.
İstekli yürütmenin birkaç benzersiz avantajı olsa da, grafik yürütme Python dışında taşınabilirlik sağlar ve daha iyi performans sunma eğilimindedir. Grafik yürütme , tensör hesaplamalarının bazen bir tf.Graph
veya yalnızca bir "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.
İki katmanlı bir sinir ağını temsil eden bir TensorFlow grafiği, TensorBoard'da görselleştirildiğinde böyle görünür.
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, Python'dan dışa aktarırken kaydedilen modeller için format olarak grafikleri kullanır.
Grafikler de kolayca optimize edilerek derleyicinin aşağıdaki gibi dönüşümler yapmasına olanak tanır:
- Hesaplamanızdaki sabit düğümleri katlayarak ("sabit katlama") 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 bölen ayrı alt bölümleri.
- Ortak alt ifadeleri ortadan kaldırarak aritmetik işlemleri basitleştirin.
Bu ve diğer hızlandırmaları gerçekleştirmek için eksiksiz 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 çalışmasına izin verir.
Ancak yine de kolaylık sağlamak için makine öğrenimi modellerinizi (veya diğer hesaplamaları) Python'da tanımlamak ve ardından ihtiyacınız olduğunda otomatik olarak grafikler oluşturmak istiyorsunuz.
Kurmak
import tensorflow as tf
import timeit
from datetime import datetime
Grafiklerden yararlanma
Doğrudan çağrı veya dekoratör olarak tf.function kullanarak tf.function
bir grafik oluşturur ve çalıştırırsınız. tf.function
normal bir işlevi girdi olarak alır ve bir Function
döndürür. Function
, Python işlevinden TensorFlow grafikleri oluşturan bir Python çağrılabilir. Bir Function
Python eşdeğeriyle aynı şekilde kullanırsınız.
# 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ışarıdan bir Function
, TensorFlow işlemlerini kullanarak yazdığınız normal bir işleve benzer. Ancak alt tarafı çok farklı . Bir Function
, bir API'nin arkasında birkaç tf.Graph
s içerir . Function
, grafik yürütmenin hız ve konuşlandırılabilirlik gibi avantajlarını bu şekilde sağlayabilir.
tf.function
bir işleve ve çağırdığı diğer tüm işlevlere uygulanır:
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()
tutucu3 l10n-yerarray([[12.]], dtype=float32)
TensorFlow 1.x kullandıysanız, hiçbir zaman Placeholder
veya tf.Session
tanımlamanız gerekmediğini fark edeceksiniz.
Python fonksiyonlarını grafiklere dönüştürme
TensorFlow ile yazdığınız herhangi bir işlev, yerleşik TF işlemleri ile if-then
yan tümceleri, döngüler, break
, return
, continue
ve daha fazlası gibi Python mantığının bir karışımını içerecektir. 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ımdan geçmesi gerekir. tf.function
Python kodunu grafik oluşturan 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())
tutucu5 l10n-yerFirst branch, with graph: 1 Second branch, with graph: 0
Grafikleri doğrudan görüntülemeniz pek olası olmasa da, kesin sonuçları kontrol etmek için çıktıları inceleyebilirsiniz. Bunları okumak kolay değil, bu yüzden çok dikkatli bakmanıza 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 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)yer tutucu8 l10n-yer
# 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 } } } } 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 } } } } 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 } } } } 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 } } } } node_def { name: "cond/Identity" op: "Identity" input: "cond/Const_3:output:0" attr { key: "T" value { type: DT_BOOL } } } 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 } } } } node_def { name: "cond/Identity_1" op: "Identity" input: "cond/Const_4:output:0" attr { key: "T" value { type: DT_INT32 } } } 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 } } } } node_def { name: "cond/Identity" op: "Identity" input: "cond/Const:output:0" attr { key: "T" value { type: DT_BOOL } } } node_def { name: "cond/Identity_1" op: "Identity" input: "cond_identity_1_x" attr { key: "T" value { type: DT_INT32 } } } 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: 898 min_consumer: 12 }
Çoğu zaman, tf.function
özel hususlar olmadan çalışacaktır. Ancak, bazı uyarılar vardır ve tf.function kılavuzunun yanı sıra tam Otomatik Grafik referansı da burada yardımcı olabilir.
Polimorfizm: bir Function
, birçok grafik
Bir tf.Graph
, belirli bir girdi türü için özelleştirilir (örneğin, belirli bir dtype
sahip tensörler veya aynı id()
ile nesneler).
tf.Graph
değişkenlerinde yeni türler ve şekiller içeren bir Function
her çağırdığınızda, Function
yeni bağımsız değişkenler için yeni bir dtypes
oluşturur. Bir dtypes
girdilerinin tf.Graph
ve şekilleri, bir girdi imzası veya sadece bir imza olarak bilinir.
Function
, bu imzaya karşılık gelen tf.Graph
bir ConcreteFunction
içinde saklar. Bir ConcreteFunction
, bir 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 observes more signatures.
print(my_relu(tf.constant(5.5)))
print(my_relu([1, -1]))
print(my_relu(tf.constant([3., -3.])))
tutucu11 l10n-yertf.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ıldıysa, 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.])`.
tutucu13 l10n-yertf.Tensor(0.0, shape=(), dtype=float32) tf.Tensor([0. 1.], shape=(2,), dtype=float32)
Birden çok grafikle desteklendiğinden, bir 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 etmesini 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())
tutucu15 l10n-yermy_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
kullanma
Şimdiye kadar, bir dekoratör veya sarmalayıcı olarak tf.function
kullanarak bir Python fonksiyonunu bir grafiğe nasıl dönüştüreceğinizi öğrendiniz. Ancak pratikte, tf.function
işlevinin doğru şekilde çalışmasını sağlamak zor olabilir! Aşağıdaki bölümlerde, kodunuzu tf.function
ile beklendiği gibi nasıl çalıştırabileceğinizi öğreneceksiniz.
Grafik yürütme ve istekli yürütme
Bir Function
kod hem hevesle hem de grafik olarak yürütülebilir. 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 0 4 4 7], shape=(5,), dtype=int32) tf.Tensor([3 6 3 0 6], shape=(5,), dtype=int32)
get_MSE(y_true, y_pred)
<tf.Tensor: shape=(), dtype=int32, numpy=11>
Function
grafiğinizin eşdeğer Python işleviyle aynı hesaplamayı yaptığını doğrulamak için, tf.config.run_functions_eagerly(True)
ile hevesle çalışmasını sağlayabilirsiniz. Bu, İşlev'in kodu normal şekilde yürütmek yerine Function
oluşturma ve çalıştırma yeteneğini kapatan bir anahtardır.
tf.config.run_functions_eagerly(True)
get_MSE(y_true, y_pred)
yer tutucu23 l10n-yer<tf.Tensor: shape=(), dtype=int32, numpy=11>
# 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 bir örnektir. Fonksiyonunuza bir print
deyimi eklediğinizde ve onu tekrar tekrar çağırdığınızda ne olduğuna bakalım.
@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)
Ne bası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)
tutucu27 l10n-yerCalculating 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 için, print
ifadesi, "tracing" olarak bilinen bir işlemde grafiği oluşturmak için Function
orijinal kodu çalıştırdığında yürütülür. İzleme, TensorFlow işlemlerini bir grafikte yakalar ve print
grafikte yakalanmaz. Bu grafik daha sonra Python kodunu tekrar çalıştırmadan üç çağrının tümü için yürütülür.
Akıl sağlığı kontrolü olarak, 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)
yer tutucu30 l10n-yerCalculating MSE! Calculating MSE! Calculating MSE!
tf.config.run_functions_eagerly(False)
print
bir Python yan etkisidir ve bir Function
bir İşleve dönüştürürken bilmeniz gereken başka farklılıklar da vardır. tf ile daha iyi performans kılavuzunun Sınırlamalar bölümünde daha fazla bilgi edinin.
katı olmayan yürütme
Grafik yürütme, yalnızca aşağıdakileri içeren gözlemlenebilir etkileri üretmek için gerekli işlemleri yürütür:
- Fonksiyonun dönüş değeri
- Aşağıdakiler gibi belgelenmiş iyi bilinen yan etkiler:
-
tf.print
gibi giriş/çıkış işlemleri -
tf.debugging
assert işlevleri gibi hata ayıklama işlemleri -
tf.Variable
mutasyonları
-
Bu davranış genellikle "Kesin olmayan yürütme" olarak bilinir ve gerekli olsun veya olmasın tüm program işlemlerinde adım adım ilerleyen istekli yürütmeden farklıdır.
Özellikle, çalışma zamanı hata denetimi, gözlemlenebilir bir etki olarak sayılmaz. Bir işlem gereksiz olduğu için atlanırsa, herhangi bir çalışma zamanı hatası oluşturamaz.
Aşağıdaki örnekte, grafik yürütme sırasında "gereksiz" tf.gather
işlemi atlanır, bu nedenle çalışma zamanı hatası InvalidArgumentError
, istekli yürütmede olacağı için ortaya çıkmaz. Bir grafiği yürütürken ortaya çıkan bir hataya güvenmeyin.
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)yer tutucu34 l10n-yer
@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
en iyi uygulamaları
Function
davranışına alışmak biraz zaman alabilir. Hızlı bir şekilde başlamak için, ilk kez kullananlar, hevesliden grafik yürütmeye geçme konusunda deneyim kazanmak için @tf.function
ile oyuncak fonksiyonlarını süslemelidir.
tf.function
için tasarım yapmak , grafik uyumlu TensorFlow programları yazmak için en iyi seçeneğiniz olabilir. İşte bazı ipuçları:
-
tf.config.run_functions_eagerly
ile istekli ve grafik yürütme arasında erken ve sıklıkla geçiş yapın ve iki modun birbirinden ayrılıp ayrılmadığını/ne zaman ayrıldığını tam olarak belirleyin. - Python işlevinin dışında
tf.Variable
s oluşturun ve bunları içeride değiştirin.tf.Variable
, keras.layers,keras.Model
s vetf.optimizers
gibikeras.layers
kullanan nesneler için de geçerlidir. -
tf.Variable
s ve Keras nesneleri hariç , dış Python değişkenlerine bağlı işlevler yazmaktan kaçının. - Girdi olarak tensörleri ve diğer TensorFlow türlerini alan fonksiyonlar yazmayı tercih edin. Diğer nesne türlerini de geçebilirsin ama dikkatli ol !
- Performans kazancını en üst düzeye çıkarmak için bir
tf.function
. işlevi altında mümkün olduğunca fazla hesaplama ekleyin. Örneğin, tüm eğitim adımını veya tüm eğitim döngüsünü süsleyin.
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 hesaplamalar, bir grafiği çağırmanın ek yükü tarafından domine edilebilir. Performans farkını ş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: 2.5637862179974036
power_as_graph = tf.function(power)
print("Graph execution:", timeit.timeit(lambda: power_as_graph(x, 100), number=1000))
Graph execution: 0.6832536700021592
tf.function
genellikle eğitim döngülerini hızlandırmak için kullanılır ve bununla ilgili daha fazla bilgiyi Keras ile sıfırdan eğitim döngüsü yazma bölümünde bulabilirsiniz.
Performans ve takaslar
Grafikler kodunuzu hızlandırabilir, ancak bunları oluşturma sürecinin biraz yükü 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 yürütmelerin performans artışıyla 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ğini bilmek ö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 geri izlemeyi önlemek için tensör bağımsız değişkenlerinin nasıl kullanılacağını açıklar. Alışılmadık derecede düşük performans aldığınızı fark ederseniz, yanlışlıkla geri dönüp bakmadığınızı kontrol etmek iyi bir fikirdir.
Bir Function
izleme ne zaman yapılır?
Function
ne zaman izleme yaptığını anlamak için koduna bir print
deyimi ekleyin. Temel bir kural olarak, Function
, her izlediğinde print
deyimini yürütü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)yer tutucu43 l10n-yer
# 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)
Yeni Python argümanları her zaman yeni bir grafiğin oluşturulmasını tetikler, dolayısıyla ekstra izleme.
Sonraki adımlar
API referans sayfasından ve tf.function
ile daha iyi performans kılavuzunu izleyerek tf.function
hakkında daha fazla bilgi edinebilirsiniz.