ML Topluluk Günü 9 Kasım! TensorFlow, JAX güncellemeler için bize katılın ve daha fazla bilgi edinin

hevesli yürütme

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Not defterini indir

TensorFlow'un istekli yürütmesi, işlemleri grafikler oluşturmadan hemen değerlendiren zorunlu bir programlama ortamıdır: işlemler daha sonra çalıştırılacak bir hesaplama grafiği oluşturmak yerine somut değerler döndürür. Bu, TensorFlow ve hata ayıklama modellerini kullanmaya başlamayı kolaylaştırır ve aynı zamanda ortak kullanım plakasını da azaltır. Bu kılavuz ile birlikte takip interaktif aşağıda kod örnekleri çalıştırmak için python tercüman.

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

  • Kodunuzdaki -Yapı Sezgisel bir arayüz doğal ve Python veri yapılarını kullanır. Küçük modeller ve küçük veriler üzerinde hızla yineleme yapın.
  • Daha kolay çalışan modelleri ve test değişiklikleri kontrol doğrudan -Başlangıç ops ayıklama. Anında hata raporlaması için standart Python hata ayıklama araçlarını kullanın.
  • Doğal kontrol dinamik modelleri özellikleri basitleştirilmesi, grafik kontrol akımının yerine Use Python kontrol akım.

İstekli yürütme, çoğu TensorFlow işlemini ve GPU hızlandırmasını 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 etkinleştirilmiştir.

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 hemen değerlendirir ve değerlerini Python'a döndürür. tf.Tensor bir hesaplama düğümleri grafikte referans beton değerleri yerine sembolik kulplar nesneleri. Bir hesaplama sürüme grafiği ve daha sonra bir oturumda çalıştırmak olmadığı için, bu kullanarak sonuçları incelemek kolaydır print() veya debugger. Tensör değerlerinin değerlendirilmesi, yazdırılması ve kontrol edilmesi, gradyan hesaplama akışını bozmaz.

Hevesli yürütme ile güzel çalışıyor numpy . NumPy işlemleri kabul tf.Tensor argümanlar. TensorFlow tf.math için operasyonlar Python nesneleri ve NumPy diziler dönüştürmek tf.Tensor nesneleri. tf.Tensor.numpy yöntemi NumPy olarak nesnenin bir değer verir 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 önemli bir yararı, modeliniz yürütülürken ana bilgisayar dilinin tüm işlevlerinin kullanılabilir olmasıdır. Yani, örneğin, yazma kolaydır fizzbuzz :

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

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

hevesli eğitim

gradyanları hesaplama

Otomatik farklılaşma gibi makineyi algoritmaları öğrenme uygulamak için yararlıdır geri yayılım sinir ağları eğitimi için. İstekli çalışması esnasında, kullanımı tf.GradientTape sonra gradyanları hesaplanması için işlemleri takip etmek.

Sen kullanabilirsiniz tf.GradientTape istekli ve / veya hesaplama geçişlerini yetiştirmek. Özellikle karmaşık eğitim döngüleri için kullanışlıdır.

Her arama sırasında farklı işlemler yapılabileceğinden, tüm ileri geçiş işlemleri bir "kaset"e kaydedilir. Degradeyi hesaplamak için bandı geriye doğru oynatın ve ardından atın. Belirli bir tf.GradientTape sadece 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)

Model eğit

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)
# 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 olmadan bile, modeli arayın ve çıktıyı istekli yürütmede inceleyin:

for images,labels in dataset.take(1):
  print("Logits: ", mnist_model(images[0:1]).numpy())
Logits:  [[-0.01775933 -0.01194787 -0.08372174 -0.06535977  0.00338565 -0.01974326
  -0.04763228  0.00904049 -0.00144051 -0.01944664]]

Keras modelleri bir yerleşik eğitim döngü (kullanırken varken fit yöntemi), bazen fazla özelleştirme gerekir. İşte istekli ile uygulanan bir eğitim döngüsü örneği:

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 objelerin değişken saklamak tf.Tensor kolay otomatik farklılaşma yapmak eğitim sırasında erişilen değerlere -ister.

Değişken koleksiyonları, üzerlerinde çalışan yöntemlerle birlikte katmanlara veya modellere kapsüllenebilir. Bkz Özel Keras katmanları ve modelleri detaylar için. Tabakalar ve model arasındaki ana fark modelleri gibi yöntemleri eklemek olmasıdır Model.fit , Model.evaluate ve Model.save .

