![]() | ![]() | ![]() | ![]() |
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 daha hızlıdır), ancak bu performans ve devreye alınabilirlik pahasına gelebilir.
tf.function
programlarınızdan grafik yapmak için kullanabilirsiniz. Python kodunuzdan Python'dan bağımsız veri akışı grafikleri oluşturan bir dönüştürme aracıdır. Bu, yüksek performanslı ve taşınabilir modeller oluşturmanıza yardımcı olacaktır ve SavedModel
kullanmanız SavedModel
.
Bu kılavuz, tf.function
başlık altında nasıl çalıştığını kavramsallaştırmanıza yardımcı olacak, böylece onu etkili bir şekilde kullanabilirsiniz.
Ana çıkarımlar ve öneriler şunlardır:
- İstekli modda hata ayıklayın, ardından
@tf.function
ile@tf.function
. - Nesne mutasyonu veya liste ekleri gibi Python yan etkilerine güvenmeyin.
-
tf.function
en iyitf.function
çalışır; NumPy ve Python çağrıları sabitlere dönüştürülür.
Kurulum
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: Hevesle çalıştırabilirsiniz; degradeleri hesaplayabilirsiniz; ve bunun gibi.
@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)>
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
diğer 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]))
<tf.Tensor: shape=(3, 2), dtype=float32, numpy= array([[3., 3.], [3., 3.], [3., 3.]], dtype=float32)>
Function
, özellikle çok sayıda 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 (evrişimler 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")
Eager conv: 0.003693543000053978 Function conv: 0.004675635000012335 Note how there's not much difference in performance for convolutions
İzleme
Bu bölüm , gelecekte değişebilecek uygulama ayrıntıları 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 kolaydır!
"İzleme" nedir?
Bir Function
, programınızı bir TensorFlow Grafiğinde çalıştırır . Ancak, bir tf.Graph
, istekli bir TensorFlow programında yazacağınız her şeyi temsil edemez. Örneğin, Python polimorfizmi destekler, ancak tf.Graph
, girdilerinin belirli bir veri türüne ve boyuta sahip olmasını gerektirir. Veya komut satırı argümanlarını okumak, bir hata oluşturmak veya daha karmaşık bir Python nesnesiyle çalışmak gibi yan görevleri gerçekleştirebilirsiniz; bunların hiçbiri bir tf.Graph
.
Function
, kodunuzu iki aşamada ayırarak bu boşluğu kapatır:
1) " İzleme " olarak adlandırılan ilk aşamada, Function
yeni bir tf.Graph
oluşturur. Python kodu normal şekilde çalışır, ancak tüm TensorFlow işlemleri (iki Tensör eklemek gibi) ertelenir : tf.Graph
tarafından tf.Graph
ve çalıştırılmaz.
2) İkinci aşamada, birinci 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.
Girdilerine bağlı olarak, Function
çağrıldığında her zaman ilk aşamayı çalıştırmayacaktır. Bu belirlemeyi nasıl yaptığına dair daha iyi bir fikir edinmek için aşağıdaki "İzleme kuralları" bölümüne 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ın hemen ardından ikinci aşama gelir, bu nedenle Function
çağrılması hem tf.Graph
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 get_concrete_function
.
Bir Function
farklı türde argümanlar Function
, 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()
Tracing 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ı bağımsız değişken türüne sahip bir Function
tekrar tekrar çağırırsanız, TensorFlow'un izleme aşamasını atlayacağını ve oluşturulan grafik aynı olacağından daha önce izlenen bir grafiği yeniden kullanacağını unutmayın.
# This doesn't print 'Tracing with ...'
print(double(tf.constant("b")))
tf.Tensor(b'bb', shape=(), dtype=string)
Kullanılabilir tüm izleri görmek için pretty_printed_concrete_signatures()
kullanabilirsiniz:
print(double.pretty_printed_concrete_signatures())
double(a) Args: a: float32 Tensor, shape=() Returns: float32 Tensor, shape=() double(a) Args: a: string Tensor, shape=() Returns: string Tensor, shape=() double(a) Args: a: int32 Tensor, shape=() Returns: int32 Tensor, shape=()
Şimdiye kadar, tf.function
TensorFlow'un grafik izleme mantığı üzerinden önbelleğe alınmış, dinamik bir gönderim 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
tf.Graph
sarar. - Bir
Function
, birConcreteFunction
önbelleğini yönetir ve girdileriniz için doğru olanı seçer. -
tf.function
bir Python işlevinitf.function
birFunction
nesnesi döndürür. - İzleme bir
tf.Graph
oluşturur ve onu izleme olarak da bilinen birConcreteFunction
tf.Graph
.
İzleme kuralları
Bir Function
, bir girdinin bağımsız değişkenlerinden ve anahtar sözcüklerinden bir önbellek anahtarı hesaplayarak izlenen bir ConcreteFunction
yeniden kullanılıp kullanılmayacağını belirler. Önbellek anahtarı , aşağıdaki kurallara göre (değişebilir), Function
çağrısının giriş argümanlarına ve anahtarlarına göre bir ConcreteFunction
tanımlayan anahtardır:
- Bir
tf.Tensor
için üretilen anahtar, şekli ve tipidir. - Bir
tf.Variable
için oluşturulan anahtar, benzersiz bir değişkentf.Variable
. - Bir Python ilkeli için üretilen anahtar (
int
,float
,str
) değeridir. - İç içe geçmiş
dict
s,list
s,tuple
s,namedtuple
s veattr
s için oluşturulan anahtar, yaprak anahtarlarının düzleştirilmişnest.flatten
(bkz.nest.flatten
). (Bu düzleştirmenin bir sonucu olarak, izleme sırasında kullanılandan farklı bir iç içe geçme yapısına sahip somut bir işlevi çağırmak, bir TypeError ile sonuçlanacaktır). - Diğer tüm Python türleri için, anahtarlar nesne
id()
dayanır, böylece yöntemler bir sınıfın her örneği için bağımsız olarak izlenir.
Yeniden izlemeyi kontrol etme
Function
birden fazla iz oluşturduğu zaman olan yeniden izleme, TensorFlow'un her bir girdi kümesi için doğru grafikler oluşturmasına yardımcı olur. Ancak, izleme pahalı bir işlemdir! Function
her çağrı için yeni bir grafiği yeniden tf.function
kullanmadığınız tf.function
göre daha yavaş tf.function
.
İzleme davranışını kontrol etmek için aşağıdaki teknikleri kullanabilirsiniz:
-
input_signature
sınırlandırmak içininput_signature
tf.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])))
# We 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]]))
# We specified an int32 dtype in the input signature, so this should fail.
with assert_raises(ValueError):
next_collatz(tf.constant([1.0, 2.0]))
Tracing 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 "<ipython-input-1-73d0ca52e838>", line 8, in assert_raises yield File "<ipython-input-1-20f544b8adbf>", 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 "<ipython-input-1-73d0ca52e838>", line 8, in assert_raises yield File "<ipython-input-1-20f544b8adbf>", 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))
İz yeniden kullanımında esneklik sağlamak için
tf.TensorSpec
içinde bir [Yok] boyutu belirtin.TensorFlow tensörleri şekillerine göre eşleştirdiğinden, joker karakter olarak
None
boyutunun kullanılması,Function
ın değişken boyutlu girdiler için izleri yeniden kullanmasına izin verir. Her grup için farklı uzunlukta dizileriniz veya farklı boyutlarda resimleriniz varsa değişken boyutlu girdi 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])))
Tracing 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)
Yeniden izlemeyi azaltmak için Python argümanlarını Tensörlere aktarın.
Python argümanları genellikle hiperparametreleri ve grafik yapılarını kontrol etmek için kullanılır - örneğin,
num_layers=10
veyatraining=True
veyanonlinearity='relu'
. Dolayısıyla, Python argümanı değişirse, grafiği yeniden izlemeniz gerektiği mantıklıdır.Bununla birlikte, grafik yapısını kontrol etmek için bir Python argümanı kullanılmıyor olabilir. Bu durumlarda, Python değerindeki bir değişiklik gereksiz yeniden izlemeyi tetikleyebilir. Örneğin, AutoGraph'ın dinamik olarak açacağı bu eğitim döngüsünü ele alalım. Birden fazla 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))
Retracing 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
Yeniden izlemeyi zorlamanız gerekiyorsa yeni bir Function
. Ayrı Function
nesnelerinin izleri paylaşmamaları garanti edilir.
def f():
print('Tracing!')
tf.print('Executing')
tf.function(f)()
tf.function(f)()
Tracing! Executing Tracing! Executing
Somut işlevler elde etmek
Bir işlev her izlendiğinde, yeni bir somut işlev oluşturulur. get_concrete_function
işlevini 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)
# 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")))
Tracing with Tensor("a:0", shape=(), dtype=string) 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)
ConcreteFunction double(a) Args: a: string Tensor, shape=() Returns: string Tensor, shape=()
Ayrıca somut bir işlevin imzasını doğrudan da alabilirsiniz.
print(double_strings.structured_input_signature)
print(double_strings.structured_outputs)
((TensorSpec(shape=(), dtype=tf.string, name='a'),), {}) Tensor("Identity:0", shape=(), dtype=string)
Uyumsuz türlere sahip somut bir iz kullanmak bir hataya neden olur
with assert_raises(tf.errors.InvalidArgumentError):
double_strings(tf.constant(1))
Caught expected exception <class 'tensorflow.python.framework.errors_impl.InvalidArgumentError'>: Traceback (most recent call last): File "<ipython-input-1-73d0ca52e838>", line 8, in assert_raises yield File "<ipython-input-1-e4e2860a4364>", 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]
Python argümanlarına somut bir fonksiyonun girdi imzasında özel muamele gördüğünü fark edebilirsiniz. TensorFlow 2.3'ten önce, Python argümanları somut fonksiyonun imzasından basitçe kaldırılıyordu. TensorFlow 2.3 ile başlayarak, Python argümanları imzada kalır, ancak izleme sırasında ayarlanan değeri almak için 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>
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.6/site-packages/tensorflow/python/eager/function.py", line 1683, in _call_impl cancellation_manager) File "/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/eager/function.py", line 1728, in _call_with_flat_signature self._flat_signature_summary(), ", ".join(sorted(kwargs)))) TypeError: pow(a) got unexpected keyword arguments: b. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<ipython-input-1-73d0ca52e838>", line 8, in assert_raises yield File "<ipython-input-1-d163f3d206cb>", 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
Grafikler elde etmek
Her somut işlev, bir tf.Graph
etrafında ç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}')
[] -> a ['a', 'a'] -> add ['add'] -> Identity
Hata ayıklama
Genel olarak, hata ayıklama kodu istekli modda tf.function
içinden daha tf.function
. tf.function
ile dekorasyon yapmadan önce kodunuzun istekli modda hatasız çalıştığından emin tf.function
. Hata ayıklama sürecine yardımcı olmak için, tf.config.run_functions_eagerly(True)
işlevini global olarak devre dışı bırakmak ve yeniden etkinleştirmek için tf.config.run_functions_eagerly(True)
işlevini tf.function
.
Yalnızca tf.function
görünen sorunları takip tf.function
, 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
,tf.debugging.enable_check_numerics
nerede oluşturulduğunutf.debugging.enable_check_numerics
kolay bir yoludur. -
pdb
, izleme sırasında neler olduğunu anlamanıza yardımcı olabilir. (Uyarı: PDB sizi AutoGraph'a dönüştürülmüş kaynak koda bırakacaktır.)
Otomatik Grafik Dönüşümleri
AutoGraph, tf fonksiyonunda varsayılan olarak tf.function
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
işlemleri çalışmaya devam eder, ancak kontrol akışının Python'da yazıldıklarında yazılması ve anlaşılması genellikle daha kolaydır.
# 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]))
[0.150836706 0.575092077 0.530339956 0.492499471 0.696070552] [0.149703071 0.519089103 0.485640883 0.456198 0.601867676] [0.148594663 0.476996601 0.450749785 0.426980466 0.538377285] [0.147510558 0.44383505 0.422515154 0.402794749 0.491758645] [0.146449849 0.416818231 0.399047196 0.382337689 0.45561108] [0.145411745 0.394246608 0.379133403 0.364735901 0.42650038] [0.144395441 0.375015408 0.361954659 0.349378705 0.402392507] [0.143400162 0.358370811 0.346934587 0.3358244 0.381994188] [0.142425224 0.343778163 0.333654165 0.323744506 0.364438057] [0.141469926 0.330846161 0.321800381 0.312888771 0.34911716] [0.140533626 0.319280863 0.311133921 0.303062797 0.335592359] [0.139615685 0.308856487 0.301468313 0.294112951 0.323536754] [0.13871555 0.299396455 0.292655736 0.285915941 0.312701344] [0.137832627 0.290760159 0.28457731 0.278371543 0.302892596] [0.136966363 0.282834291 0.277136147 0.271397203 0.293957472] [0.136116222 0.275526226 0.270252436 0.264924437 0.285773188] [0.135281757 0.268759459 0.263859689 0.258895695 0.278239816] [0.134462461 0.262470126 0.257902056 0.253262341 0.271275192] [0.133657902 0.256604493 0.252332211 0.24798286 0.264810979] [0.132867619 0.251116842 0.247109696 0.243021563 0.258789837] [0.132091209 0.245968238 0.242199793 0.238347709 0.253163248] [0.131328285 0.241125017 0.237572461 0.233934492 0.247889832] [0.130578429 0.236558065 0.233201504 0.229758516 0.242934018] [0.129841298 0.232242063 0.229064062 0.225799173 0.238265097] [0.129116505 0.228154778 0.22514002 0.222038344 0.233856365] [0.128403738 0.224276677 0.221411601 0.218459949 0.229684487] [0.127702653 0.220590457 0.217863053 0.215049684 0.225728899] <tf.Tensor: shape=(5,), dtype=float32, numpy= array([0.12701295, 0.21708074, 0.21448033, 0.21179478, 0.22197153], dtype=float32)>
Merak ediyorsanız, üretilen kod imzasını inceleyebilirsiniz.
print(tf.autograph.to_code(f.python_function))
def 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 bir Python koşullu olarak çalıştırılır.
İzleme sırasında bir Python koşullu çalıştırılır, bu nedenle grafiğe koşulun tam olarak bir dalı eklenir. AutoGraph olmadan, bu izlenen grafik, veriye bağlı kontrol akışı varsa alternatif dalı alamaz.
tf.cond
, çalıştırma zamanında dinamik olarak bir dal seçerek grafiğe koşulun her iki dalını da izler ve ekler. İzlemenin istenmeyen yan etkileri olabilir; Daha fazlası 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))
Tracing 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 deyimleriyle ilgili ek kısıtlamalar için referans belgelerine bakın.
Döngüler
AutoGraph, bazı for
ve while
ifadelerini tf.while_loop
. tf.while_loop
gibi eşdeğer TensorFlow döngü işlemlerine tf.while_loop
. Dönüştürülmezse, for
veya while
döngüsü bir Python döngüsü olarak yürütülür.
Bu değişiklik aşağıdaki durumlarda yapılır:
-
tf.while_loop
for x in y
:y
bir Tensör ise,tf.while_loop
.tf.while_loop
dönüştürün. Özel durumday
a,tf.data.Dataset
bir kombinasyonutf.data.Dataset
ops oluşturulur. -
while <condition>
:<condition>
bir Tensör ise,tf.while_loop
.tf.while_loop
dönüştür.
Bir Python döngüsü izleme sırasında çalıştırılır ve döngünün her yinelemesi için tf.Graph
ek işlemler tf.Graph
.
Bir TensorFlow döngüsü, döngünün gövdesini izler ve yürütme zamanında kaç yineleme ç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
deyimleriyle ilgili ek kısıtlamalar için referans belgelerine bakın.
Python verileri üzerinde döngü
Yaygın bir tuzak, bir tf.function
içinde Python / Numpy verileri üzerinden döngü tf.function
. Bu döngü izleme işlemi sırasında yürütülür 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
sarmak istiyorsanız, bunu yapmanın en güvenli yolu, verilerinizitf.data.Dataset
olarak sarmalayarak AutoGraph'ın egzersiz döngüsünü dinamik olarak açmasını sağlamaktı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)))
train([(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 10 nodes in its graph train(<FlatMapDataset shapes: (<unknown>, <unknown>), types: (tf.int32, tf.int32)>) contains 10 nodes in its graph
Bir Veri Kümesinde Python / Numpy verilerini tf.data.Dataset.from_generator
, tf.data.Dataset.from_generator
ile tf.data.Dataset.from_tensors
dikkatli tf.data.Dataset.from_tensors
. İlki, verileri Python'da tutacak ve performansı etkileyebilecek tf.py_function
aracılığıyla tf.py_function
, ikincisi ise verilerin bir kopyasını grafikte bellek etkilerine sahip olabilecek büyük bir tf.constant()
düğümü olarak tf.constant()
.
TFRecordDataset / CsvDataset / etc aracılığıyla dosyalardan veri okuma. TensorFlow, Python'u dahil etmek zorunda kalmadan verilerin eşzamansız yüklenmesini ve önceden getirilmesini yönetebildiğinden, verileri tüketmenin en etkili yoludur. Daha fazla bilgi edinmek için tf.data kılavuzuna bakın .
Bir döngüde değerleri toplamak
Yaygın bir model, bir döngüden ara değerleri toplamaktır. Normalde bu, bir Python listesine eklenerek veya bir Python sözlüğüne girişler eklenerek gerçekleştirilir. Bununla birlikte, bunlar Python yan etkileri olduğundan, dinamik olarak kaydırılmamış bir döngüde beklendiği gibi çalışmayacaktır. tf.TensorArray
olarak tf.TensorArray
sonuçları tf.TensorArray
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]))
<tf.Tensor: shape=(2, 3, 4), dtype=float32, numpy= array([[[0.6345552 , 0.3862481 , 0.8089291 , 0.397156 ], [0.8435192 , 0.46313608, 1.2150625 , 1.2924602 ], [0.84762645, 0.9920107 , 1.6375196 , 1.8461396 ]], [[0.44864273, 0.8552673 , 0.36585057, 0.88470626], [0.6609589 , 1.4641674 , 0.79369175, 1.0593072 ], [0.8057562 , 2.4129076 , 1.5868478 , 1.8529567 ]]], dtype=float32)>
Sınırlamalar
TensorFlow Function
Bir üzere bir Python işlevini dönüştürürken farkında olması gerektiğini tasarımı ile birkaç sınırlaması vardır Function
.
Python yan etkilerini yürütmek
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ülebilir veya hepsini gerçekleştirmeyebilir. Yalnızca bir dizi girişle bir Function
ilk kez çağırdığınızda olurlar. Daha sonra, izlenen tf.Graph
, Python kodunu çalıştırmadan yeniden çalıştırılır.
Genel kural, mantığınızda Python yan etkilerine güvenmekten kaçınmak ve bunları yalnızca izlerinizde hata ayıklamak için kullanmaktır. Aksi takdirde, gibi TensorFlow API'leri tf.data
, tf.print
, tf.summary
, tf.Variable.assign
ve tf.TensorArray
her çağrı ile TensorFlow çalışma zamanı tarafından yürütülecek kodunuzu 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)
Traced with 1 Executed with 1 Executed with 1 Traced with 2 Executed with 2
Bir her çağrı sırasında Python kodu çalıştırmak istiyorsanız Function
, tf.py_function
bir çıkış kapak olduğunu. tf.py_function
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
grafiğe bağlanması gerektiğinden, tüm girdileri / çıktıları tensörlere çevirir.
Python global ve serbest değişkenleri değiştirme
Python global ve serbest değişkenlerinin değiştirilmesi bir Python yan etkisi olarak sayılır, bu nedenle yalnızca izleme sırasında gerçekleşir.
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
Python side effect
Listeler, dikteler ve Function
dışında yaşayan diğer nesneler gibi kapları değiştirmekten kaçınmalısınız. Bunun yerine, bağımsız değişkenleri ve TF nesnelerini kullanın. Örneğin, "Bir döngüde değerleri biriktirme" 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
yapılan yinelenen çağrılarla bu şekilde güncellenir.
Python yineleyicileri ve oluşturucuları kullanma
Üreteçler ve yineleyiciler gibi birçok Python özelliği, durumu takip etmek için Python çalışma zamanına güvenir. Genel olarak, bu yapılar istekli modda beklendiği gibi çalışırken, 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)
Value: 1 Value: 1 Value: 1
tf.TensorArray
liste yapıları için özel bir tf.TensorArray'e sahip olması gibi, yineleme yapıları için özel bir tf.data.Iterator
sahiptir. Bir genel bakış için Otomatik Grafik Dönüşümleri bölümüne bakın. Ayrıca tf.data
API, oluşturucu modellerinin 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)
Value: 1 Value: 2 Value: 3
Function
çağrıları arasındaki tf.Variables'ı silme
Karşılaşabileceğiniz diğer bir hata, çöpte toplanan bir değişkendir. ConcreteFunction
s yalnızca kapattıkları değişkenlere yönelik WeakRef'leri korur, bu nedenle herhangi bir değişkene yönelik bir referans tutmanız gerekir.
external_var = tf.Variable(3)
@tf.function
def f(x):
return x * external_var
traced_f = f.get_concrete_function(4)
print("Calling concrete function...")
print(traced_f(4))
# The original variable object gets garbage collected, since there are no more
# references to it.
external_var = tf.Variable(4)
print()
print("Calling concrete function after garbage collecting its closed Variable...")
with assert_raises(tf.errors.FailedPreconditionError):
traced_f(4)
Calling concrete function... tf.Tensor(12, shape=(), dtype=int32) Calling concrete function after garbage collecting its closed Variable... Caught expected exception <class 'tensorflow.python.framework.errors_impl.FailedPreconditionError'>: Traceback (most recent call last): File "<ipython-input-1-73d0ca52e838>", line 8, in assert_raises yield File "<ipython-input-1-9a93d2e07632>", line 16, in <module> traced_f(4) tensorflow.python.framework.errors_impl.FailedPreconditionError: 2 root error(s) found. (0) Failed precondition: Error while reading resource variable _AnonymousVar3 from Container: localhost. This could mean that the variable was uninitialized. Not found: Resource localhost/_AnonymousVar3/N10tensorflow3VarE does not exist. [[node ReadVariableOp (defined at <ipython-input-1-9a93d2e07632>:4) ]] (1) Failed precondition: Error while reading resource variable _AnonymousVar3 from Container: localhost. This could mean that the variable was uninitialized. Not found: Resource localhost/_AnonymousVar3/N10tensorflow3VarE does not exist. [[node ReadVariableOp (defined at <ipython-input-1-9a93d2e07632>:4) ]] [[ReadVariableOp/_2]] 0 successful operations. 0 derived errors ignored. [Op:__inference_f_782] Function call stack: f -> f
Bilinen Sorunlar
Function
doğru bir şekilde değerlendirilmiyorsa, hata ileride düzeltilmesi planlanan bu bilinen sorunlardan kaynaklanıyor olabilir.
Python global ve serbest değişkenlere bağlı olarak
Function
, bir Python bağımsız değişkeninin yeni bir değeriyle çağrıldığında yeni bir ConcreteFunction
oluşturur. Ancak, Python kapanışı, globalleri veya bu Function
yerel olmayanları için bunu yapmaz. Onların değeri çağrıları arasında değişirse Function
, Function
hala takip edildiğinde oldukları değerleri kullanır. Bu, normal Python işlevlerinin çalışma biçiminden farklıdır.
Bu nedenle, dış adların üzerine kapatmak yerine bağımsız değişkenler kullanan işlevsel bir programlama stili öneriyoruz.
@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)
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)
Dış adların değerlerini güncellemediğiniz sürece kapatabilirsiniz.
Python nesnelerine bağlı olarak
Python nesnelerini argüman olarak tf.function
, gelecekte düzeltilmesi beklenen bir dizi bilinen sorun vardır. Genel olarak, bir Python ilkel veya tf.nest
uyumlu yapıyı bir argüman olarak kullanırsanız veya bir nesnenin farklı bir örneğini bir Function
geçirirseniz tutarlı izlemeye güvenebilirsiniz. Ancak Function
aynı nesneyi geçmek ve sadece özelliklerini değiştiğinde 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)
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şebilir nesne niteliklerine bağlı kalmamak için Function
yazmanızı veya yeni nesneler oluşturmanızı öneririz.
Bu mümkün değilse, nesnenizi her değiştirdiğinizde geri izlemeyi zorlamak için yeni Function
oluşturmak bir geçici çözümdü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)
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)
Yeniden tf.Variable
pahalı olabileceğinden , tf.Variable
s'yi nesne öznitelikleri olarak kullanabilirsiniz; bu, benzer bir etki için yeniden tf.Variable
gerek kalmadan mutasyona tf.Variable
(ancak değiştirilemez, dikkatli!).
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)
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.Variables oluşturma
Function
, değişkenleri yalnızca bir kez, ilk çağrıldığında oluşturmayı ve sonra yeniden kullanmayı destekler. Yeni izlerde tf.Variables
oluşturamazsınız. Sonraki çağrılarda yeni değişkenler oluşturulmasına şu anda izin verilmemektedir, ancak gelecekte olacaktır.
Misal:
@tf.function
def f(x):
v = tf.Variable(1.0)
return v
with assert_raises(ValueError):
f(1.0)
Caught expected exception <class 'ValueError'>: Traceback (most recent call last): File "<ipython-input-1-73d0ca52e838>", line 8, in assert_raises yield File "<ipython-input-1-8a0913e250e0>", line 7, in <module> f(1.0) ValueError: in user code: <ipython-input-1-8a0913e250e0>:3 f * v = tf.Variable(1.0) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/variables.py:262 __call__ ** return cls._variable_v2_call(*args, **kwargs) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/variables.py:256 _variable_v2_call shape=shape) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/variables.py:67 getter return captured_getter(captured_previous, **kwargs) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/eager/def_function.py:731 invalid_creator_scope "tf.function-decorated function tried to create " ValueError: tf.function-decorated function tried to create variables on non-first call.
Bu değişkenler yalnızca işlev ilk kez çalıştırıldığında oluşturulduğu sürece Function
içinde değişkenler oluşturabilirsiniz.
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())
tf.Tensor(1, shape=(), dtype=int32) tf.Tensor(2, shape=(), dtype=int32)
Birden çok Keras optimize ediciyle kullanma
ValueError: tf.function-decorated function tried to create variables on non-first call.
karşılaşabilirsiniz ValueError: tf.function-decorated function tried to create variables on non-first call.
tf.function
sahip birden fazla tf.function
iyileştirici tf.function
. Bu hata, optimize tf.Variables
degradeleri ilk kez uyguladıklarında dahili olarak tf.Variables
oluşturdukları için 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)
Calling `train_step` with different optimizer... Caught expected exception <class 'ValueError'>: Traceback (most recent call last): File "<ipython-input-1-73d0ca52e838>", line 8, in assert_raises yield File "<ipython-input-1-d3d3937dbf1a>", line 18, in <module> train_step(w, x, y, opt2) ValueError: in user code: <ipython-input-1-d3d3937dbf1a>:9 train_step * optimizer.apply_gradients(zip(gradients, [w])) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py:604 apply_gradients ** self._create_all_weights(var_list) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py:781 _create_all_weights _ = self.iterations /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py:788 __getattribute__ return super(OptimizerV2, self).__getattribute__(name) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py:926 iterations aggregation=tf_variables.VariableAggregation.ONLY_FIRST_REPLICA) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py:1132 add_weight aggregation=aggregation) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/base.py:810 _add_variable_with_custom_getter **kwargs_for_getter) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/engine/base_layer_utils.py:142 make_variable shape=variable_shape if variable_shape else None) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/variables.py:260 __call__ return cls._variable_v1_call(*args, **kwargs) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/variables.py:221 _variable_v1_call shape=shape) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/variables.py:67 getter return captured_getter(captured_previous, **kwargs) /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/eager/def_function.py:731 invalid_creator_scope "tf.function-decorated function tried to create " ValueError: tf.function-decorated function tried to create variables on non-first call.
Eğitim sırasında optimize ediciyi değiştirmeniz gerekirse, her bir optimize edici için yeni bir Function
oluşturmak için bir geçici çözüm, ConcreteFunction
doğrudan çağırmaktı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
ValueError: tf.function-decorated function tried to create variables on non-first call.
de karşılaşabilirsiniz ValueError: tf.function-decorated function tried to create variables on non-first call.
farklı model örneklerini aynı Function
geçirirken.
Bu hata, Keras modelleri ( giriş şekli tanımlanmamış ) ve tf.Variables
katmanları ilk çağrıldıklarında tf.Variables
s oluşturduğu için tf.Variables
. Zaten çağrılmış olan bir Function
içinde bu değişkenleri başlatmaya çalışıyor olabilirsiniz. Bu hatayı önlemek için, modeli model.build(input_shape)
ö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 ardışık düzeninizi nasıl optimize edeceğinizi ve modelinizin profilini nasıl optimize edeceğinizi öğrenmek için Profiler kılavuzuna bakın .