Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Grafiklere ve tf fonksiyonlarına giriş

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

Genel Bakış

Bu kılavuz, TensorFlow'un nasıl çalıştığını görmek için TensorFlow ve Keras yüzeyinin altına iner. Bunun yerine Keras'ı hemen kullanmaya başlamak istiyorsanız, lütfen Keras kılavuzları koleksiyonumuza bakın.

Bu kılavuzda, TensorFlow'un grafik almak için kodunuzda basit değişiklikler yapmanıza nasıl izin verdiğini, bunların nasıl saklanıp temsil edildiğini ve modellerinizi hızlandırmak ve dışa aktarmak için bunları nasıl kullanabileceğinizi göreceksiniz.

Bu kısa biçimli bir giriştir; bu kavramlara tam bir giriş için , tf.function kılavuzuna bakın .

Grafik nedir?

Önceki üç kılavuzda, TensorFlow'un hevesle çalıştığını gördünüz. Bu, TensorFlow işlemlerinin Python tarafından yürütüldüğü, işlem başına işlem yapıldığı ve sonuçları Python'a geri döndürdüğü anlamına gelir. Eager TensorFlow, GPU'lardan yararlanarak değişkenleri, tensörleri ve hatta işlemleri GPU'lara ve TPU'lara yerleştirmenize olanak tanır. Hata ayıklamak da kolaydır.

Bazı kullanıcılar için Python'a asla ihtiyaç duymayabilir veya Python'dan ayrılmak istemeyebilirsiniz.

Bununla birlikte, Python'da TensorFlow op-by-op çalıştırmak, aksi takdirde mevcut olan bir dizi hızlandırmayı engeller. Python'dan tensör hesaplamalarını çıkarabilirseniz, bunları bir grafiğe dönüştürebilirsiniz.

Grafikler, hesaplama birimlerini temsil eden bir dizi tf.Operation nesnesi içeren veri yapılarıdır; ve işlemler arasında akan veri birimlerini temsil eden tf.Tensor nesneleri. Bir tf.Graph bağlamında tanımlanırlar. Bu grafikler veri yapıları olduğundan, orijinal Python kodu olmadan kaydedilebilir, çalıştırılabilir ve geri yüklenebilir.

Bu, TensorBoard'da görselleştirildiğinde basit bir iki katmanlı grafiğin nasıl göründüğüdür.

iki katmanlı tensorflow grafiği

Grafiklerin faydaları

Bir grafikle, büyük bir esnekliğe sahipsiniz. TensorFlow grafiğinizi, mobil uygulamalar, gömülü aygıtlar ve arka uç sunucuları gibi Python yorumlayıcısı olmayan ortamlarda kullanabilirsiniz. TensorFlow, grafikleri Python'dan dışa aktardığında kaydedilen modeller için format olarak kullanır.

Grafikler de kolayca optimize edilerek derleyicinin aşağıdaki gibi dönüşümler yapmasına olanak tanır:

  • Hesaplamanızda sabit düğümleri katlayarak ("sabit bölme") tensörlerin değerini statik olarak çıkarın.
  • Bir hesaplamanın bağımsız olan alt bölümlerini ayırın ve bunları iş parçacıkları veya aygıtlar arasında ayırın.
  • Yaygın alt ifadeleri ortadan kaldırarak aritmetik işlemleri basitleştirin.

Bunu ve diğer hızlandırmaları gerçekleştirmek için tam bir optimizasyon sistemi, Grappler var .

Kısacası, grafikler son derece kullanışlıdır ve TensorFlow'unuzun hızlı çalışmasına , paralel çalışmasına ve birden çok cihazda verimli şekilde çalışmasına izin verir .

Bununla birlikte, yine de kolaylık sağlamak için makine öğrenimi modellerimizi (veya diğer hesaplamaları) Python'da tanımlamak ve daha sonra ihtiyacınız olduğunda otomatik olarak grafikler oluşturmak istiyorsunuz.

Grafikleri izleme

Eğer TensorFlow bir grafik oluşturmak yolu kullanmaktır tf.function doğrudan çağrı olarak veya bir dekoratör olarak ister.

import tensorflow as tf
import timeit
from datetime import datetime
# Define a Python function
def function_to_get_faster(x, y, b):
  x = tf.matmul(x, y)
  x = x + b
  return x