Örneğin, yukarıdaki otomatik farklılaşma ö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ı 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: 69.909
Loss at step 000: 67.145
Loss at step 020: 30.170
Loss at step 040: 13.859
Loss at step 060: 6.659
Loss at step 080: 3.479
Loss at step 100: 2.074
Loss at step 120: 1.453
Loss at step 140: 1.178
Loss at step 160: 1.056
Loss at step 180: 1.003
Loss at step 200: 0.979
Loss at step 220: 0.968
Loss at step 240: 0.963
Loss at step 260: 0.961
Loss at step 280: 0.960
print("Final loss: {:.3f}".format(loss(model, training_inputs, training_outputs)))
Final loss: 0.960
print("W = {}, B = {}".format(model.W.numpy(), model.B.numpy()))
W = 2.9515867233276367, B = 2.0210201740264893

Nesne tabanlı kaydetme

Bir tf.keras.Model elverişli içerir save_weights kolayca bir kontrol noktası oluşturmak için izin yöntemini:

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

Kullanımı tf.train.Checkpoint Bu işlemle üzerinde tam kontrol alabilir.

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

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(checkpoint_path)
'./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>

Kaydetmek ve yük modelleri, To tf.train.Checkpoint gizli değişkenleri gerektirmeden, nesnelerin iç durumunu saklar. Bir durumunu kaydetmek için model , bir optimizer onları geçmek, ve küresel adım 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 0x7f4ba0648310>

Nesneye yönelik metrikler

tf.keras.metrics nesneler olarak depolanır. Çağrılabilir yeni veri geçirerek bir metrik güncelleyin ve kullanma sonucu almak tf.keras.metrics.result örneğin, yöntem:

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 , anlayış ayıklama ve model eğitim sürecini optimize etmek için bir görselleştirme aracıdır. Program yürütülürken yazılan özet olayları kullanır.

Sen kullanabilirsiniz tf.summary istekli yürütülmesinde değişkenin rekor özetleri için. Örneğin, özetlerini kaydetmeye loss Her 100 eğitim adımlarla kez:

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.1632342765.kokoro-gcp-ubuntu-prod-230753280.22287.0.v2

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

Dinamik modeller

tf.GradientTape dinamik modellerinde kullanılabilir. Bir Bu örnek backtracking hattı aramak karmaşık kontrol akışı rağmen geçişlerini vardır haricinde normal NumPy kodu gibi algoritma görünüyor ve ayırt edilebilirdir:

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 degradeler, degradeleri geçersiz kılmanın kolay bir yoludur. İleri işlevi içinde, girdilere, çıktılara veya ara sonuçlara göre gradyanı 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 fonksiyonu analitik özel bir degrade ile basitleştirilmiş olabilir. Tekrar kullanım aşağıdaki uygulama için değer tf.exp(x) ileri sırasında hesaplanır gereksiz hesaplamaları ortadan kaldırarak daha verimli geçişte verme:

@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

Hesaplama, istekli yürütme sırasında otomatik olarak GPU'lara yüklenir. Eğer bir hesaplama Eğer içine alın edebilir hale geldiğini üzerinde kontrol isterseniz tf.device('/gpu:0') bloğu (veya CPU eşdeğeri):

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.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: 1.007401466369629 secs
GPU: 0.04124784469604492 secs

Bir tf.Tensor nesne faaliyetlerini yürütmek için farklı bir cihaza kopyalanabilir:

if tf.config.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 /tmp/ipykernel_22287/406964202.py: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 /tmp/ipykernel_22287/406964202.py: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

Gibi işlem ağır modelleri için ResNet50 bir grafik işlemci performansı üzerinde eğitim, istekli yürütme performansı ile karşılaştırılabilir tf.function yürütme. Ancak bu boşluk, daha az hesaplamalı modeller için daha da büyür ve çok sayıda küçük işlem içeren modeller için etkin kod yollarını optimize etmek için yapılması gereken işler vardır.

İşlevlerle çalışma

İstekli yürütme, geliştirmeyi ve hata ayıklamayı daha etkileşimli hale getirirken, TensorFlow 1.x stili 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 amacıyla, TensorFlow 2.0 tanıtır function aracılığıyla s tf.function API. Daha fazla bilgi için, bkz tf.function kılavuzu.