Yardım Kaggle üzerinde TensorFlow ile Büyük Bariyer Resifi korumak Meydan Üyelik

tf.function ile daha iyi performans

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyinNot 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 çalıştırmak çok daha kolay ve hızlıdır), ancak bu performans ve konuşlandırılabilirlik pahasına olabilir.

Sen kullanabilirsiniz tf.function programlarınızın grafikler çıkarmak. Python kodunuzdan Python'dan bağımsız veri akışı grafikleri oluşturan bir dönüştürme aracıdır. Bu ölçülebilir ve taşınabilir modeller oluşturmak yardımcı olacak ve kullanımı gereklidir SavedModel .

Bu kılavuz nasıl conceptualize yardımcı olacaktır tf.function etkili bir şekilde kullanabilmesi için, kaputun altında çalışır.

Başlıca çıkarımlar ve öneriler şunlardır:

  • İstekli modunda ayıklama, daha sonra dekore @tf.function .
  • Nesne mutasyonu veya liste ekleme gibi Python yan etkilerine güvenmeyin.
  • tf.function TensorFlow ops en iyi sonucu verir; 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

Bir Function Eğer (uygulanarak örneğin tanımlamak @tf.function dekoratör) sadece bir çekirdek TensorFlow operasyonu benzer: hevesle bunu çalıştırabilir; gradyanları 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>

Sen kullanabilirsiniz Function s içini diğer Function s.

@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 ler özellikle çok sayıda küçük ops grafikler için, daha hızlı istekli kod daha olabilir. Ancak birkaç pahalı işlemi olan (kıvrımlar gibi) grafikler için ç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.006058974999177735
Function conv: 0.005791576000774512
Note how there's not much difference in performance for convolutions

İzleme

Nasıl Bu bölüm ortaya Function gelecekte değişebilir uygulama ayrıntıları içeren başlık altında çalışır. Ancak, anlamak niçin ve ne izleme sırasında bir kez, o kullanımı çok daha kolay tf.function etkili bir!

"İzlemek" nedir?

Bir Function bir daki programını yürüten TensorFlow Graph . Ancak, tf.Graph bir istekli TensorFlow programında yazma olacağımı her şeyi temsil edemez. Örneğin, Python polimorfizm destekler, ancak tf.Graph belirtilen bir veri tipi ve boyuta sahip olan girdileri 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örevleri gerçekleştirebilirsiniz; bunların hiçbiri bir çalışabilir tf.Graph .

Function iki aşamada kodunuzu ayırarak bu boşluğu köprü:

1) "izleme" olarak anılacaktır İlk aşamada, olarak, Function yeni oluşturur tf.Graph . Python kodu normalde çalışır, ancak (iki Tensörler ekleme gibi) tüm TensorFlow işlemleri ertelenir: bunlar tarafından yakalanır tf.Graph ve çalışmaz.

2) İkinci aşamada, bir tf.Graph ilk aşamada ertelenmiş her şeyi içerir çalıştırılır. Bu aşama, izleme aşamasından çok daha hızlıdır.

Girdilere bağlı olarak Function daima denir ilk aşamasını yayınlanmaz. Bkz "izleme Kurallarını" o bu belirlemeyi yapar nasıl daha iyi bir fikir edinmek için aşağıdaki. İlk aşamayı atlamak ve yalnızca ikinci aşamayı yürütmek, size TensorFlow'un yüksek performansını verir.

Ne zaman Function iz karar veriyor, izleme aşaması hemen böylece çağırarak, ikinci aşama takip eder Function oluşturur ve çalıştırır hem tf.Graph . Daha sonra size sadece izleme sahne çalıştırabilirsiniz nasıl göreceğiz get_concrete_function .

Eğer bir içine farklı türde argümanlar geçtiğinizde Function , her iki aşama ç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)

Tekrar tekrar bir çağrı eğer Not Function aynı argüman türü ile oluşturulan grafik özdeş olacağı gibi, TensorFlow, izleme aşamasını atlayıp önceden takip grafiği yeniden kullanılacaktır.

# This doesn't print 'Tracing with ...'
print(double(tf.constant("b")))
tf.Tensor(b'bb', shape=(), dtype=string)

Sen kullanabilirsiniz pretty_printed_concrete_signatures() mevcut izleri tümünü görmek için:

print(double.pretty_printed_concrete_signatures())
double(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, bu gördüğüm tf.function mantığı izleme TensorFlow en grafiğin üzerine bir önbelleğe alınmış, dinamik sevk tabakası oluşturur. Terminoloji hakkında daha spesifik olmak gerekirse:

  • Bir tf.Graph bir TensorFlow hesaplama ham, dil agnostik, taşınabilir bir temsilidir.
  • Bir ConcreteFunction bir sarar tf.Graph .
  • Bir Function bir önbellek yöneten ConcreteFunction ler ve girişler için doğru olanı seçer.
  • tf.function dönen, bir Python işlevini sarar Function nesnesi.
  • Takip Bir oluşturur tf.Graph ve onu saran ConcreteFunction da iz olarak da bilinir.

izleme kuralları

Bir Function , bir takip yeniden belirler ConcreteFunction bir girişin args ve kwargs bir önbellek anahtarı hesaplanmasıyla. Bir önbellek anahtar kilit önem taşıdığı tanımlar bir ConcreteFunction girdi args ve kwargs dayalı Function çağrısı, aşağıdaki kurallar (değişebilir olan) göre:

  • Bir için oluşturulan anahtar tf.Tensor şekli ve d_type olup.
  • Bir için oluşturulan anahtar tf.Variable eşsiz değişken kimliğidir.
  • (Örneğin bir Python ilkel için oluşturulan anahtar int , float , str ) kendi değerdir.
  • İç içe için oluşturulan anahtar dict s, list ler, tuple ler, namedtuple ler ve attr s yaprak-tuşları (bkz düzleştirilmiş başlık olur 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

Sizin, hangi zaman retracing Function birden fazla izleme oluşturur TensorFlow girdilerin her set için doğru grafikler üretir olmasını sağlar yardımcı olur. Ancak, izleme pahalı bir işlemdir! Senin Eğer Function her çağrı için yeni bir grafik izini, kodunuz yürütür daha yavaş kullanmak olmasaydı olduğunu göreceksiniz tf.function .

İzleme davranışını kontrol etmek için aşağıdaki teknikleri kullanabilirsiniz:

  • Belirtin input_signature içinde tf.function sınırı izleme için.
@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]))
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 "/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)).
  • Bir [Yok] boyutu belirleme tf.TensorSpec iz yeniden kullanımı esneklik sağlamak için.

    TensorFlow bir kullanarak kendi şekline dayalı tensörleri maçları yana None sağlayacak bir joker olarak boyut Function ler yeniden izleri için değişken boyutlu girişi için. Her partiden (Bkz için farklı uzunlukta dizileri, ya da farklı boyutlarda resimler varsa değişken boyutlu girişi oluşabilir Trafo ve Derin Rüya örneğin öğreticiler).

@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)
  • Geri izlemeyi azaltmak için Python bağımsız değişkenlerini Tensörlere yayınlayın.

    Çoğu zaman, Python bağımsız değişkenler kontrol hyperparameters ve grafik konstrüksiyon için kullanılır - örneğin, num_layers=10 ya da training=True ya da nonlinearity='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, Otomatik Grafik'in 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))
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

Eğer kuvvet retracing gerekiyorsa, yeni oluşturmak Function . Ayrı Function nesneleri payı izleri değil garantilidir.

def f():
  print('Tracing!')
  tf.print('Executing')

tf.function(f)()
tf.function(f)()
Tracing!
Executing
Tracing!
Executing

Somut fonksiyonların elde edilmesi

Her fonksiyon izlendiğinde, yeni bir somut fonksiyon yaratılır. Doğrudan kullanarak, somut bir işlevi elde edebilirsiniz get_concrete_function .

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")))
tf.Tensor(b'cc', shape=(), dtype=string)

Bir yazdırma ConcreteFunction görüntüler (türleriyle) kendi giriş tartışmaların özetini ve bunun çıktı türünü.

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 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ürlerle somut bir iz kullanmak hata verir

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 "/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 verildiğini 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>
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şlevi etrafında çağrılabilir sarıcı tf.Graph . Gerçek alınırken rağmen tf.Graph nesneyi normalde yapmanız gerekir şey değildir, herhangi bir somut işlevinden 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, kod hata ayıklama iç daha istekli modda daha kolay tf.function . Eğer kod ile süsleyen önce hatasız istekli modda çalıştırır emin olmalıdır tf.function . Ayıklama sürecinde yardımcı olmak için, Arayabileceğin tf.config.run_functions_eagerly(True) küresel devre dışı ve yeniden etkinleştirmek için tf.function .