# Create a `Function` object that contains a graph
a_function_that_uses_a_graph = tf.function(function_to_get_faster)

# Make some tensors
x1 = tf.constant([[1.0, 2.0]])
y1 = tf.constant([[2.0], [3.0]])
b1 = tf.constant(4.0)

# It just works!
a_function_that_uses_a_graph(x1, y1, b1).numpy()
array([[12.]], dtype=float32)

tf.function -ized işlevler, Python eşdeğerleriyle aynı şekilde çalışan Python çağrılabilirleridir . Belirli bir sınıfları vardır ( python.eager.def_function.Function ), ancak sizin için izlenmeyen sürüm olarak hareket ederler.

tf.function , çağırdığı herhangi bir Python işlevini özyinelemeli olarak izler.

def inner_function(x, y, b):
  x = tf.matmul(x, y)
  x = x + b
  return x

# Use the decorator
@tf.function
def outer_function(x):
  y = tf.constant([[2.0], [3.0]])
  b = tf.constant(4.0)

  return inner_function(x, y, b)

# Note that the callable will create a graph that
# includes inner_function() as well as outer_function()
outer_function(tf.constant([[1.0, 2.0]])).numpy()
array([[12.]], dtype=float32)

TensorFlow 1.x kullandıysanız, hiçbir zaman bir Placeholder veya tf.Sesssion . tf.Sesssion tanımlamanıza gerek olmadığını fark tf.Sesssion .

Akış kontrolü ve yan etkiler

Akış denetimi ve döngüleri, varsayılan olarak tf.autograph aracılığıyla tf.autograph dönüştürülür. İmza, döngü yapılarını standartlaştırma, rulo açma ve AST manipülasyonu dahil olmak üzere bir yöntem kombinasyonu kullanır.

def my_function(x):
  if tf.reduce_sum(x) <= 1:
    return x * x
  else:
    return x-1

a_function = tf.function(my_function)

print("First branch, with graph:", a_function(tf.constant(1.0)).numpy())
print("Second branch, with graph:", a_function(tf.constant([5.0, 5.0])).numpy())
First branch, with graph: 1.0
Second branch, with graph: [4. 4.]

Python'un TensorFlow işlemlerine nasıl dönüştürüldüğünü görmek için doğrudan Autograph dönüşümünü çağırabilirsiniz. Bu, çoğunlukla okunamaz, ancak dönüşümü görebilirsiniz.

# Don't read the output too carefully.
print(tf.autograph.to_code(my_function))
def tf__my_function(x):
    with ag__.FunctionScope('my_function', 'fscope', ag__.ConversionOptions(recursive=True, user_requested=True, optional_features=(), internal_convert_user_code=True)) as fscope:
        do_return = False
        retval_ = ag__.UndefinedReturnValue()

        def get_state():
            return (do_return, retval_)

        def set_state(vars_):
            nonlocal do_return, retval_
            (do_return, retval_) = vars_

        def if_body():
            nonlocal do_return, retval_
            try:
                do_return = True
                retval_ = (ag__.ld(x) * ag__.ld(x))
            except:
                do_return = False
                raise

        def else_body():
            nonlocal do_return, retval_
            try:
                do_return = True
                retval_ = (ag__.ld(x) - 1)
            except:
                do_return = False
                raise
        ag__.if_stmt((ag__.converted_call(ag__.ld(tf).reduce_sum, (ag__.ld(x),), None, fscope) <= 1), if_body, else_body, get_state, set_state, ('do_return', 'retval_'), 2)
        return fscope.ret(retval_, do_return)


İmza, if-then cümlelerini, döngüleri, break , return , continue ve daha fazlasını otomatik olarak dönüştürür.

Çoğu zaman, Autograph özel bir husus olmadan çalışacaktır. Bununla birlikte, bazı uyarılar vardır ve tf.fonksiyon kılavuzu , tam imza referansının yanı sıra burada yardımcı olabilir.

Hızı görmek

Sadece tensör kullanan bir işlevi tf.function , kodunuzu otomatik olarak hızlandırmaz. Tek bir makinede birkaç kez çağrılan küçük işlevler için, bir grafik veya grafik parçasını çağırmanın ek yükü çalışma süresine hakim olabilir. Ayrıca, hesaplamaların çoğu GPU ağırlıklı evrişim yığınları gibi bir hızlandırıcıda zaten yapılıyorsa, grafik hızlandırma büyük olmayacaktır.

