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

Hevesli yürütme

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

TensorFlow'un istekli yürütmesi, grafikleri oluşturmadan işlemleri hemen değerlendiren zorunlu bir programlama ortamıdır: işlemler, daha sonra çalıştırmak için bir hesaplama grafiği oluşturmak yerine somut değerler döndürür. Bu, TensorFlow ve hata ayıklama modellerine başlamayı kolaylaştırır ve aynı zamanda ortak metini de azaltır. Bu kılavuzu takip etmek için aşağıdaki kod örneklerini etkileşimli bir python yorumlayıcıda çalıştırın.

İstekli yürütme, araştırma ve deneme için esnek bir makine öğrenimi platformudur ve şunları sağlar:

  • Sezgisel bir arayüz —Kodunuzu doğal bir şekilde yapılandırın ve Python veri yapılarını kullanın. Küçük modeller ve küçük veriler üzerinde hızla yineleme yapın.
  • Daha kolay hata ayıklama —Çalışan modelleri incelemek ve değişiklikleri test etmek için operasyonları doğrudan arayın. Anında hata bildirimi için standart Python hata ayıklama araçlarını kullanın.
  • Doğal kontrol akışı — Dinamik modellerin özelliklerini basitleştirerek grafik kontrol akışı yerine Python kontrol akışını kullanın.

İstekli yürütme, çoğu TensorFlow işlemini ve GPU hızlandırmayı destekler.

Kurulum ve temel kullanım

import os

import tensorflow as tf

import cProfile

Tensorflow 2.0'da, istekli yürütme varsayılan olarak etkindir.

tf.executing_eagerly()
True

Artık TensorFlow işlemlerini çalıştırabilirsiniz ve sonuçlar hemen dönecektir:

x = [[2.]]
m = tf.matmul(x, x)
print("hello, {}".format(m))
hello, [[4.]]

İstekli yürütmeyi etkinleştirmek, TensorFlow işlemlerinin nasıl davrandığını değiştirir - şimdi değerleri anında değerlendirip Python'a döndürürler. tf.Tensor nesneleri, hesaplama grafiğindeki düğümlere sembolik tutamaçlar yerine somut değerlere tf.Tensor . Bir oturumda daha sonra oluşturulacak ve çalıştırılacak bir hesaplama grafiği olmadığından, sonuçları print() veya bir hata ayıklayıcı kullanarak incelemek kolaydır. Tensör değerlerinin değerlendirilmesi, yazdırılması ve kontrol edilmesi degradeleri hesaplamak için akışı bozmaz.

Hevesli uygulama NumPy ile iyi çalışıyor . NumPy işlemleri tf.Tensor bağımsız değişkenlerini kabul tf.Tensor . TensorFlow tf.math işlemleri Python nesnelerini ve NumPy dizilerini tf.Tensor nesnelerine dönüştürür. tf.Tensor.numpy yöntemi, nesnenin değerini NumPy ndarray olarak ndarray .

a = tf.constant([[1, 2],
                 [3, 4]])
print(a)
tf.Tensor(
[[1 2]
 [3 4]], shape=(2, 2), dtype=int32)

# Broadcasting support
b = tf.add(a, 1)
print(b)
tf.Tensor(
[[2 3]
 [4 5]], shape=(2, 2), dtype=int32)

# Operator overloading is supported
print(a * b)
tf.Tensor(
[[ 2  6]
 [12 20]], shape=(2, 2), dtype=int32)

# Use NumPy values
import numpy as np

c = np.multiply(a, b)
print(c)
[[ 2  6]
 [12 20]]

# Obtain numpy value from a tensor:
print(a.numpy())
# => [[1 2]
#     [3 4]]
[[1 2]
 [3 4]]

Dinamik kontrol akışı

İstekli yürütmenin en büyük yararı, modeliniz yürütülürken ana bilgisayar dilinin tüm işlevlerinin kullanılabilir olmasıdır. Yani, örneğin fizzbuzz yazmak kolaydır :

def fizzbuzz(max_num):
  counter = tf.constant(0)
  max_num = tf.convert_to_tensor(max_num)
  for num in range(1, max_num.numpy()+1):
    num = tf.constant(num)
    if int(num % 3) == 0 and int(num % 5) == 0:
      print('FizzBuzz')
    elif int(num % 3) == 0:
      print('Fizz')
    elif int(num % 5) == 0:
      print('Buzz')
    else:
      print(num.numpy())
    counter += 1
