Tarihi kaydet! Google I / O 18-20 Mayıs'ta geri dönüyor Şimdi kaydolun
Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Tf.function ile daha iyi performans

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

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 iyi tf.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 benzeri.

@tf.function  # The decorator converts `add` into a `Function`.
def add(a, b):
  return a + b

add(tf.ones([2, 2]), tf.ones([2, 2]))  #  [[2., 2.], [2., 2.]]
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[2., 2.],
       [2., 2.]], dtype=float32)>
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.0035502629999655255
Function conv: 0.004116348000025027
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ü 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 ç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ığını daha iyi anlamak 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 , bir ConcreteFunction önbelleğini yönetir ve girdileriniz için doğru olanı seçer.
  • tf.function bir Python işlevini tf.function bir Function nesnesi döndürür.
  • İzleme bir tf.Graph oluşturur ve onu iz olarak da bilinen bir ConcreteFunction tf.Graph .

İzleme kuralları

Bir Function , bir girdinin bağımsız değişkenlerinden ve anahtarlarından 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şken tf.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 ve attr 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 anahtar nesneye özeldir. Bu şekilde, çağrıldığı her örnek için bir işlev veya yöntem bağımsız olarak izlenir.

Yeniden izlemeyi kontrol etme

Function birden fazla iz oluşturduğu zaman olan yeniden izleme, TensorFlow'un her 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çin input_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 görüntüleriniz 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 veya training=True veya nonlinearity='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ürlerle 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ının somut bir fonksiyonun girdi imzasında özel bir 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ğunu tf.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.928048491 0.537333608 0.319427252 0.414729953 0.138620138]
[0.729682684 0.490966946 0.308988899 0.392481416 0.137739]
[0.62287122 0.454983532 0.299516946 0.373497456 0.136874482]
[0.553123951 0.425986826 0.290870458 0.357047111 0.13602607]
[0.502857924 0.401961982 0.282935768 0.342610359 0.135193244]
[0.464361787 0.381626487 0.27562 0.329805791 0.134375557]
[0.433632493 0.364119112 0.268846452 0.318346262 0.133572534]
[0.408352554 0.348837078 0.262551099 0.308010817 0.132783771]
[0.387072921 0.335343778 0.256680071 0.298626363 0.132008836]
[0.368834078 0.32331419 0.251187652 0.290055037 0.131247327]
[0.352971435 0.312500536 0.246034727 0.282185435 0.130498841]
[0.339008093 0.302710205 0.241187632 0.274926543 0.129763052]
[0.326591551 0.293790847 0.236617178 0.26820302 0.129039586]
[0.315454811 0.285620153 0.232297987 0.261951953 0.128328085]
[0.305391371 0.278098613 0.228207797 0.256120354 0.127628237]
[0.296238661 0.27114439 0.224326983 0.250663161 0.126939729]
[0.287866682 0.264689356 0.220638305 0.245541915 0.126262262]
[0.280170113 0.25867638 0.217126325 0.240723446 0.12559554]
[0.273062497 0.253057063 0.213777393 0.236178935 0.124939285]
[0.266472191 0.247790173 0.210579231 0.231883332 0.124293216]
[0.260339141 0.242840245 0.207520843 0.227814704 0.12365707]
[0.254612684 0.238176659 0.204592302 0.223953649 0.123030603]
[0.249249727 0.23377277 0.201784685 0.220283121 0.122413576]
[0.244213238 0.229605287 0.199089885 0.216787875 0.12180575]
<tf.Tensor: shape=(5,), dtype=float32, numpy=
array([0.23947136, 0.22565375, 0.19650048, 0.21345437, 0.12120689],
      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:

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. o zaman 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.8216245 , 0.29562855, 0.379112  , 0.49940717],
        [1.6473945 , 1.039927  , 1.3268942 , 0.5298227 ],
        [2.4393063 , 1.1283967 , 2.087479  , 1.2748951 ]],

       [[0.08016336, 0.73864746, 0.33738315, 0.4542967 ],
        [0.7459605 , 1.307698  , 1.1588445 , 0.9293362 ],
        [1.3752056 , 1.6133544 , 1.8199729 , 1.7356051 ]]], 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 çalıştırabilir 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 olur.

external_list = []

@tf.function
def side_effect(x):
  print('Python side effect')
  external_list.append(x)

side_effect(1)
side_effect(1)
side_effect(1)
# The list append only happened once!
assert len(external_list) == 1
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

Tıpkı 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. 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 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) i ç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 .