Yalnızca içinde görünür konularda izini zaman tf.function , burada bazı ipuçları şunlardır:

  • Düz eski Python print aramalar sadece fonksiyonu (yeniden) takip vardığında izini yardımcı izleme sırasında yürütün.
  • tf.print çağrıları her zaman çalıştırır ve yürütme sırasında ara değerleri izini yardımcı olabilir.
  • tf.debugging.enable_check_numerics NaN'ler ve Enf oluşturulur nerede aşağı izlemek için kolay bir yoldur.
  • pdb ( Python ayıklama ) Eğer izleme sırasında neler olup bittiğini anlamanıza yardımcı olabilir. (Uyarı: pdb imzanı-dönüştürülmüş kaynak koduna düşecek.)

Otomatik Grafik dönüşümleri

Autograph varsayılan olarak bulunan bir kütüphane tf.function ve grafik uyumlu TensorFlow ops içine Python istekli kod bir alt kümesini dönüştürür. Bu gibi kontrol akışını içeren if , for , while .

Gibi TensorFlow ops tf.cond ve tf.while_loop çalışmalarına devam eder, ancak kontrol akış yazma ve Python ile yazılmış zaman takip etmek çoğu zaman 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]))
[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))
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ı dönüştürür if <condition> eşdeğer içine ifadeleri tf.cond aramalar. Bu ikame yapılır <condition> bir tensör olduğunu. Aksi takdirde, if deyim bir Python Şartlı olarak yürütülür.

İzleme sırasında bir Python koşulu yürütülür, bu nedenle koşullunun tam olarak bir dalı grafiğe eklenir. AutoGraph olmadan, veriye bağlı kontrol akışı varsa, bu izlenen grafik alternatif dalı alamaz.

tf.cond izleri ve dinamik olarak yürütülmesi sırasında bir kolun seçilmesi, grafik koşullu iki dalları ekler. İzlemenin istenmeyen yan etkileri olabilir; kontrol imzanı izleme etkileri daha fazla bilgi için.

@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

Bkz başvuru belgeleri ek kısıtlamalar ifadeleri ise imzanı-dönüştürdü.

döngüler

Autograph bazı dönüştürme for ve while eşdeğer TensorFlow içine ifadeleri gibi, op döngü tf.while_loop . Dönüştürülür Değilse, for ya while döngü bir Python döngü olarak yürütülür.

Bu ikame aşağıdaki durumlarda yapılır:

  • for x in y : eğer y , bir tensör olup, dönüştürme için tf.while_loop . Özel durumda y a, tf.data.Dataset bir kombinasyonu tf.data.Dataset ops oluşturulur.
  • while <condition> : eğer <condition> bir tensör olduğunu dönüştürme için tf.while_loop .

Ek ops ilave izleme sırasında bir Python döngü yürütür, tf.Graph döngünün her yineleme için.

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 sadece oluşturulan bir kez görünür tf.Graph .

Bkz başvuru belgeleri imzamı dönüştürülmüş ek kısıtlamalar için for ve while ifadeleri.

Python verileri üzerinde döngü

Bir yaygın görülen bir güçlük içinde Python / NumPy veriler üzerinde döngü olduğunu tf.function . Bu döngü için modelin bir kopyasını ekleyerek, izleme sürecinde çalıştırır tf.Graph döngünün her okunması için.

İçinde tüm eğitim döngü sarmak istiyorsanız tf.function , bu yapılacak en güvenli yolu olarak verilerinizi sarılmasıdır tf.data.Dataset böylece imzalar dinamik göz önüne sermek eğitim döngü.

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 6 nodes in its graph
train(<FlatMapDataset shapes: (<unknown>, <unknown>), types: (tf.int32, tf.int32)>) contains 6 nodes in its graph

Bir Veri Seti Python / NumPy veri kaydırma zaman, dikkatli olmak tf.data.Dataset.from_generator karşı tf.data.Dataset.from_tensors . Python verileri tutmak ve yoluyla almak olacaktır önceki tf.py_function ikinci bir büyük olarak verilerin bir kopyasını paket oysa, performans üzerindeki etkileri olabilir tf.constant() bellek etkileri olabilir grafikte düğümü.