fizzbuzz(15)
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

Bunun tensör değerlerine bağlı koşullara sahiptir ve bu değerleri çalışma zamanında yazdırır.

Hevesli eğitim

Degradeleri hesaplama

Otomatik farklılaştırma , sinir ağlarını eğitmek için geri yayılım gibi makine öğrenimi algoritmalarını uygulamak için yararlıdır. İstekli yürütme sırasında, degradeleri daha sonra hesaplamak için işlemleri izlemek üzere tf.GradientTape kullanın.

Degradeleri istekli bir şekilde eğitmek ve / veya hesaplamak için tf.GradientTape kullanabilirsiniz. Özellikle karmaşık eğitim döngüleri için kullanışlıdır.

Her arama sırasında farklı işlemler olabileceğinden, tüm iletme işlemleri bir "kasete" kaydedilir. Gradyanı hesaplamak için kaseti geriye doğru oynatın ve ardından atın. Belirli bir tf.GradientTape yalnızca bir gradyanı hesaplayabilir; sonraki çağrılar bir çalışma zamanı hatası verir.

w = tf.Variable([[1.0]])
with tf.GradientTape() as tape:
  loss = w * w

grad = tape.gradient(loss, w)
print(grad)  # => tf.Tensor([[ 2.]], shape=(1, 1), dtype=float32)
tf.Tensor([[2.]], shape=(1, 1), dtype=float32)

Bir model eğitin

Aşağıdaki örnek, standart MNIST el yazısı rakamlarını sınıflandıran çok katmanlı bir model oluşturur. İstekli bir yürütme ortamında eğitilebilir grafikler oluşturmak için optimize edici ve katman API'lerini gösterir.

# Fetch and format the mnist data
(mnist_images, mnist_labels), _ = tf.keras.datasets.mnist.load_data()

dataset = tf.data.Dataset.from_tensor_slices(
  (tf.cast(mnist_images[...,tf.newaxis]/255, tf.float32),
   tf.cast(mnist_labels,tf.int64)))
dataset = dataset.shuffle(1000).batch(32)
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step

# Build the model
mnist_model = tf.keras.Sequential([
  tf.keras.layers.Conv2D(16,[3,3], activation='relu',
                         input_shape=(None, None, 1)),
  tf.keras.layers.Conv2D(16,[3,3], activation='relu'),
  tf.keras.layers.GlobalAveragePooling2D(),
  tf.keras.layers.Dense(10)
])

Eğitim olmasa bile modeli arayın ve çıktıyı istekli bir şekilde inceleyin:

for images,labels in dataset.take(1):
  print("Logits: ", mnist_model(images[0:1]).numpy())
Logits:  [[-0.04126375  0.03160043 -0.07807496 -0.10245611  0.02141886 -0.00049652
  -0.07772101  0.06026737  0.05762767 -0.10979556]]

Keras modellerinde yerleşik bir eğitim döngüsü varken ( fit yöntemini kullanarak), bazen daha fazla özelleştirmeye ihtiyacınız vardır. İşte hevesle uygulanan bir eğitim döngüsüne bir örnek:

optimizer = tf.keras.optimizers.Adam()
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

loss_history = []
def train_step(images, labels):
  with tf.GradientTape() as tape:
    logits = mnist_model(images, training=True)
    
    # Add asserts to check the shape of the output.
    tf.debugging.assert_equal(logits.shape, (32, 10))
    
    loss_value = loss_object(labels, logits)

  loss_history.append(loss_value.numpy().mean())
  grads = tape.gradient(loss_value, mnist_model.trainable_variables)
  optimizer.apply_gradients(zip(grads, mnist_model.trainable_variables))
def train(epochs):
  for epoch in range(epochs):
    for (batch, (images, labels)) in enumerate(dataset):
      train_step(images, labels)
    print ('Epoch {} finished'.format(epoch))
train(epochs = 3)
Epoch 0 finished
Epoch 1 finished
Epoch 2 finished

import matplotlib.pyplot as plt

