TensorFlow.org'da görüntüleyin | Google Colab'da çalıştırın | Kaynağı GitHub'da görüntüleyin | Not defterini indir |
TensorFlow 2'de istekli yürütme varsayılan olarak açıktır. Kullanıcı arayüzü sezgisel ve esnektir (tek seferlik işlemleri yürütmek çok daha kolay ve hızlıdır), ancak bu performans ve konuşlandırılabilirlik pahasına olabilir.
Programlarınızdan grafikler oluşturmak için tf.function
işlevini kullanabilirsiniz. Python kodunuzdan Python'dan bağımsız veri akışı grafikleri oluşturan bir dönüştürme aracıdır. Bu, performanslı ve taşınabilir modeller oluşturmanıza yardımcı olur ve SavedModel
kullanılması gerekir.
Bu kılavuz, etkin bir şekilde kullanabilmeniz için tf.function
kaputun altında nasıl çalıştığını kavramsallaştırmanıza yardımcı olacaktır.
Başlıca çıkarımlar ve öneriler şunlardır:
- İstekli modda hata ayıklayın, ardından
@tf.function
ile süsleyin. - Nesne mutasyonu veya liste ekleme gibi Python yan etkilerine güvenmeyin.
-
tf.function
en iyi TensorFlow operasyonlarında çalışır; NumPy ve Python çağrıları sabitlere dönüştürülür.
Kurmak
import tensorflow as tf
Karşılaşabileceğiniz hata türlerini göstermek için bir yardımcı işlev tanımlayın:
import traceback
import contextlib
# Some helper code to demonstrate the kinds of errors you might encounter.
@contextlib.contextmanager
def assert_raises(error_class):
try:
yield
except error_class as e:
print('Caught expected exception \n {}:'.format(error_class))
traceback.print_exc(limit=2)
except Exception as e:
raise e
else:
raise Exception('Expected {} to be raised but no error was raised!'.format(
error_class))
temel bilgiler
kullanım
Tanımladığınız bir Function
(örneğin @tf.function
dekoratörünü uygulayarak) tıpkı bir çekirdek TensorFlow işlemi gibidir: Onu hevesle çalıştırabilirsiniz; gradyanları hesaplayabilirsiniz; ve benzeri.
@tf.function # The decorator converts `add` into a `Function`.
def add(a, b):
return a + b
add(tf.ones([2, 2]), tf.ones([2, 2])) # [[2., 2.], [2., 2.]]
<tf.Tensor: shape=(2, 2), dtype=float32, numpy= array([[2., 2.], [2., 2.]], dtype=float32)>yer tutucu4 l10n-yer
v = tf.Variable(1.0)
with tf.GradientTape() as tape:
result = add(v, 1.0)
tape.gradient(result, v)
<tf.Tensor: shape=(), dtype=float32, numpy=1.0>
Function
Function
içinde kullanabilirsiniz.
@tf.function
def dense_layer(x, w, b):
return add(tf.matmul(x, w), b)
dense_layer(tf.ones([3, 2]), tf.ones([2, 2]), tf.ones([2]))
tutucu7 l10n-yer<tf.Tensor: shape=(3, 2), dtype=float32, numpy= array([[3., 3.], [3., 3.], [3., 3.]], dtype=float32)>
Function
s, özellikle birçok küçük işlem içeren grafikler için istekli koddan daha hızlı olabilir. Ancak birkaç pahalı işlem içeren grafikler için (kıvrımlar gibi), çok fazla hızlanma görmeyebilirsiniz.
import timeit
conv_layer = tf.keras.layers.Conv2D(100, 3)
@tf.function
def conv_fn(image):
return conv_layer(image)
image = tf.zeros([1, 200, 200, 100])
# Warm up
conv_layer(image); conv_fn(image)
print("Eager conv:", timeit.timeit(lambda: conv_layer(image), number=10))
print("Function conv:", timeit.timeit(lambda: conv_fn(image), number=10))
print("Note how there's not much difference in performance for convolutions")
tutucu9 l10n-yerEager conv: 0.006058974999177735 Function conv: 0.005791576000774512 Note how there's not much difference in performance for convolutions
İzleme
Bu bölüm , gelecekte değişebilecek uygulama ayrıntıları da dahil olmak üzere, Function
başlık altında nasıl çalıştığını ortaya koymaktadır. Ancak, izlemenin neden ve ne zaman gerçekleştiğini anladıktan sonra, tf.function
etkili bir şekilde kullanmak çok daha kolay!
"İzlemek" nedir?
Bir Function
, programınızı bir TensorFlow Graph'ta çalıştırır. Ancak, bir tf.Graph
, hevesli bir TensorFlow programında yazacağınız her şeyi temsil edemez. Örneğin, Python polimorfizmi destekler, ancak tf.Graph
, girdilerinin belirli bir veri tipine ve boyutuna sahip olmasını gerektirir. Veya komut satırı argümanlarını okumak, bir hatayı yükseltmek veya daha karmaşık bir Python nesnesi ile çalışmak gibi yan görevler gerçekleştirebilirsiniz; bunların hiçbiri bir tf.Graph
içinde çalıştırılamaz.
Function
, kodunuzu iki aşamada ayırarak bu boşluğu doldurur:
1) " Tracing " olarak adlandırılan ilk aşamada, Function
yeni bir tf.Graph
oluşturur. Python kodu normal çalışır, ancak tüm TensorFlow işlemleri (iki Tensör eklemek gibi) ertelenir : bunlar tf.Graph
tarafından yakalanır ve çalıştırılmaz.
2) İkinci aşamada, ilk aşamada ertelenen her şeyi içeren bir tf.Graph
çalıştırılır. Bu aşama, izleme aşamasından çok daha hızlıdır.
Girişlerine bağlı olarak, Function
çağrıldığında her zaman ilk aşamayı çalıştırmaz. Bu belirlemeyi nasıl yaptığını daha iyi anlamak için aşağıdaki "İzleme kuralları"na bakın. İlk aşamayı atlamak ve yalnızca ikinci aşamayı yürütmek size TensorFlow'un yüksek performansını verir.
Function
izlemeye karar verdiğinde, izleme aşamasını hemen ikinci aşama izler, bu nedenle Function
çağırmak tf.Graph
hem oluşturur hem de çalıştırır. Daha sonra get_concrete_function
ile sadece izleme aşamasını nasıl çalıştırabileceğinizi göreceksiniz.
Bir Function
içine farklı türdeki argümanları ilettiğinizde, her iki aşama da çalıştırılır:
@tf.function
def double(a):
print("Tracing with", a)
return a + a
print(double(tf.constant(1)))
print()
print(double(tf.constant(1.1)))
print()
print(double(tf.constant("a")))
print()
tutucu11 l10n-yerTracing with Tensor("a:0", shape=(), dtype=int32) tf.Tensor(2, shape=(), dtype=int32) Tracing with Tensor("a:0", shape=(), dtype=float32) tf.Tensor(2.2, shape=(), dtype=float32) Tracing with Tensor("a:0", shape=(), dtype=string) tf.Tensor(b'aa', shape=(), dtype=string)
Aynı argüman tipine sahip bir Function
tekrar tekrar çağırırsanız, oluşturulan grafik aynı olacağından TensorFlow'un izleme aşamasını atlayacağını ve önceden izlenen bir grafiği yeniden kullanacağını unutmayın.
# This doesn't print 'Tracing with ...'
print(double(tf.constant("b")))
tutucu13 l10n-yertf.Tensor(b'bb', shape=(), dtype=string)
Mevcut tüm izleri görmek için pretty_printed_concrete_signatures()
kullanabilirsiniz:
print(double.pretty_printed_concrete_signatures())
tutucu15 l10n-yerdouble(a) Args: a: int32 Tensor, shape=() Returns: int32 Tensor, shape=() double(a) Args: a: float32 Tensor, shape=() Returns: float32 Tensor, shape=() double(a) Args: a: string Tensor, shape=() Returns: string Tensor, shape=()
Şimdiye kadar, tf.function işlevinin tf.function
grafik izleme mantığı üzerinde önbelleğe alınmış, dinamik bir gönderme katmanı oluşturduğunu gördünüz. Terminoloji hakkında daha spesifik olmak gerekirse:
- Bir
tf.Graph
, bir TensorFlow hesaplamasının ham, dilden bağımsız, taşınabilir temsilidir. - Bir
ConcreteFunction
, birtf.Graph
sarar. - Bir
Function
,ConcreteFunction
s önbelleğini yönetir ve girdileriniz için doğru olanı seçer. -
tf.function
Bir Python işlevini sarar ve birFunction
nesnesi döndürür. - İzleme , bir
tf.Graph
oluşturur ve onu iz olarak da bilinen birConcreteFunction
'a sarar.
izleme kuralları
Bir Function
, bir girdinin argümanlarından ve kwarg'larından bir önbellek anahtarı hesaplayarak izlenen bir ConcreteFunction
yeniden kullanılıp kullanılmayacağını belirler. Önbellek anahtarı , aşağıdaki kurallara (değişebilir) göre, Function
çağrısının giriş argümanlarına ve ConcreteFunction
dayalı olarak bir SomutFonksiyon tanımlayan bir anahtardır:
- Bir
tf.Tensor
için oluşturulan anahtar, şekli ve tipidir. - Bir
tf.Variable
için oluşturulan anahtar, benzersiz bir değişken kimliğidir. - Bir Python ilkel öğesi (
int
,float
,str
gibi) için oluşturulan anahtar, değeridir. - Yuvalanmış
dict
s,list
s,tuple
s,namedtuple
s veattr
s için oluşturulan anahtar, yaprak anahtarların düzleştirilmiş demetidir (bkz.nest.flatten
). (Bu düzleştirmenin bir sonucu olarak, izleme sırasında kullanılandan farklı bir yuvalama yapısına sahip somut bir işlevi çağırmak TypeError ile sonuçlanacaktır). - Diğer tüm Python türleri için anahtar, nesneye özeldir. Bu şekilde bir işlev veya yöntem, çağrıldığı her örnek için bağımsız olarak izlenir.
Geri izlemeyi kontrol etme
Function
birden fazla iz oluşturduğu geri izleme, TensorFlow'un her giriş kümesi için doğru grafikler oluşturmasını sağlamaya yardımcı olur. Ancak, izleme pahalı bir işlemdir! Function
her arama için yeni bir grafiğin izini sürerse, kodunuzun tf.function
kullanmadığınıza göre daha yavaş yürütüldüğünü göreceksiniz.
İzleme davranışını kontrol etmek için aşağıdaki teknikleri kullanabilirsiniz:
- İzlemeyi sınırlamak için
input_signature
içindetf.function
belirtin.
@tf.function(input_signature=(tf.TensorSpec(shape=[None], dtype=tf.int32),))
def next_collatz(x):
print("Tracing with", x)
return tf.where(x % 2 == 0, x // 2, 3 * x + 1)
print(next_collatz(tf.constant([1, 2])))
# You specified a 1-D tensor in the input signature, so this should fail.
with assert_raises(ValueError):
next_collatz(tf.constant([[1, 2], [3, 4]]))
# You specified an int32 dtype in the input signature, so this should fail.
with assert_raises(ValueError):
next_collatz(tf.constant([1.0, 2.0]))
tutucu17 l10n-yerTracing with Tensor("x:0", shape=(None,), dtype=int32) tf.Tensor([4 1], shape=(2,), dtype=int32) Caught expected exception <class 'ValueError'>: Caught expected exception <class 'ValueError'>: Traceback (most recent call last): File "/tmp/ipykernel_26244/3551158538.py", line 8, in assert_raises yield File "/tmp/ipykernel_26244/1851403433.py", line 9, in <module> next_collatz(tf.constant([[1, 2], [3, 4]])) ValueError: Python inputs incompatible with input_signature: inputs: ( tf.Tensor( [[1 2] [3 4]], shape=(2, 2), dtype=int32)) input_signature: ( TensorSpec(shape=(None,), dtype=tf.int32, name=None)). Traceback (most recent call last): File "/tmp/ipykernel_26244/3551158538.py", line 8, in assert_raises yield File "/tmp/ipykernel_26244/1851403433.py", line 13, in <module> next_collatz(tf.constant([1.0, 2.0])) ValueError: Python inputs incompatible with input_signature: inputs: ( tf.Tensor([1. 2.], shape=(2,), dtype=float32)) input_signature: ( TensorSpec(shape=(None,), dtype=tf.int32, name=None)).
İzleme yeniden kullanımında esnekliğe izin vermek için
tf.TensorSpec
bir [Yok] boyutu belirtin.TensorFlow, tensörleri şekillerine göre eşleştirdiğinden, joker karakter olarak
None
boyutunun kullanılması,Function
s öğesinin değişken boyutlu girdiler için izleri yeniden kullanmasına olanak tanır. Farklı uzunluktaki dizileriniz veya her grup için farklı boyutlardaki resimleriniz varsa, değişken boyutlu girdiler oluşabilir (örneğin, Transformer ve Deep Dream eğitimlerine bakın).
@tf.function(input_signature=(tf.TensorSpec(shape=[None], dtype=tf.int32),))
def g(x):
print('Tracing with', x)
return x
# No retrace!
print(g(tf.constant([1, 2, 3])))
print(g(tf.constant([1, 2, 3, 4, 5])))
tutucu19 l10n-yerTracing with Tensor("x:0", shape=(None,), dtype=int32) tf.Tensor([1 2 3], shape=(3,), dtype=int32) tf.Tensor([1 2 3 4 5], shape=(5,), dtype=int32)
Geri izlemeyi azaltmak için Python bağımsız değişkenlerini Tensörlere yayınlayın.
Genellikle, Python bağımsız değişkenleri hiperparametreleri ve grafik yapılarını kontrol etmek için kullanılır - örneğin,
num_layers=10
veyatraining=True
veyanonlinearity='relu'
. Bu nedenle, Python argümanı değişirse, grafiği tekrar izlemeniz mantıklı olur.Ancak, grafik yapısını kontrol etmek için bir Python argümanının kullanılmaması mümkündür. Bu durumlarda, Python değerindeki bir değişiklik gereksiz yere yeniden izlemeyi tetikleyebilir. Örneğin, AutoGraph'ın dinamik olarak açacağı bu eğitim döngüsünü ele alalım. Birden çok izlemeye rağmen, oluşturulan grafik aslında aynıdır, bu nedenle yeniden izleme gereksizdir.
def train_one_step():
pass
@tf.function
def train(num_steps):
print("Tracing with num_steps = ", num_steps)
tf.print("Executing with num_steps = ", num_steps)
for _ in tf.range(num_steps):
train_one_step()
print("Retracing occurs for different Python arguments.")
train(num_steps=10)
train(num_steps=20)
print()
print("Traces are reused for Tensor arguments.")
train(num_steps=tf.constant(10))
train(num_steps=tf.constant(20))
tutucu21 l10n-yerRetracing occurs for different Python arguments. Tracing with num_steps = 10 Executing with num_steps = 10 Tracing with num_steps = 20 Executing with num_steps = 20 Traces are reused for Tensor arguments. Tracing with num_steps = Tensor("num_steps:0", shape=(), dtype=int32) Executing with num_steps = 10 Executing with num_steps = 20
Geri izlemeyi zorlamanız gerekirse, yeni bir Function
oluşturun. Separate Function
nesnelerinin izleri paylaşmamaları garanti edilir.
def f():
print('Tracing!')
tf.print('Executing')
tf.function(f)()
tf.function(f)()
tutucu23 l10n-yerTracing! Executing Tracing! Executing
Somut fonksiyonların elde edilmesi
Her fonksiyon izlendiğinde, yeni bir somut fonksiyon yaratılır. get_concrete_function
kullanarak doğrudan somut bir işlev elde edebilirsiniz.
print("Obtaining concrete trace")
double_strings = double.get_concrete_function(tf.constant("a"))
print("Executing traced function")
print(double_strings(tf.constant("a")))
print(double_strings(a=tf.constant("b")))
Obtaining concrete trace Executing traced function tf.Tensor(b'aa', shape=(), dtype=string) tf.Tensor(b'bb', shape=(), dtype=string)yer tutucu26 l10n-yer
# You can also call get_concrete_function on an InputSpec
double_strings_from_inputspec = double.get_concrete_function(tf.TensorSpec(shape=[], dtype=tf.string))
print(double_strings_from_inputspec(tf.constant("c")))
tf.Tensor(b'cc', shape=(), dtype=string)
Bir ConcreteFunction
yazdırmak, girdi bağımsız değişkenlerinin (türlerle birlikte) ve çıktı türünün bir özetini görüntüler.
print(double_strings)
tutucu29 l10n-yerConcreteFunction double(a) Args: a: string Tensor, shape=() Returns: string Tensor, shape=()
Ayrıca, somut bir işlevin imzasını doğrudan alabilirsiniz.
print(double_strings.structured_input_signature)
print(double_strings.structured_outputs)
tutucu31 l10n-yer((TensorSpec(shape=(), dtype=tf.string, name='a'),), {}) Tensor("Identity:0", shape=(), dtype=string)
Uyumsuz türlerle somut bir iz kullanmak hata verir
with assert_raises(tf.errors.InvalidArgumentError):
double_strings(tf.constant(1))
tutucu33 l10n-yerCaught expected exception <class 'tensorflow.python.framework.errors_impl.InvalidArgumentError'>: Traceback (most recent call last): File "/tmp/ipykernel_26244/3551158538.py", line 8, in assert_raises yield File "/tmp/ipykernel_26244/3196284684.py", line 2, in <module> double_strings(tf.constant(1)) tensorflow.python.framework.errors_impl.InvalidArgumentError: cannot compute __inference_double_162 as input #0(zero-based) was expected to be a string tensor but is a int32 tensor [Op:__inference_double_162]
Somut bir işlevin giriş imzasında Python argümanlarına özel muamele yapıldığını fark edebilirsiniz. TensorFlow 2.3'ten önce, Python argümanları somut fonksiyonun imzasından basitçe kaldırıldı. TensorFlow 2.3 ile başlayarak, Python bağımsız değişkenleri imzada kalır, ancak izleme sırasında ayarlanan değeri almakla sınırlandırılır.
@tf.function
def pow(a, b):
return a ** b
square = pow.get_concrete_function(a=tf.TensorSpec(None, tf.float32), b=2)
print(square)
ConcreteFunction pow(a, b=2) Args: a: float32 Tensor, shape=<unknown> Returns: float32 Tensor, shape=<unknown>yer tutucu36 l10n-yer
assert square(tf.constant(10.0)) == 100
with assert_raises(TypeError):
square(tf.constant(10.0), b=3)
Caught expected exception <class 'TypeError'>: Traceback (most recent call last): File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/function.py", line 1721, in _call_impl cancellation_manager) File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/function.py", line 1765, in _call_with_flat_signature raise TypeError(f"{self._flat_signature_summary()} got unexpected " TypeError: pow(a) got unexpected keyword arguments: b. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/tmp/ipykernel_26244/3551158538.py", line 8, in assert_raises yield File "/tmp/ipykernel_26244/2310937119.py", line 4, in <module> square(tf.constant(10.0), b=3) TypeError: ConcreteFunction pow(a, b) was constructed with int value 2 in b, but was called with int value 3.
Grafiklerin elde edilmesi
Her somut işlev, bir tf.Graph
çevresinde çağrılabilir bir sarmalayıcıdır. Gerçek tf.Graph
nesnesini almak normalde yapmanız gereken bir şey olmasa da, herhangi bir somut işlevden kolayca elde edebilirsiniz.
graph = double_strings.graph
for node in graph.as_graph_def().node:
print(f'{node.input} -> {node.name}')
tutucu39 l10n-yer[] -> a ['a', 'a'] -> add ['add'] -> Identity
hata ayıklama
Genel olarak, hevesli modda kodun hata ayıklaması, tf.function
içindekinden daha kolaydır. tf.function
ile süslemeden önce kodunuzun istekli modda hatasız yürütülmesini sağlamalısınız. Hata ayıklama sürecine yardımcı olmak için, tf.function öğesini genel olarak devre dışı bırakmak ve yeniden etkinleştirmek için tf.function
tf.config.run_functions_eagerly(True)
öğesini çağırabilirsiniz.
Yalnızca tf.function
içinde görünen sorunları takip ederken, işte bazı ipuçları:
- Düz eski Python
print
çağrıları yalnızca izleme sırasında yürütülür ve işleviniz (yeniden) izlendiğinde izlemenize yardımcı olur. -
tf.print
çağrıları her seferinde yürütülür ve yürütme sırasında ara değerleri izlemenize yardımcı olabilir. -
tf.debugging.enable_check_numerics
, NaN'lerin ve Inf'nin nerede oluşturulduğunu izlemenin kolay bir yoludur. -
pdb
( Python hata ayıklayıcı ), izleme sırasında neler olduğunu anlamanıza yardımcı olabilir. (Uyarı:pdb
sizi AutoGraph ile dönüştürülmüş kaynak koduna bırakacaktır.)
Otomatik Grafik dönüşümleri
AutoGraph, tf.function
varsayılan olarak açık olan ve Python istekli kodunun bir alt kümesini grafik uyumlu TensorFlow işlemlerine dönüştüren bir kitaplıktır. Bu, if
, for
, while
gibi kontrol akışını içerir.
tf.cond ve tf.while_loop
gibi tf.cond
operasyonları çalışmaya devam eder, ancak Python'da yazıldığında kontrol akışını yazmak ve anlamak genellikle daha kolaydır.
# A simple loop
@tf.function
def f(x):
while tf.reduce_sum(x) > 1:
tf.print(x)
x = tf.tanh(x)
return x
f(tf.random.uniform([5]))
tutucu41 l10n-yer[0.666458249 0.713946581 0.723879576 0.330758929 0.184087753] [0.582645297 0.613145649 0.619306684 0.319202513 0.182036072] [0.524585426 0.546337605 0.550645113 0.308785647 0.18005164] [0.481231302 0.497770309 0.501003504 0.299331933 0.178130865] [0.447229207 0.460361809 0.462906033 0.290701121 0.176270396] [0.419618756 0.430379033 0.432449728 0.282779962 0.174467146] [0.396609187 0.405638 0.407366514 0.275476 0.172718227] [0.377043903 0.384762734 0.386234313 0.268712848 0.17102097] [0.360137492 0.366836458 0.368109286 0.262426734 0.169372901] [0.345335096 0.351221472 0.352336824 0.256563932 0.167771652] [0.332231969 0.337458342 0.338446289 0.251078814 0.166215062] [0.320524871 0.325206399 0.326089561 0.24593246 0.164701089] [0.309981436 0.314206958 0.31500268 0.241091311 0.163227797] [0.300420195 0.304259449 0.304981351 0.236526251 0.161793426] [0.291697085 0.295205742 0.295864582 0.232211992 0.160396278] [0.283696055 0.286919087 0.287523568 0.228126258 0.159034774] [0.276322395 0.279296666 0.27985391 0.224249557 0.157707423] [0.269497961 0.272254 0.272769839 0.220564634 0.15641281] [0.263157606 0.265720904 0.266200244 0.21705614 0.155149609] [0.257246554 0.259638608 0.260085613 0.213710397 0.153916568] [0.251718313 0.25395745 0.254375577 0.210515186 0.152712509] [0.246533215 0.248635098 0.249027327 0.207459539 0.151536316] [0.241657034 0.243635193 0.244004101 0.204533577 0.15038693] [0.237060249 0.238926381 0.239274174 0.201728329 0.149263337] [0.232717097 0.234481394 0.234810054 0.199035719 0.148164615] [0.228605017 0.230276451 0.230587661 0.196448416 0.147089839] [0.224704206 0.226290658 0.22658591 0.193959698 0.14603813] [0.220997125 0.222505584 0.222786173 0.191563457 0.145008713] <tf.Tensor: shape=(5,), dtype=float32, numpy= array([0.21746822, 0.21890487, 0.21917202, 0.18925412, 0.14400077], dtype=float32)>
Merak ediyorsanız, imzanın oluşturduğu kodu inceleyebilirsiniz.
print(tf.autograph.to_code(f.python_function))
tutucu43 l10n-yerdef tf__f(x): with ag__.FunctionScope('f', 'fscope', ag__.ConversionOptions(recursive=True, user_requested=True, optional_features=(), internal_convert_user_code=True)) as fscope: do_return = False retval_ = ag__.UndefinedReturnValue() def get_state(): return (x,) def set_state(vars_): nonlocal x (x,) = vars_ def loop_body(): nonlocal x ag__.converted_call(ag__.ld(tf).print, (ag__.ld(x),), None, fscope) x = ag__.converted_call(ag__.ld(tf).tanh, (ag__.ld(x),), None, fscope) def loop_test(): return (ag__.converted_call(ag__.ld(tf).reduce_sum, (ag__.ld(x),), None, fscope) > 1) ag__.while_stmt(loop_test, loop_body, get_state, set_state, ('x',), {}) try: do_return = True retval_ = ag__.ld(x) except: do_return = False raise return fscope.ret(retval_, do_return)
Şartlılar
AutoGraph, bazı if <condition>
ifadelerini eşdeğer tf.cond
çağrılarına dönüştürür. Bu değiştirme, <condition>
bir Tensör ise yapılır. Aksi takdirde, if
ifadesi Python koşullu olarak yürütülür.
İzleme sırasında bir Python koşulu yürütülür, bu nedenle koşulun tam olarak bir dalı grafiğe eklenir. AutoGraph olmadan, veriye bağlı kontrol akışı varsa, bu izlenen grafik alternatif dalı alamaz.
tf.cond
, yürütme zamanında dinamik olarak bir dal seçerek koşulun her iki dalını da izler ve grafiğe ekler. İzlemenin istenmeyen yan etkileri olabilir; Daha fazla bilgi için AutoGraph izleme efektlerine bakın.
@tf.function
def fizzbuzz(n):
for i in tf.range(1, n + 1):
print('Tracing for loop')
if i % 15 == 0:
print('Tracing fizzbuzz branch')
tf.print('fizzbuzz')
elif i % 3 == 0:
print('Tracing fizz branch')
tf.print('fizz')
elif i % 5 == 0:
print('Tracing buzz branch')
tf.print('buzz')
else:
print('Tracing default branch')
tf.print(i)
fizzbuzz(tf.constant(5))
fizzbuzz(tf.constant(20))
tutucu45 l10n-yerTracing for loop Tracing fizzbuzz branch Tracing fizz branch Tracing buzz branch Tracing default branch 1 2 fizz 4 buzz 1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz 16 17 fizz 19 buzz
AutoGraph ile dönüştürülmüş if ifadeleriyle ilgili ek kısıtlamalar için başvuru belgelerine bakın.
döngüler
AutoGraph, bazı for
ve while
ifadelerini tf.while_loop gibi eşdeğer tf.while_loop
döngü işlemlerine dönüştürür. Dönüştürülmezse, for
veya while
döngüsü bir Python döngüsü olarak yürütülür.
Bu ikame aşağıdaki durumlarda yapılır:
- y'deki
for x in y
:y
bir Tensör ise,tf.while_loop
dönüştürün.y
birtf.data.Dataset
olduğu özel durumda,tf.data.Dataset
işlemlerinin bir kombinasyonu oluşturulur. -
while <condition>
:<condition>
bir Tensör ise,tf.while_loop
dönüştürün.
İzleme sırasında bir Python döngüsü yürütülür ve döngünün her yinelemesi için tf.Graph
ek işlemler eklenir.
Bir TensorFlow döngüsü, döngünün gövdesini izler ve yürütme zamanında kaç yinelemenin çalıştırılacağını dinamik olarak seçer. Döngü gövdesi, oluşturulan tf.Graph
yalnızca bir kez görünür.
AutoGraph ile dönüştürülmüş for
ve while
ifadelerine ilişkin ek kısıtlamalar için başvuru belgelerine bakın.
Python verileri üzerinde döngü
Yaygın bir tuzak, bir tf.function
içindeki Python/NumPy verileri üzerinde döngü oluşturmaktır. Bu döngü, izleme işlemi sırasında yürütülecek ve döngünün her yinelemesi için modelinizin bir kopyasını tf.Graph
.
Tüm eğitim döngüsünü tf.function
içine sarmak istiyorsanız, bunu yapmanın en güvenli yolu, AutoGraph'ın eğitim döngüsünü dinamik olarak açması için verilerinizi bir tf.data.Dataset
olarak sarmaktır.
def measure_graph_size(f, *args):
g = f.get_concrete_function(*args).graph
print("{}({}) contains {} nodes in its graph".format(
f.__name__, ', '.join(map(str, args)), len(g.as_graph_def().node)))
@tf.function
def train(dataset):
loss = tf.constant(0)
for x, y in dataset:
loss += tf.abs(y - x) # Some dummy computation.
return loss
small_data = [(1, 1)] * 3
big_data = [(1, 1)] * 10
measure_graph_size(train, small_data)
measure_graph_size(train, big_data)
measure_graph_size(train, tf.data.Dataset.from_generator(
lambda: small_data, (tf.int32, tf.int32)))
measure_graph_size(train, tf.data.Dataset.from_generator(
lambda: big_data, (tf.int32, tf.int32)))
tutucu47 l10n-yertrain([(1, 1), (1, 1), (1, 1)]) contains 11 nodes in its graph train([(1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)]) contains 32 nodes in its graph train(<FlatMapDataset shapes: (<unknown>, <unknown>), types: (tf.int32, tf.int32)>) contains 6 nodes in its graph train(<FlatMapDataset shapes: (<unknown>, <unknown>), types: (tf.int32, tf.int32)>) contains 6 nodes in its graph
Python/NumPy verilerini bir Veri Kümesine sararken, tf.data.Dataset.from_generator
ile tf.data.Dataset.from_tensors
arasında dikkatli olun. İlki, verileri Python'da tutacak ve performans etkileri olabilecek tf.py_function
aracılığıyla getirecek, ikincisi ise verilerin bir kopyasını grafikte bellek etkileri olabilecek büyük bir tf.constant()
düğümü olarak paketleyecektir.
Dosyalardan TFRecordDataset
, CsvDataset
vb. aracılığıyla veri okumak, veri tüketmenin en etkili yoludur, çünkü bu durumda TensorFlow, Python'u dahil etmek zorunda kalmadan verilerin eşzamansız yüklenmesini ve önceden getirilmesini yönetebilir. Daha fazla bilgi edinmek için tf.data
: TensorFlow giriş işlem hatları oluşturma kılavuzuna bakın.
Bir döngüde değerlerin toplanması
Yaygın bir kalıp, bir döngüden ara değerleri toplamaktır. Normalde bu, bir Python listesine ekleyerek veya bir Python sözlüğüne girdiler ekleyerek gerçekleştirilir. Ancak bunlar Python yan etkileri olduğundan dinamik olarak açılmamış bir döngüde beklendiği gibi çalışmayacaktır. Dinamik olarak açılmamış bir döngüden sonuçları toplamak için tf.TensorArray
kullanın.
batch_size = 2
seq_len = 3
feature_size = 4
def rnn_step(inp, state):
return inp + state
@tf.function
def dynamic_rnn(rnn_step, input_data, initial_state):
# [batch, time, features] -> [time, batch, features]
input_data = tf.transpose(input_data, [1, 0, 2])
max_seq_len = input_data.shape[0]
states = tf.TensorArray(tf.float32, size=max_seq_len)
state = initial_state
for i in tf.range(max_seq_len):
state = rnn_step(input_data[i], state)
states = states.write(i, state)
return tf.transpose(states.stack(), [1, 0, 2])
dynamic_rnn(rnn_step,
tf.random.uniform([batch_size, seq_len, feature_size]),
tf.zeros([batch_size, feature_size]))
tutucu49 l10n-yer<tf.Tensor: shape=(2, 3, 4), dtype=float32, numpy= array([[[0.06309307, 0.9938811 , 0.90789986, 0.42136216], [0.44997275, 1.9107027 , 1.0716251 , 0.717237 ], [0.6026064 , 2.1622117 , 1.4164022 , 1.4153863 ]], [[0.04946005, 0.69127274, 0.56848884, 0.22406638], [0.8148316 , 1.0278493 , 0.6207781 , 1.1935129 ], [0.9178308 , 1.320889 , 0.989761 , 2.0120025 ]]], dtype=float32)>
sınırlamalar
TensorFlow Function
, bir Python işlevini bir Function
dönüştürürken bilmeniz gereken tasarım gereği birkaç sınırlamaya sahiptir.
Python yan etkilerini yürütme
Yazdırma, listelere ekleme ve globalleri değiştirme gibi yan etkiler, bir Function
içinde beklenmedik şekilde davranabilir, bazen iki kez yürütülür veya tümü yürütülmez. Yalnızca bir dizi girdiye sahip bir Function
ilk kez çağırdığınızda gerçekleşirler. Daha sonra izlenen tf.Graph
, Python kodu çalıştırılmadan yeniden çalıştırılır.
Genel kural, mantığınızdaki Python yan etkilerine güvenmekten kaçınmak ve bunları yalnızca izlemelerinizde hata ayıklamak için kullanmaktır. Aksi takdirde, tf.data , tf.print
, tf.summary
, tf.Variable.assign
ve tf.TensorArray
gibi tf.data
API'leri, kodunuzun her çağrıda TensorFlow çalışma zamanı tarafından yürütülmesini sağlamanın en iyi yoludur.
@tf.function
def f(x):
print("Traced with", x)
tf.print("Executed with", x)
f(1)
f(1)
f(2)
tutucu51 l10n-yerTraced with 1 Executed with 1 Executed with 1 Traced with 2 Executed with 2
Bir Function
öğesinin her çağrılması sırasında Python kodunu yürütmek isterseniz, tf.py_function
bir çıkış taramasıdır. tf.py_function
öğesinin dezavantajı, taşınabilir olmaması veya özellikle performanslı olmaması, SavedModel ile kaydedilememesi ve dağıtılmış (çoklu GPU, TPU) kurulumlarda iyi çalışmamasıdır. Ayrıca, tf.py_function
bağlı olması gerektiğinden, tüm girdileri/çıktıları tensörlere gönderir.
Python global ve serbest değişkenlerini değiştirme
Python genel ve serbest değişkenlerini değiştirmek, Python yan etkisi olarak sayılır, bu nedenle yalnızca izleme sırasında olur.
external_list = []
@tf.function
def side_effect(x):
print('Python side effect')
external_list.append(x)
side_effect(1)
side_effect(1)
side_effect(1)
# The list append only happened once!
assert len(external_list) == 1
tutucu53 l10n-yerPython side effect
Bazen beklenmedik davranışları fark etmek çok zordur. Aşağıdaki örnekte, counter
bir değişkenin artışını koruması amaçlanmıştır. Ancak bir python tamsayı olduğu ve bir TensorFlow nesnesi olmadığı için değeri ilk izleme sırasında yakalanır. tf.function
kullanıldığında, assign_add
, temel alınan grafikte koşulsuz olarak kaydedilecektir. Bu nedenle v
, tf.function
her çağrıldığında 1 artacaktır. Bu sorun, hangi işlemlerin çalıştırılacağını belirlemek için python yan etkileri (örnekteki counter
) kullanıldığında (örnekte assign_add
) Grpah modu Tensorflow kodunu tf.function
2'ye geçirmeye çalışan kullanıcılar arasında yaygındır. ). Genellikle, kullanıcılar bunu ancak şüpheli sayısal sonuçlar gördükten veya beklenenden önemli ölçüde daha düşük performans gördükten sonra fark ederler (örneğin, korunan işlem çok maliyetliyse).
class Model(tf.Module):
def __init__(self):
self.v = tf.Variable(0)
self.counter = 0
@tf.function
def __call__(self):
if self.counter == 0:
# A python side-effect
self.counter += 1
self.v.assign_add(1)
return self.v
m = Model()
for n in range(3):
print(m().numpy()) # prints 1, 2, 3
tutucu55 l10n-yer1 2 3
Beklenen davranışı elde etmek için bir geçici çözüm, işlemleri işlev grafiğinin dışına çıkarmak için tf.init_scope
kullanmaktır. Bu, değişken artışının izleme süresi boyunca yalnızca bir kez yapılmasını sağlar. init_scope
temizlenmiş kontrol akışı ve gradyan bandı da dahil olmak üzere başka yan etkileri olduğuna dikkat edilmelidir. Bazen init_scope
kullanımı gerçekçi bir şekilde yönetilemeyecek kadar karmaşık hale gelebilir.
class Model(tf.Module):
def __init__(self):
self.v = tf.Variable(0)
self.counter = 0
@tf.function
def __call__(self):
if self.counter == 0:
# Lifts ops out of function-building graphs
with tf.init_scope():
self.counter += 1
self.v.assign_add(1)
return self.v
m = Model()
for n in range(3):
print(m().numpy()) # prints 1, 1, 1
tutucu57 l10n-yer1 1 1
Özetle, genel bir kural olarak, Function
dışında yaşayan tamsayılar veya listeler gibi kapsayıcılar gibi python nesnelerini mutasyona uğratmaktan kaçınmalısınız. Bunun yerine argümanları ve TF nesnelerini kullanın. Örneğin, "Bir döngüde değerlerin toplanması" bölümünde, liste benzeri işlemlerin nasıl uygulanabileceğine dair bir örnek vardır.
Bazı durumlarda, bir tf.Variable
ise durumu yakalayabilir ve değiştirebilirsiniz. Keras modellerinin ağırlıkları, aynı ConcreteFunction
tekrarlanan çağrılarla bu şekilde güncellenir.
Python yineleyicilerini ve oluşturucularını kullanma
Oluşturucular ve yineleyiciler gibi birçok Python özelliği, durumu izlemek için Python çalışma zamanına güvenir. Genel olarak, bu yapılar istekli modda beklendiği gibi çalışsa da, bunlar Python yan etkilerinin örnekleridir ve bu nedenle yalnızca izleme sırasında gerçekleşir.
@tf.function
def buggy_consume_next(iterator):
tf.print("Value:", next(iterator))
iterator = iter([1, 2, 3])
buggy_consume_next(iterator)
# This reuses the first value from the iterator, rather than consuming the next value.
buggy_consume_next(iterator)
buggy_consume_next(iterator)
tutucu59 l10n-yerValue: 1 Value: 1 Value: 1
Tıpkı tf.TensorArray
liste yapıları için özel bir tf.data.Iterator
sahiptir. Genel bir bakış için AutoGraph dönüşümleri bölümüne bakın. Ayrıca, tf.data
API, oluşturucu kalıplarının uygulanmasına yardımcı olabilir:
@tf.function
def good_consume_next(iterator):
# This is ok, iterator is a tf.data.Iterator
tf.print("Value:", next(iterator))
ds = tf.data.Dataset.from_tensor_slices([1, 2, 3])
iterator = iter(ds)
good_consume_next(iterator)
good_consume_next(iterator)
good_consume_next(iterator)
tutucu61 l10n-yerValue: 1 Value: 2 Value: 3
Bir tf.function işlevinin tüm çıktıları, dönüş değerleri olmalıdır
tf.Variable
s dışında, bir tf.fonksiyonu tüm çıktılarını döndürmelidir. Herhangi bir tensöre bir fonksiyondan dönüş değerlerinden geçmeden doğrudan erişmeye çalışmak "sızıntılara" neden olur.
Örneğin, aşağıdaki işlev tensörü a
Python global x
aracılığıyla "sızdırır":
x = None
@tf.function
def leaky_function(a):
global x
x = a + 1 # Bad - leaks local tensor
return a + 2
correct_a = leaky_function(tf.constant(1))
print(correct_a.numpy()) # Good - value obtained from function's returns
try:
x.numpy() # Bad - tensor leaked from inside the function, cannot be used here
except AttributeError as expected:
print(expected)
tutucu63 l10n-yer3 'Tensor' object has no attribute 'numpy'
Bu, sızdırılan değer de döndürülse bile geçerlidir:
@tf.function
def leaky_function(a):
global x
x = a + 1 # Bad - leaks local tensor
return x # Good - uses local tensor
correct_a = leaky_function(tf.constant(1))
print(correct_a.numpy()) # Good - value obtained from function's returns
try:
x.numpy() # Bad - tensor leaked from inside the function, cannot be used here
except AttributeError as expected:
print(expected)
@tf.function
def captures_leaked_tensor(b):
b += x # Bad - `x` is leaked from `leaky_function`
return b
with assert_raises(TypeError):
captures_leaked_tensor(tf.constant(2))
tutucu65 l10n-yer2 'Tensor' object has no attribute 'numpy' Caught expected exception <class 'TypeError'>: Traceback (most recent call last): File "/tmp/ipykernel_26244/3551158538.py", line 8, in assert_raises yield File "/tmp/ipykernel_26244/566849597.py", line 21, in <module> captures_leaked_tensor(tf.constant(2)) TypeError: Originated from a graph execution error. The graph execution error is detected at a node built at (most recent call last): >>> File /usr/lib/python3.7/runpy.py, line 193, in _run_module_as_main >>> File /usr/lib/python3.7/runpy.py, line 85, in _run_code >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py, line 16, in <module> >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/traitlets/config/application.py, line 846, in launch_instance >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel/kernelapp.py, line 677, in start >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tornado/platform/asyncio.py, line 199, in start >>> File /usr/lib/python3.7/asyncio/base_events.py, line 534, in run_forever >>> File /usr/lib/python3.7/asyncio/base_events.py, line 1771, in _run_once >>> File /usr/lib/python3.7/asyncio/events.py, line 88, in _run >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel/kernelbase.py, line 457, in dispatch_queue >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel/kernelbase.py, line 446, in process_one >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel/kernelbase.py, line 353, in dispatch_shell >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel/kernelbase.py, line 648, in execute_request >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel/ipkernel.py, line 353, in do_execute >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel/zmqshell.py, line 533, in run_cell >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/IPython/core/interactiveshell.py, line 2902, in run_cell >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/IPython/core/interactiveshell.py, line 2947, in _run_cell >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/IPython/core/async_helpers.py, line 68, in _pseudo_sync_runner >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/IPython/core/interactiveshell.py, line 3173, in run_cell_async >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/IPython/core/interactiveshell.py, line 3364, in run_ast_nodes >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/IPython/core/interactiveshell.py, line 3444, in run_code >>> File /tmp/ipykernel_26244/566849597.py, line 7, in <module> >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/util/traceback_utils.py, line 150, in error_handler >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py, line 910, in __call__ >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py, line 958, in _call >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py, line 781, in _initialize >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/function.py, line 3157, in _get_concrete_function_internal_garbage_collected >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/function.py, line 3557, in _maybe_define_function >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/function.py, line 3402, in _create_graph_function >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py, line 1143, in func_graph_from_py_func >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py, line 672, in wrapped_fn >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py, line 1125, in autograph_handler >>> File /tmp/ipykernel_26244/566849597.py, line 4, in leaky_function >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/util/traceback_utils.py, line 150, in error_handler >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/math_ops.py, line 1383, in binary_op_wrapper >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/util/traceback_utils.py, line 150, in error_handler >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/util/dispatch.py, line 1096, in op_dispatch_handler >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/math_ops.py, line 1737, in _add_dispatch >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/gen_math_ops.py, line 476, in add_v2 >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/framework/op_def_library.py, line 746, in _apply_op_helper >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/framework/func_graph.py, line 691, in _create_op_internal >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/framework/ops.py, line 3705, in _create_op_internal >>> File /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/framework/ops.py, line 2101, in __init__ Error detected in node 'add' defined at: File "/tmp/ipykernel_26244/566849597.py", line 4, in leaky_function TypeError: tf.Graph captured an external symbolic tensor. The symbolic tensor 'add:0' created by node 'add' is captured by the tf.Graph being executed as an input. But a tf.Graph is not allowed to take symbolic tensors from another graph as its inputs. Make sure all captured inputs of the executing tf.Graph are not symbolic tensors. Use return values, explicit Python locals or TensorFlow collections to access it. Please see https://www.tensorflow.org/guide/function#all_outputs_of_a_tffunction_must_be_return_values for more information.
Genellikle, Python deyimlerini veya veri yapılarını kullandığınızda bu tür sızıntılar meydana gelir. Erişilemeyen tensörleri sızdırmaya ek olarak, bu tür ifadeler Python yan etkileri olarak sayıldığından ve her işlev çağrısında yürütüleceği garanti edilmediğinden muhtemelen yanlıştır.
Yerel tensörleri sızdırmanın yaygın yolları, harici bir Python koleksiyonunu veya bir nesneyi mutasyona uğratmayı da içerir:
class MyClass:
def __init__(self):
self.field = None
external_list = []
external_object = MyClass()
def leaky_function():
a = tf.constant(1)
external_list.append(a) # Bad - leaks tensor
external_object.field = a # Bad - leaks tensor
Özyinelemeli tf.işlevleri desteklenmez
Özyinelemeli Function
desteklenmez ve sonsuz döngülere neden olabilir. Örneğin,
@tf.function
def recursive_fn(n):
if n > 0:
return recursive_fn(n - 1)
else:
return 1
with assert_raises(Exception):
recursive_fn(tf.constant(5)) # Bad - maximum recursion error.
tutucu68 l10n-yerCaught expected exception <class 'Exception'>: Traceback (most recent call last): File "/tmp/ipykernel_26244/3551158538.py", line 8, in assert_raises yield File "/tmp/ipykernel_26244/2233998312.py", line 9, in <module> recursive_fn(tf.constant(5)) # Bad - maximum recursion error. tensorflow.python.autograph.impl.api.StagingError: in user code: File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 4, in recursive_fn * return recursive_fn(n - 1) File "/tmp/ipykernel_26244/2233998312.py", line 3, in recursive_fn * if n > 0: File "/usr/lib/python3.7/abc.py", line 139, in __instancecheck__ return _abc_instancecheck(cls, instance) RecursionError: maximum recursion depth exceeded while calling a Python object
Özyinelemeli bir Function
çalışıyor gibi görünse bile, python işlevi birden çok kez izlenir ve performans ima edebilir. Örneğin,
@tf.function
def recursive_fn(n):
if n > 0:
print('tracing')
return recursive_fn(n - 1)
else:
return 1
recursive_fn(5) # Warning - multiple tracings
tutucu70 l10n-yertracing tracing tracing tracing tracing <tf.Tensor: shape=(), dtype=int32, numpy=1>
Bilinen Sorunlar
Function
doğru bir şekilde değerlendirmiyorsa, hata gelecekte düzeltilmesi planlanan bu bilinen sorunlarla açıklanabilir.
Python global ve serbest değişkenlerine bağlı olarak
Function
, Python bağımsız değişkeninin yeni bir değeriyle çağrıldığında yeni bir ConcreteFunction
oluşturur. Ancak, Python kapanışı, globaller veya o Function
yerel olmayanları için bunu yapmaz. Function
Function
sahip oldukları değerleri kullanmaya devam eder. Bu, normal Python işlevlerinin çalışma biçiminden farklıdır.
Bu nedenle, dış adları kapatmak yerine argümanları kullanan işlevsel bir programlama stili izlemelisiniz.
@tf.function
def buggy_add():
return 1 + foo
@tf.function
def recommended_add(foo):
return 1 + foo
foo = 1
print("Buggy:", buggy_add())
print("Correct:", recommended_add(foo))
Buggy: tf.Tensor(2, shape=(), dtype=int32) Correct: tf.Tensor(2, shape=(), dtype=int32)yer tutucu73 l10n-yer
print("Updating the value of `foo` to 100!")
foo = 100
print("Buggy:", buggy_add()) # Did not change!
print("Correct:", recommended_add(foo))
Updating the value of `foo` to 100! Buggy: tf.Tensor(2, shape=(), dtype=int32) Correct: tf.Tensor(101, shape=(), dtype=int32)
Genel bir değeri güncellemenin başka bir yolu, onu bir tf.Variable
yapmak ve bunun yerine Variable.assign
yöntemini kullanmaktır.
@tf.function
def variable_add():
return 1 + foo
foo = tf.Variable(1)
print("Variable:", variable_add())
Variable: tf.Tensor(2, shape=(), dtype=int32)yer tutucu77 l10n-yer
print("Updating the value of `foo` to 100!")
foo.assign(100)
print("Variable:", variable_add())
Updating the value of `foo` to 100! Variable: tf.Tensor(101, shape=(), dtype=int32)
Python nesnelerine bağlı olarak
Python nesnelerini argüman olarak tf.function
, gelecekte düzeltilmesi beklenen bir dizi bilinen soruna sahiptir. Genel olarak, argüman olarak Python ilkel veya tf.nest
uyumlu bir yapı kullanıyorsanız veya bir nesnenin farklı bir örneğini bir Function
içine iletirseniz tutarlı izlemeye güvenebilirsiniz. Ancak, aynı nesneyi geçtiğinizde ve yalnızca niteliklerini değiştirdiğinizde Function
yeni bir iz oluşturmaz.
class SimpleModel(tf.Module):
def __init__(self):
# These values are *not* tf.Variables.
self.bias = 0.
self.weight = 2.
@tf.function
def evaluate(model, x):
return model.weight * x + model.bias
simple_model = SimpleModel()
x = tf.constant(10.)
print(evaluate(simple_model, x))
tf.Tensor(20.0, shape=(), dtype=float32)yer tutucu81 l10n-yer
print("Adding bias!")
simple_model.bias += 5.0
print(evaluate(simple_model, x)) # Didn't change :(
Adding bias! tf.Tensor(20.0, shape=(), dtype=float32)
Güncellenen model orijinal modelle aynı önbellek anahtarına sahip olduğundan, modelin güncellenmiş örneğini değerlendirmek için aynı Function
kullanmak hatalı olacaktır.
Bu nedenle, değişken nesne özniteliklerine bağlı kalmaktan kaçınmak veya yeni nesneler oluşturmak için Function
yazmanız önerilir.
Bu mümkün değilse, bir geçici çözüm, nesnenizi yeniden izlemeye zorlamak için her değiştirdiğinizde yeni Function
s yapmaktır:
def evaluate(model, x):
return model.weight * x + model.bias
new_model = SimpleModel()
evaluate_no_bias = tf.function(evaluate).get_concrete_function(new_model, x)
# Don't pass in `new_model`, `Function` already captured its state during tracing.
print(evaluate_no_bias(x))
tf.Tensor(20.0, shape=(), dtype=float32)yer tutucu85 l10n-yer
print("Adding bias!")
new_model.bias += 5.0
# Create new Function and ConcreteFunction since you modified new_model.
evaluate_with_bias = tf.function(evaluate).get_concrete_function(new_model, x)
print(evaluate_with_bias(x)) # Don't pass in `new_model`.
Adding bias! tf.Tensor(25.0, shape=(), dtype=float32)
Geri izleme pahalı olabileceğinden, tf.Variable
s'yi nesne öznitelikleri olarak kullanabilirsiniz; bu öznitelikler mutasyona uğratılabilir (ancak değiştirilemez, dikkatli olun!), benzer bir etki için bir geri izlemeye gerek yoktur.
class BetterModel:
def __init__(self):
self.bias = tf.Variable(0.)
self.weight = tf.Variable(2.)
@tf.function
def evaluate(model, x):
return model.weight * x + model.bias
better_model = BetterModel()
print(evaluate(better_model, x))
tf.Tensor(20.0, shape=(), dtype=float32)yer tutucu89 l10n-yer
print("Adding bias!")
better_model.bias.assign_add(5.0) # Note: instead of better_model.bias += 5
print(evaluate(better_model, x)) # This works!
Adding bias! tf.Tensor(25.0, shape=(), dtype=float32)
tf.Değişkenleri Oluşturma
Function
yalnızca, ilk çağrıda bir kez oluşturulan ve sonraki işlev çağrılarında yeniden kullanılan tekil tf.Variable
destekler. Aşağıdaki kod parçacığı, her işlev çağrısında yeni bir tf.Variable
oluşturur ve bu da ValueError
istisnasıyla sonuçlanır.
Örnek:
@tf.function
def f(x):
v = tf.Variable(1.0)
return v
with assert_raises(ValueError):
f(1.0)
tutucu92 l10n-yerCaught expected exception <class 'ValueError'>: Traceback (most recent call last): File "/tmp/ipykernel_26244/3551158538.py", line 8, in assert_raises yield File "/tmp/ipykernel_26244/3018268426.py", line 7, in <module> f(1.0) ValueError: in user code: File "/tmp/ipykernel_26244/3018268426.py", line 3, in f * v = tf.Variable(1.0) ValueError: tf.function only supports singleton tf.Variables created on the first call. Make sure the tf.Variable is only created once or created outside tf.function. See https://www.tensorflow.org/guide/function#creating_tfvariables for more information.
Bu sınırlamaya geçici bir çözüm bulmak için kullanılan yaygın bir kalıp, Python Yok değeriyle başlamak ve ardından değer Yok ise koşullu olarak tf.Variable
oluşturmaktır:
class Count(tf.Module):
def __init__(self):
self.count = None
@tf.function
def __call__(self):
if self.count is None:
self.count = tf.Variable(0)
return self.count.assign_add(1)
c = Count()
print(c())
print(c())
tutucu94 l10n-yertf.Tensor(1, shape=(), dtype=int32) tf.Tensor(2, shape=(), dtype=int32)
Birden çok Keras optimize edici ile kullanma
ValueError ile karşılaşabilirsiniz ValueError: tf.function only supports singleton tf.Variables created on the first call.
tf.function ile birden fazla tf.function
iyileştirici kullanırken. Bu hata, optimize edicilerin degradeleri ilk kez uyguladıklarında dahili olarak tf.Variables
oluşturmaları nedeniyle oluşur.
opt1 = tf.keras.optimizers.Adam(learning_rate = 1e-2)
opt2 = tf.keras.optimizers.Adam(learning_rate = 1e-3)
@tf.function
def train_step(w, x, y, optimizer):
with tf.GradientTape() as tape:
L = tf.reduce_sum(tf.square(w*x - y))
gradients = tape.gradient(L, [w])
optimizer.apply_gradients(zip(gradients, [w]))
w = tf.Variable(2.)
x = tf.constant([-1.])
y = tf.constant([2.])
train_step(w, x, y, opt1)
print("Calling `train_step` with different optimizer...")
with assert_raises(ValueError):
train_step(w, x, y, opt2)
tutucu96 l10n-yerCalling `train_step` with different optimizer... Caught expected exception <class 'ValueError'>: Traceback (most recent call last): File "/tmp/ipykernel_26244/3551158538.py", line 8, in assert_raises yield File "/tmp/ipykernel_26244/3167358578.py", line 18, in <module> train_step(w, x, y, opt2) ValueError: in user code: File "/tmp/ipykernel_26244/3167358578.py", line 9, in train_step * optimizer.apply_gradients(zip(gradients, [w])) File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/optimizer_v2.py", line 639, in apply_gradients ** self._create_all_weights(var_list) File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/optimizer_v2.py", line 828, in _create_all_weights _ = self.iterations File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/optimizer_v2.py", line 835, in __getattribute__ return super(OptimizerV2, self).__getattribute__(name) File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/optimizer_v2.py", line 995, in iterations aggregation=tf.VariableAggregation.ONLY_FIRST_REPLICA) File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/optimizer_v2.py", line 1202, in add_weight aggregation=aggregation) File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/engine/base_layer_utils.py", line 129, in make_variable shape=variable_shape if variable_shape else None) ValueError: tf.function only supports singleton tf.Variables created on the first call. Make sure the tf.Variable is only created once or created outside tf.function. See https://www.tensorflow.org/guide/function#creating_tfvariables for more information.
Eğitim sırasında optimize ediciyi değiştirmeniz gerekirse, bir geçici çözüm, her optimize edici için doğrudan ConcreteFunction
çağıran yeni bir Function
oluşturmaktır.
opt1 = tf.keras.optimizers.Adam(learning_rate = 1e-2)
opt2 = tf.keras.optimizers.Adam(learning_rate = 1e-3)
# Not a tf.function.
def train_step(w, x, y, optimizer):
with tf.GradientTape() as tape:
L = tf.reduce_sum(tf.square(w*x - y))
gradients = tape.gradient(L, [w])
optimizer.apply_gradients(zip(gradients, [w]))
w = tf.Variable(2.)
x = tf.constant([-1.])
y = tf.constant([2.])
# Make a new Function and ConcreteFunction for each optimizer.
train_step_1 = tf.function(train_step).get_concrete_function(w, x, y, opt1)
train_step_2 = tf.function(train_step).get_concrete_function(w, x, y, opt2)
for i in range(10):
if i % 2 == 0:
train_step_1(w, x, y) # `opt1` is not used as a parameter.
else:
train_step_2(w, x, y) # `opt2` is not used as a parameter.
Birden çok Keras modeliyle kullanma
Ayrıca ValueError ile karşılaşabilirsiniz ValueError: tf.function only supports singleton tf.Variables created on the first call.
farklı model örneklerini aynı Function
geçirirken.
Bu hata, Keras modellerinin ( giriş şekilleri tanımlı olmayan ) ve Keras katmanlarının ilk çağrıldıklarında tf.Variables
s oluşturması nedeniyle oluşur. Bu değişkenleri, önceden çağrılmış bir Function
içinde başlatmaya çalışıyor olabilirsiniz. Bu hatayı önlemek için, modeli eğitmeden önce tüm ağırlıkları başlatmak için model.build(input_shape)
çağırmayı deneyin.
daha fazla okuma
Bir Function
nasıl dışa aktarılacağını ve yükleneceğini öğrenmek için SavedModel kılavuzuna bakın. İzlemeden sonra gerçekleştirilen grafik optimizasyonları hakkında daha fazla bilgi edinmek için Grappler kılavuzuna bakın. Veri hattınızı nasıl optimize edeceğinizi ve modelinizin profilini nasıl çıkaracağınızı öğrenmek için Profiler kılavuzuna bakın.