Karmaşık hesaplamalar için, grafikler önemli bir hızlanma sağlayabilir. Bunun nedeni, grafiklerin Python'dan cihaza iletişimi azaltması ve bazı hızlandırmalar gerçekleştirmesidir.

Hızlanma, aşağıdaki örnekte olduğu gibi, birçok küçük katmanı çalıştırırken en belirgindir:

# Create an oveerride model to classify pictures
class SequentialModel(tf.keras.Model):
  def __init__(self, **kwargs):
    super(SequentialModel, self).__init__(**kwargs)
    self.flatten = tf.keras.layers.Flatten(input_shape=(28, 28))
    # Add a lot of small layers
    num_layers = 100
    self.my_layers = [tf.keras.layers.Dense(64, activation="relu")
                      for n in range(num_layers)]
    self.dropout = tf.keras.layers.Dropout(0.2)
    self.dense_2 = tf.keras.layers.Dense(10)

  def call(self, x):
    x = self.flatten(x)
    for layer in self.my_layers:
      x = layer(x)
    x = self.dropout(x)
    x = self.dense_2(x)
    return x
input_data = tf.random.uniform([20, 28, 28])
eager_model = SequentialModel()

# Don't count the time for the initial build.
eager_model(input_data)
print("Eager time:", timeit.timeit(lambda: eager_model(input_data), number=100))
Eager time: 2.185799148000001

# Wrap the call method in a `tf.function`
graph_model = SequentialModel()
graph_model.call = tf.function(graph_model.call)

# Don't count the time for the initial build and trace.
graph_model(input_data)
print("Graph time:", timeit.timeit(lambda: graph_model(input_data), number=100))
Graph time: 0.30396231500003523

Polimorfik fonksiyonlar

Bir işlevi izlediğinizde , polimorfik olan bir Function nesnesi oluşturursunuz. Polimorfik bir işlev, bir API'nin arkasında birkaç somut işlev grafiğini kapsülleyen bir Python çağrılabilir özelliktir.

Bu Function tüm farklı dtypes ve şekillerde kullanabilirsiniz. Onu yeni bir bağımsız değişken imzasıyla her çağırdığınızda, orijinal işlev yeni bağımsız değişkenlerle yeniden izlenir. Function sonra depolayan tf.Graph bir o iz tekabül concrete_function . İşlev zaten bu tür bir argümanla izlenmişse, önceden izlenen grafiğinizi elde edersiniz.

O halde kavramsal olarak:

  • Bir tf.Graph , bir hesaplamayı tanımlayan ham, taşınabilir veri yapısıdır.
  • Bir Function , ConcreteFunctions üzerinden önbelleğe alma, izleme, dağıtıcıdır
  • ConcreteFunction , grafiği Python'dan çalıştırmanıza izin veren, bir grafiğin etrafındaki hevesle uyumlu bir sarmalayıcıdır.

Polimorfik fonksiyonları inceleme

Sen inceleyebilir a_function çağırarak sonucudur, tf.function Python fonksiyonu üzerinde my_function . Bu örnekte, a_function üç tür bağımsız değişkenle çağırmak, üç farklı somut işlevle sonuçlanır.

print(a_function)

print("Calling a `Function`:")
print("Int:", a_function(tf.constant(2)))
print("Float:", a_function(tf.constant(2.0)))
print("Rank-1 tensor of floats", a_function(tf.constant([2.0, 2.0, 2.0])))
<tensorflow.python.eager.def_function.Function object at 0x7f90cc28e4a8>
Calling a `Function`:
Int: tf.Tensor(1, shape=(), dtype=int32)
Float: tf.Tensor(1.0, shape=(), dtype=float32)
Rank-1 tensor of floats tf.Tensor([1. 1. 1.], shape=(3,), dtype=float32)

# Get the concrete function that works on floats
print("Inspecting concrete functions")
print("Concrete function for float:")
print(a_function.get_concrete_function(tf.TensorSpec(shape=[], dtype=tf.float32)))
print("Concrete function for tensor of floats:")
print(a_function.get_concrete_function(tf.constant([2.0, 2.0, 2.0])))
Inspecting concrete functions
Concrete function for float:
ConcreteFunction my_function(x)
  Args:
    x: float32 Tensor, shape=()
  Returns:
    float32 Tensor, shape=()