plt.plot(loss_history)
plt.xlabel('Batch #')
plt.ylabel('Loss [entropy]')
Text(0, 0.5, 'Loss [entropy]')

png

Değişkenler ve optimize ediciler

tf.Variable nesneler, otomatik farklılaştırmayı kolaylaştırmak için eğitim sırasında erişilen değişken tf.Tensor benzeri değerleri depolar.

Değişken koleksiyonları, üzerinde çalışan yöntemlerle birlikte katmanlar veya modeller halinde kapsüllenebilir. Ayrıntılar için Özel Keras katmanları ve modellerine bakın. Katmanlar ve modeller arasındaki temel fark, modellerin Model.fit , Model.evaluate ve Model.save gibi yöntemler Model.save .

Örneğin, yukarıdaki otomatik farklılaştırma örneği yeniden yazılabilir:

class Linear(tf.keras.Model):
  def __init__(self):
    super(Linear, self).__init__()
    self.W = tf.Variable(5., name='weight')
    self.B = tf.Variable(10., name='bias')
  def call(self, inputs):
    return inputs * self.W + self.B
# A toy dataset of points around 3 * x + 2
NUM_EXAMPLES = 2000
training_inputs = tf.random.normal([NUM_EXAMPLES])
noise = tf.random.normal([NUM_EXAMPLES])
training_outputs = training_inputs * 3 + 2 + noise

# The loss function to be optimized
def loss(model, inputs, targets):
  error = model(inputs) - targets
  return tf.reduce_mean(tf.square(error))

def grad(model, inputs, targets):
  with tf.GradientTape() as tape:
    loss_value = loss(model, inputs, targets)
  return tape.gradient(loss_value, [model.W, model.B])

Sonraki:

  1. Modeli oluşturun.
  2. Model parametrelerine göre bir kayıp fonksiyonunun Türevleri.
  3. Türevlere dayalı olarak değişkenleri güncellemek için bir strateji.
model = Linear()
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)

print("Initial loss: {:.3f}".format(loss(model, training_inputs, training_outputs)))

steps = 300
for i in range(steps):
  grads = grad(model, training_inputs, training_outputs)
  optimizer.apply_gradients(zip(grads, [model.W, model.B]))
  if i % 20 == 0:
    print("Loss at step {:03d}: {:.3f}".format(i, loss(model, training_inputs, training_outputs)))
Initial loss: 68.274
Loss at step 000: 65.640
Loss at step 020: 30.091
Loss at step 040: 14.106
Loss at step 060: 6.914
Loss at step 080: 3.677
Loss at step 100: 2.218
Loss at step 120: 1.561
Loss at step 140: 1.264
Loss at step 160: 1.130
Loss at step 180: 1.070
Loss at step 200: 1.043
Loss at step 220: 1.030
Loss at step 240: 1.025
Loss at step 260: 1.022
Loss at step 280: 1.021

print("Final loss: {:.3f}".format(loss(model, training_inputs, training_outputs)))
Final loss: 1.021

print("W = {}, B = {}".format(model.W.numpy(), model.B.numpy()))
W = 2.997738838195801, B = 2.018033742904663

Nesne tabanlı tasarruf

Bir tf.keras.Model , kolayca bir kontrol noktası oluşturmanıza olanak tanıyan uygun bir kaydetme save_weights yöntemi içerir:

model.save_weights('weights')
status = model.load_weights('weights')

tf.train.Checkpoint kullanarak bu işlem üzerinde tam kontrol sahibi olabilirsiniz.

Bu bölüm, eğitim kontrol noktaları kılavuzunun kısaltılmış bir versiyonudur.

x = tf.Variable(10.)
checkpoint = tf.train.Checkpoint(x=x)
x.assign(2.)   # Assign a new value to the variables and save.
checkpoint_path = './ckpt/'
checkpoint.save('./ckpt/')
'./ckpt/-1'
x.assign(11.)  # Change the variable after saving.

# Restore values from the checkpoint
checkpoint.restore(tf.train.latest_checkpoint(checkpoint_path))

print(x)  # => 2.0
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=2.0>