Aracılığıyla dosyalardan veri okuma TFRecordDataset , CsvDataset vb kendisi Python dahil etmek zorunda kalmadan, asenkron yükleme ve veri ön yükleme yönetebilirsiniz TensorFlow olarak daha sonra, veri tüketmek için en etkili yoldur. Daha fazla bilgi için bkz tf.data : Yapı TensorFlow giriş boru hatları yönlendirir.

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. Kullanım tf.TensorArray dinamik unrolled döngüden sonuçları birikmeye.

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.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 ü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ütme

Yan etkileri, baskı listelerine ekleme ve globals mutasyona gibi bir iç beklenmedik davranabilir Function bazen iki kez ya da olmasın, tüm yürütme. Onlar sadece bir çağrı ilk zaman olur Function girişleri kümesine sahip. Daha sonra takip tf.Graph Python kodunu çalıştırmadan, reexecuted edilir.

Genel kural, mantığınızdaki 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. Dezavantajı tf.py_function değil taşınabilir ya da özellikle ölçülebilir, SavedModel ile kaydedilemez, ve dağıtılmış (çoklu grafik işlemcisi, TPU) kurulumları iyi çalışmaz olmasıdır. Aynı zamanda, tf.py_function grafik kablo bağlantısı yapılacak kadar vardır, bu tansörlerine tüm giriş / çıkış atar.

Python global ve serbest değişkenlerini değiştirme

Python küresel ve Değişen serbest değişkenler , bir Python yan etki olarak sayar yüzden sadece 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

Bazen beklenmedik davranışları fark etmek çok zordur. Aşağıdaki örnekte, counter bir değişkenin artış korumak için tasarlanmıştır. Ancak bir python tamsayı olduğu ve bir TensorFlow nesnesi olmadığı için değeri ilk izleme sırasında yakalanır. Tüm tf.function kullanılır assign_add alttaki grafik koşulsuz olarak kaydedilecektir. Dolayısıyla v , 1 ile her zaman artacaktır tf.function denir. Bu sorun kullanarak Tensorflow 2 onların Grpah modlu Tensorflow kodu geçirilecek deneyin kullanıcıları arasında yaygındır tf.function piton yan etkiler (dekoratörler, counter örnekte) vadede ne op (belirlemek için kullanılır assign_add örnekte ). 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 anlarlar (ö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
1
2
3

Bir çözüm beklenen davranış kullanarak elde etmek için tf.init_scope fonksiyonu grafiği dışında operasyonlar kaldırın. Bu, değişken artışının izleme süresi boyunca yalnızca bir kez yapılmasını sağlar. Belirtilmelidir init_scope temizlenir kontrol akış ve gradyan bant dahil olmak üzere diğer yan etkileri vardır. Bazen kullanımı init_scope gerçekçi yönetmek için çok 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
1
1
1

Özetle, bir kural olarak, sen piton mutasyona listeleri canlı dışarıdan böyle tamsayılar ya konteynerlerin gibi nesneleri kaçınmalıdır Function . Bunun yerine argümanları ve TF nesnelerini kullanın. Örneğin, bölüm "bir döngü içinde değerlerini Biriken" liste benzeri operasyonlar uygulanabilir nasıl bir örneğini vardır.

Bir olup olmadığını ve bazı durumlarda, yakalama durumunu manipüle edebilir tf.Variable . Bu Keras modellerinin ağırlıkları aynı üzere sürekli çağrı ile güncellenir nasıl ConcreteFunction .

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)
Value: 1
Value: 1
Value: 1

Sadece TensorFlow bir uzman nasıl gibi tf.TensorArray liste yapıları için, bir uzman olan tf.data.Iterator yineleme yapılardan oluşur. Bölümüne bakın imzamı dönüşümler bir bakış için. Ayrıca, tf.data API jeneratör desenleri uygulamak 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

Bir tf.fonksiyonunun tüm çıktıları dönüş değerleri olmalıdır

Haricinde tf.Variable ler, bir tf.function tüm çıkışlarını geri dönmelidir. 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, "sızıntı" tensör altında fonksiyon a Python küresel yoluyla x :

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)
3
'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))
2
'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

Rekürsif Function ler desteklenmez ve sonsuz döngüler 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.
Caught 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