Concrete function for tensor of floats:
ConcreteFunction my_function(x)
  Args:
    x: float32 Tensor, shape=(3,)
  Returns:
    float32 Tensor, shape=(3,)

# Concrete functions are callable
# Note: You won't normally do this, but instead just call the containing `Function`
cf = a_function.get_concrete_function(tf.constant(2))
print("Directly calling a concrete function:", cf(tf.constant(2)))
Directly calling a concrete function: tf.Tensor(1, shape=(), dtype=int32)

Bu örnekte, yığının oldukça ilerisini görüyorsunuz. İzlemeyi özel olarak yönetmediğiniz sürece, normalde burada gösterildiği gibi somut işlevleri doğrudan çağırmanız gerekmez.

Hevesli uygulamaya geri dönüyoruz

Kendinizi uzun yığın izlerine bakarken bulabilirsiniz, özellikle tf.Graph veya with tf.Graph().as_default() . Bu, muhtemelen bir grafik bağlamında çalıştığınız anlamına gelir. TensorFlow'daki temel işlevler, Keras'ın model.fit() gibi grafik bağlamlarını kullanır.

İstekli yürütmede hata ayıklamak genellikle çok daha kolaydır. Yığın izleri nispeten kısa ve anlaşılması kolay olmalıdır.

Grafiğin hata ayıklamayı zorlaştırdığı durumlarda, hata ayıklamak için istekli yürütmeyi kullanmaya geri dönebilirsiniz.

İşte hevesle koştuğunuzdan emin olmanın yolları:

  • Modelleri ve katmanları doğrudan çağrılabilir olarak çağırın

  • model.compile(run_eagerly=True) compile / fit kullanırken, derleme zamanında model.compile(run_eagerly=True) kullanın model.compile(run_eagerly=True)

  • tf.config.run_functions_eagerly(True) aracılığıyla genel yürütme modunu ayarlayın

run_eagerly=True kullanma

# Define an identity layer with an eager side effect
class EagerLayer(tf.keras.layers.Layer):
  def __init__(self, **kwargs):
    super(EagerLayer, self).__init__(**kwargs)
    # Do some kind of initialization here

  def call(self, inputs):
    print("\nCurrently running eagerly", str(datetime.now()))
    return inputs
# Create an override model to classify pictures, adding the custom layer
class SequentialModel(tf.keras.Model):
  def __init__(self):
    super(SequentialModel, self).__init__()
    self.flatten = tf.keras.layers.Flatten(input_shape=(28, 28))
    self.dense_1 = tf.keras.layers.Dense(128, activation="relu")
    self.dropout = tf.keras.layers.Dropout(0.2)
    self.dense_2 = tf.keras.layers.Dense(10)
    self.eager = EagerLayer()

  def call(self, x):
    x = self.flatten(x)
    x = self.dense_1(x)
    x = self.dropout(x)
    x = self.dense_2(x)
    return self.eager(x)

# Create an instance of this model
model = SequentialModel()

# Generate some nonsense pictures and labels
input_data = tf.random.uniform([60, 28, 28])
labels = tf.random.uniform([60])

loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

İlk olarak, modeli istekli olmadan derleyin. Modelin izlenmediğini unutmayın; ismine rağmen, compile yalnızca kayıp işlevlerini, optimizasyonu ve diğer eğitim parametrelerini ayarlar.

model.compile(run_eagerly=False, loss=loss_fn)

Şimdi, fit çağırın ve fonksiyonun izlendiğini (iki kez) ve ardından istekli etkinin bir daha asla çalışmadığını görün.

model.fit(input_data, labels, epochs=3)
Epoch 1/3

Currently running eagerly 2021-01-13 02:25:36.809205

Currently running eagerly 2021-01-13 02:25:36.941800
2/2 [==============================] - 0s 3ms/step - loss: 2.0352
Epoch 2/3
2/2 [==============================] - 0s 3ms/step - loss: 0.0045
Epoch 3/3
2/2 [==============================] - 0s 2ms/step - loss: 0.0026

<tensorflow.python.keras.callbacks.History at 0x7f90102f2550>

Ancak tek bir dönemi bile hevesle çalıştırırsanız, istekli yan etkiyi iki kez görebilirsiniz.