Modelleri kaydetmek ve yüklemek için tf.train.Checkpoint , gizli değişkenler gerektirmeden nesnelerin dahili durumunu depolar. Bir model durumunu, bir optimizer tf.train.Checkpoint ve bir genel adımı kaydetmek için bunları bir tf.train.Checkpoint :

model = tf.keras.Sequential([
  tf.keras.layers.Conv2D(16,[3,3], activation='relu'),
  tf.keras.layers.GlobalAveragePooling2D(),
  tf.keras.layers.Dense(10)
])
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
checkpoint_dir = 'path/to/model_dir'
if not os.path.exists(checkpoint_dir):
  os.makedirs(checkpoint_dir)
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt")
root = tf.train.Checkpoint(optimizer=optimizer,
                           model=model)

root.save(checkpoint_prefix)
root.restore(tf.train.latest_checkpoint(checkpoint_dir))
<tensorflow.python.training.tracking.util.CheckpointLoadStatus at 0x7f88ef2e99e8>

Nesneye yönelik ölçümler

tf.keras.metrics nesneler olarak saklanır. Yeni verileri çağrılabilir veriye ileterek bir metriği güncelleyin ve sonucu tf.keras.metrics.result yöntemini kullanarak tf.keras.metrics.result , örneğin:

m = tf.keras.metrics.Mean("loss")
m(0)
m(5)
m.result()  # => 2.5
m([8, 9])
m.result()  # => 5.5
<tf.Tensor: shape=(), dtype=float32, numpy=5.5>

Özetler ve TensorBoard

TensorBoard , model eğitim sürecini anlamak, hata ayıklamak ve optimize etmek için bir görselleştirme aracıdır. Programı çalıştırırken yazılan özet olayları kullanır.

İstekli çalıştırmada değişkenlerin özetlerini kaydetmek için tf.summary kullanabilirsiniz. Örneğin, her 100 eğitim adımında bir loss özetini kaydetmek için:

logdir = "./tb/"
writer = tf.summary.create_file_writer(logdir)

steps = 1000
with writer.as_default():  # or call writer.set_as_default() before the loop.
  for i in range(steps):
    step = i + 1
    # Calculate loss with your real train function.
    loss = 1 - 0.001 * step
    if step % 100 == 0:
      tf.summary.scalar('loss', loss, step=step)
ls tb/
events.out.tfevents.1599701382.kokoro-gcp-ubuntu-prod-2031910853.25648.619697.v2

Gelişmiş otomatik farklılaştırma konuları

Dinamik modeller

tf.GradientTape dinamik modellerde de kullanılabilir. Geriye dönük satır arama algoritması için bu örnek, gradyanların olması ve karmaşık kontrol akışına rağmen türevlenebilir olması dışında normal NumPy koduna benzer:

def line_search_step(fn, init_x, rate=1.0):
  with tf.GradientTape() as tape:
    # Variables are automatically tracked.
    # But to calculate a gradient from a tensor, you must `watch` it.
    tape.watch(init_x)
    value = fn(init_x)
  grad = tape.gradient(value, init_x)
  grad_norm = tf.reduce_sum(grad * grad)
  init_value = value
  while value > init_value - rate * grad_norm:
    x = init_x - rate * grad
    value = fn(x)
    rate /= 2.0
  return x, value

Özel degradeler

Özel renk geçişleri, degradeleri geçersiz kılmanın kolay bir yoludur. İleri işlevinde, gradyanı girdilere, çıktılara veya ara sonuçlara göre tanımlayın. Örneğin, geriye doğru geçişte degradelerin normunu kırpmanın kolay bir yolu:

@tf.custom_gradient
def clip_gradient_by_norm(x, norm):
  y = tf.identity(x)
  def grad_fn(dresult):
    return [tf.clip_by_norm(dresult, norm), None]
  return y, grad_fn

Özel gradyanlar, bir dizi işlem için sayısal olarak kararlı bir gradyan sağlamak için yaygın olarak kullanılır:

def log1pexp(x):
  return tf.math.log(1 + tf.exp(x))

def grad_log1pexp(x):
  with tf.GradientTape() as tape:
    tape.watch(x)
    value = log1pexp(x)
  return tape.gradient(value, x)

# The gradient computation works fine at x = 0.
grad_log1pexp(tf.constant(0.)).numpy()
0.5
# However, x = 100 fails because of numerical instability.
grad_log1pexp(tf.constant(100.)).numpy()
nan