Bir özyinelemeli bile Function çalışması gibi görünüyor, piton işlevi birden çok kez izlenebilir ve performans ima olabilir. Ö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
tracing
tracing
tracing
tracing
tracing
<tf.Tensor: shape=(), dtype=int32, numpy=1>

Bilinen Sorunlar

Senin Eğer Function doğru değerlendirmek değil, hata gelecekte düzeltilmesi planlanan bu bilinen sorunları açıklanabilir.

Python global ve serbest değişkenlerine bağlı olarak

Function yeni oluşturur ConcreteFunction bir Python Tartışmanın yeni bir değerle çağrıldığında. Ancak, bunun Python kapatılması genel ya ya nonlocals için bunu yapmaz Function . 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ı 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)
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)

Küresel bir değeri güncellemek için başka bir yol, bir yapmaktır tf.Variable ve kullanımı Variable.assign yerine yöntemi.

@tf.function
def variable_add():
  return 1 + foo

foo = tf.Variable(1)
print("Variable:", variable_add())
Variable: tf.Tensor(2, shape=(), dtype=int32)
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

İçine argümanlar olarak öneri Python nesneleri geçmek tf.function gelecekte sabit beklenmektedir bilinen sorunların, bir numarası vardır. Bir Python ilkel veya kullanım Genel olarak, tutarlı izleme güvenebilir tf.nest bağımsız değişken olarak uyumlu bir yapıya veya bir içine bir nesnenin başka bir örneği olarak geçmektedir Function . 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)

Aynı kullanma Function güncellenmiş modeli sahip olduğu için modelin güncellenmiş örneğini değerlendirmek için arabası olacak aynı önbellek anahtarını orijinal model olarak.

Bu nedenle size yazmaya tavsiye ediyoruz Function değişebilir nesne niteliklerini bağlı önlemek veya yeni nesneler yaratmak için.

Bu mümkün değilse, bir geçici çözüm yeni yapmaktır Function size kuvvet retracing için nesneyi değiştirmek her zaman s:

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)

Gibi izini süren pahalı olabilir , kullanabileceğiniz tf.Variable bir retrace gerek kalmadan benzer bir etki için mutasyona uğramış olabilir nesne niteliklerini, (ama değişmedi, dikkat et!) Olarak s.

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.Değişkenleri Oluşturma

Function tekil yalnızca destekler tf.Variable ilk çağrı kez oluşturulan ve sonraki işlev çağrıları arasında yeniden. Kod yeni yaratacak aşağıda pasajı tf.Variable her işlev çağrısında bir sonuçlanır içinde ValueError istisna.

Örnek:

@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 "/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 kısıtlamaya bir geçici işe etmek için kullanılan genel desen şartlı sonra, bir Python Yok değeri ile başlangıç oluşturmaktır tf.Variable değer Hiçbiri ise:

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 edici ile kullanma

Sen karşılaşabilir ValueError: tf.function only supports singleton tf.Variables created on the first call. zaman ile birden fazla Keras eniyileyicisini kullanarak tf.function . Optimize içten oluşturmak için bu hata oluşur tf.Variables ilk kez geçişlerini uyguladığınızda.

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 "/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ğer eğitim sırasında optimize edici değiştirmeniz gerekirse, bir çözüm yeni yaratmaktır Function çağırarak, her optimize edici için ConcreteFunction doğrudan.

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 fazla Keras modeliyle kullanma

Ayrıca karşılaşabilirsiniz ValueError: tf.function only supports singleton tf.Variables created on the first call. Aynı farklı modeli örneklerini geçerken Function .

Keras modelleri (burada, bu hata oluşur , girdi şekli tanımlı yok ) ve Keras tabakaları oluşturmak tf.Variables ilk çağrıldığında s. Bir iç bu değişkenleri başlatmak için çalışıyor olabilir Function zaten adı olmuştur. Bu hatayı önlemek için arama deneyin model.build(input_shape) modeli eğitim önce tüm ağırlıkları başlatmak için.

daha fazla okuma

İhracat ve yüklemesi hakkında bilgi edinmek için Function bkz SavedModel kılavuzu . İzleme sonrasında yapılmaktadır grafik optimizasyonları hakkında daha fazla bilgi edinmek için bkz Grappler kılavuzu . Veri boru hattı optimize etmek ve modeli profil öğrenmek için, bkz Profiler kılavuzu .