print("Running eagerly")
# When compiling the model, set it to run eagerly
model.compile(run_eagerly=True, loss=loss_fn)

model.fit(input_data, labels, epochs=1)
Running eagerly

Currently running eagerly 2021-01-13 02:25:37.173159
1/2 [==============>...............] - ETA: 0s - loss: 0.0023
Currently running eagerly 2021-01-13 02:25:37.195392
2/2 [==============================] - 0s 13ms/step - loss: 0.0016

<tensorflow.python.keras.callbacks.History at 0x7f90101981d0>

run_functions_eagerly kullanma

Ayrıca global olarak her şeyi hevesle çalışacak şekilde ayarlayabilirsiniz. Bu, polimorfik işlevin izlenen işlevlerini atlayan ve orijinal işlevi doğrudan çağıran bir anahtardır. Bunu hata ayıklamak için kullanabilirsiniz.

# Now, globally set everything to run eagerly
tf.config.run_functions_eagerly(True)
print("Run all functions eagerly.")

# Create a polymorphic function
polymorphic_function = tf.function(model)

print("Tracing")
# This does, in fact, trace the function
print(polymorphic_function.get_concrete_function(input_data))

print("\nCalling twice eagerly")
# When you run the function again, you will see the side effect
# twice, as the function is running eagerly.
result = polymorphic_function(input_data)
result = polymorphic_function(input_data)
Run all functions eagerly.
Tracing

Currently running eagerly 2021-01-13 02:25:37.594444
ConcreteFunction function(self)
  Args:
    self: float32 Tensor, shape=(60, 28, 28)
  Returns:
    float32 Tensor, shape=(60, 10)

Calling twice eagerly

Currently running eagerly 2021-01-13 02:25:37.600183

Currently running eagerly 2021-01-13 02:25:37.602196

# Don't forget to set it back when you are done
tf.config.experimental_run_functions_eagerly(False)
WARNING:tensorflow:From <ipython-input-1-782fe9ce7b18>:2: experimental_run_functions_eagerly (from tensorflow.python.eager.def_function) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.config.run_functions_eagerly` instead of the experimental version.

İzleme ve performans

İzleme bazı ek yüklere mal olur. Küçük işlevlerin izini sürmek hızlı olsa da, büyük modellerin izini sürmek fark edilebilir bir duvar saati süresi alabilir. Bu yatırım genellikle performans artışı ile hızlı bir şekilde geri ödenir, ancak herhangi bir büyük model eğitiminin ilk birkaç döneminin izleme nedeniyle daha yavaş olabileceğinin farkında olmak önemlidir.

Modeliniz ne kadar büyük olursa olsun, sık sık takip etmekten kaçınmak istersiniz. Tf.function kılavuzunun bu bölümünde, giriş özelliklerinin nasıl ayarlanacağı ve yeniden izlemeyi önlemek için tensör argümanlarının nasıl kullanılacağı anlatılmaktadır. Alışılmadık derecede düşük performans aldığınızı fark ederseniz, yanlışlıkla geri dönüp takip etmediğinizi kontrol etmek iyidir.

Yalnızca hevesli bir yan etki (Python bağımsız değişkeninin yazdırılması gibi) ekleyebilirsiniz, böylece işlevin ne zaman izlendiğini görebilirsiniz. Burada, fazladan yeniden izleme görüyorsunuz çünkü yeni Python argümanları her zaman yeniden izlemeyi tetikler.

# Use @tf.function decorator
@tf.function
def a_function_with_python_side_effect(x):
  print("Tracing!")  # This eager
  return x * x + tf.constant(2)

# This is traced the first time
print(a_function_with_python_side_effect(tf.constant(2)))
# The second time through, you won't see the side effect
print(a_function_with_python_side_effect(tf.constant(3)))

# This retraces each time the Python argument changes,
# as a Python argument could be an epoch count or other
# hyperparameter
print(a_function_with_python_side_effect(2))
print(a_function_with_python_side_effect(3))
Tracing!
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(11, shape=(), dtype=int32)
Tracing!
tf.Tensor(6, shape=(), dtype=int32)
Tracing!
tf.Tensor(11, shape=(), dtype=int32)

Sonraki adımlar

Sen hem de daha derinlemesine tartışma okuyabilir tf.function API başvuru sayfası ve en rehber .