Burada log1pexp işlevi, özel bir gradyan ile analitik olarak basitleştirilebilir. Aşağıdaki uygulama, ileri geçiş sırasında hesaplanan tf.exp(x) değerini yeniden kullanır ve bu, gereksiz hesaplamaları ortadan kaldırarak daha verimli hale getirir:

@tf.custom_gradient
def log1pexp(x):
  e = tf.exp(x)
  def grad(dy):
    return dy * (1 - 1 / (1 + e))
  return tf.math.log(1 + e), grad

def grad_log1pexp(x):
  with tf.GradientTape() as tape:
    tape.watch(x)
    value = log1pexp(x)
  return tape.gradient(value, x)

# As before, the gradient computation works fine at x = 0.
grad_log1pexp(tf.constant(0.)).numpy()
0.5
# And the gradient computation also works at x = 100.
grad_log1pexp(tf.constant(100.)).numpy()
1.0

Verim

İstekli yürütme sırasında hesaplama otomatik olarak GPU'lara aktarılır. Bir hesaplamanın nerede çalıştığını kontrol etmek istiyorsanız, bunu bir tf.device('/gpu:0') bloğuna (veya CPU eşdeğeri) içine alabilirsiniz:

import time

def measure(x, steps):
  # TensorFlow initializes a GPU the first time it's used, exclude from timing.
  tf.matmul(x, x)
  start = time.time()
  for i in range(steps):
    x = tf.matmul(x, x)
  # tf.matmul can return before completing the matrix multiplication
  # (e.g., can return after enqueing the operation on a CUDA stream).
  # The x.numpy() call below will ensure that all enqueued operations
  # have completed (and will also copy the result to host memory,
  # so we're including a little more than just the matmul operation
  # time).
  _ = x.numpy()
  end = time.time()
  return end - start

shape = (1000, 1000)
steps = 200
print("Time to multiply a {} matrix by itself {} times:".format(shape, steps))

# Run on CPU:
with tf.device("/cpu:0"):
  print("CPU: {} secs".format(measure(tf.random.normal(shape), steps)))

# Run on GPU, if available:
if tf.config.experimental.list_physical_devices("GPU"):
  with tf.device("/gpu:0"):
    print("GPU: {} secs".format(measure(tf.random.normal(shape), steps)))
else:
  print("GPU: not found")
Time to multiply a (1000, 1000) matrix by itself 200 times:
CPU: 0.9814188480377197 secs
GPU: 0.0416111946105957 secs

Bir tf.Tensor nesnesi, işlemlerini yürütmek için farklı bir cihaza kopyalanabilir:

if tf.config.experimental.list_physical_devices("GPU"):
  x = tf.random.normal([10, 10])

  x_gpu0 = x.gpu()
  x_cpu = x.cpu()

  _ = tf.matmul(x_cpu, x_cpu)    # Runs on CPU
  _ = tf.matmul(x_gpu0, x_gpu0)  # Runs on GPU:0
WARNING:tensorflow:From <ipython-input-43-876293b5769c>:4: _EagerTensorBase.gpu (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.identity instead.
WARNING:tensorflow:From <ipython-input-43-876293b5769c>:5: _EagerTensorBase.cpu (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.identity instead.

Kıyaslamalar

Bir GPU üzerinde ResNet50 eğitimi gibi bilgi işlem ağırlıklı modeller için, istekli yürütme performansı, tf.function . tf.function yürütme ile karşılaştırılabilir. Ancak bu boşluk, daha az hesaplamaya sahip modeller için daha da büyüyor ve çok sayıda küçük işlemi olan modeller için sıcak kod yollarını optimize etmek için yapılacak işler var.

İşlevlerle çalışın

İstekli yürütme, geliştirme ve hata ayıklamayı daha etkileşimli hale getirirken, TensorFlow 1.x tarzı grafik yürütme, dağıtılmış eğitim, performans optimizasyonları ve üretim dağıtımı için avantajlara sahiptir. Bu boşluğu doldurmak için TensorFlow 2.0, tf.function API aracılığıyla function tf.function . Daha fazla bilgi için tf işlev kılavuzuna bakın.