امروز برای رویداد محلی TensorFlow خود در همه جا پاسخ دهید!
این صفحه به‌وسیله ‏Cloud Translation API‏ ترجمه شده است.
Switch to English

اعدام با اشتیاق

مشاهده در TensorFlow.org در Google Colab اجرا کنید مشاهده منبع در GitHub دانلود دفترچه یادداشت

اجرای مشتاق TensorFlow یک محیط برنامه نویسی ضروری است که بدون ایجاد نمودار ، بلافاصله عملیات را ارزیابی می کند: عملیات به جای ساختن نمودار محاسباتی برای اجرای بعدی ، مقادیر مشخصی را برمی گرداند. این کار شروع به کار با مدل های TensorFlow و اشکال زدایی را آسان می کند ، و همچنین باعث کاهش دیگ بخار می شود. برای دنبال کردن این راهنما ، نمونه های کد زیر را در یک مفسر تعاملی python .

اعدام مشتاقانه یک پلت فرم انعطاف پذیر برای یادگیری ماشین برای تحقیق و آزمایش است ، فراهم می کند:

  • یک رابط بصری - کد خود را به طور طبیعی ساختار دهید و از ساختارهای داده Python استفاده کنید. به سرعت در مدل های کوچک و داده های کوچک تکرار کنید.
  • اشکال زدایی آسان تر - برای بررسی مدل های در حال اجرا و تغییرات آزمایشی مستقیماً تماس بگیرید. برای گزارش خطاهای فوری از ابزارهای اشکال زدایی استاندارد پایتون استفاده کنید.
  • جریان کنترل طبیعی - از جریان کنترل پایتون به جای جریان کنترل نمودار استفاده کنید ، مشخصات مدل های پویا را ساده می کند.

اجرای مشتاق از اکثر عملیات TensorFlow و شتاب GPU پشتیبانی می کند.

راه اندازی و کاربرد اصلی

import os

import tensorflow as tf

import cProfile

در Tensorflow 2.0 ، اجرای مشتاق به طور پیش فرض فعال است.

tf.executing_eagerly()
True

اکنون می توانید عملیات TensorFlow را اجرا کنید و نتایج بلافاصله باز می گردند:

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

فعال کردن اجرای اشتیاق نحوه عملکرد TensorFlow را تغییر می دهد - اکنون آنها بلافاصله مقادیر خود را ارزیابی و به پایتون برمی گردانند. tf.Tensor اجسام tf.Tensor به جای دسته های نمادین به گره ها در یک نمودار محاسباتی ، مقادیر بتن را ارجاع می دهند. از آنجا که نمودار محاسباتی برای ساختن و اجرای بعداً در یک جلسه وجود ندارد ، بازرسی نتایج با استفاده از print() یا اشکال زدایی آسان است. ارزیابی ، چاپ و بررسی مقادیر تانسور جریان شیب های محاسباتی را نمی شکند.

اعدام مشتاقانه با NumPy به راحتی کار می کند. عملیات NumPy آرگومان های tf.Tensor را می tf.Tensor . عملیات tf.math پایتون و آرایه های NumPy را به اشیا tf.Tensor می کند. روش tf.Tensor.numpy مقدار شی را به عنوان یک تقسیم NumPy 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]]

جریان کنترل پویا

یک مزیت عمده اجرای مشتاق این است که تمام عملکرد زبان میزبان هنگام اجرای مدل شما در دسترس است. بنابراین ، به عنوان مثال ، نوشتن 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

این دارای شرطی هایی است که به مقادیر تنسور بستگی دارد و این مقادیر را هنگام اجرا چاپ می کند.

آموزش مشتاقانه

شیب محاسبه

تمایز خودکار برای پیاده سازی الگوریتم های یادگیری ماشین مانند انتشار متقابل برای آموزش شبکه های عصبی مفید است. در هنگام اجرای مشتاقانه ، ازtf.GradientTape برای ردیابی عملیات محاسبات شیب ها بعداً استفاده کنید.

برای آموزش و / یا محاسبه شیب در مشتاقان می توانید ازtf.GradientTape استفاده کنید. به خصوص برای حلقه های آموزشی پیچیده بسیار مفید است.

از آنجا که در طی هر تماس می توان عملیات مختلفی را انجام داد ، همه عملیات انتقال به جلو در یک "نوار" ضبط می شود. برای محاسبه شیب ، نوار را به عقب پخش کنید و سپس دور بریزید. یکtf.GradientTape خاص فقط می تواند یک شیب را محاسبه کند. تماس های بعدی خطای زمان اجرا ایجاد می کند.

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)

یک مدل آموزش دهید

مثال زیر یک مدل چند لایه ایجاد می کند که ارقام دست نویس استاندارد MNIST را طبقه بندی می کند. این بهینه ساز و لایه های API را برای ایجاد نمودارهای قابل آموزش در یک محیط اجرای مشتاق نشان می دهد.

# 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)
])

حتی بدون آموزش ، با مدل تماس بگیرید و در اجرای مشتاقانه بازده را بررسی کنید:

for images,labels in dataset.take(1):
  print("Logits: ", mnist_model(images[0:1]).numpy())
Logits:  [[ 0.04267077 -0.02450868 -0.0284728   0.02962056  0.01268288 -0.02380248
   0.01629823  0.02717735  0.05674956 -0.02006865]]

در حالی که مدل های keras دارای یک حلقه آموزش داخلی هستند (با استفاده از روش fit ) ، گاهی اوقات شما نیاز به سفارشی سازی بیشتری دارید. در اینجا مثالی از حلقه آموزشی که با اشتیاق اجرا می شود آورده شده است:

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

متغیرها و بهینه سازها

tf.Variable اشیا tf.Tensor مقادیر قابل تغییر tf.Tensor کنند. مقادیر مانند tf.Tensor در طول آموزش برای سهولت در تمایز اتوماتیک قابل دسترسی است.

مجموعه متغیرها را می توان به همراه روشهایی که روی آنها کار می کنند ، در لایه ها یا مدلها قرار داد. برای جزئیات به لایه ها و مدلهای سفارشی Keras مراجعه کنید. تفاوت اصلی بین لایه ها و مدل ها این است که مدل ها روش هایی مانند Model.fit ، Model.evaluate و Model.save .

به عنوان مثال ، مثال تمایز اتوماتیک در بالا را می توان دوباره نوشت:

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])

بعد:

  1. مدل ایجاد کنید.
  2. مشتقات تابع ضرر با توجه به پارامترهای مدل.
  3. استراتژی به روزرسانی متغیرها بر اساس مشتقات.
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.134
Loss at step 000: 66.417
Loss at step 020: 29.994
Loss at step 040: 13.860
Loss at step 060: 6.713
Loss at step 080: 3.546
Loss at step 100: 2.143
Loss at step 120: 1.521
Loss at step 140: 1.246
Loss at step 160: 1.124
Loss at step 180: 1.070
Loss at step 200: 1.046
Loss at step 220: 1.035
Loss at step 240: 1.030
Loss at step 260: 1.028
Loss at step 280: 1.027

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

print("W = {}, B = {}".format(model.W.numpy(), model.B.numpy()))
W = 3.0401711463928223, B = 2.0334768295288086

پس انداز مبتنی بر شی

tf.keras.Model شامل یک روش save_weights مناسب است که به شما امکان می دهد به راحتی یک ایست بازرسی ایجاد کنید:

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

با استفاده از tf.train.Checkpoint می توانید کنترل کاملی بر این فرآیند داشته باشید.

این بخش نسخه خلاصه ای از راهنمای آموزش ایست های بازرسی است .

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>

برای ذخیره و بارگذاری مدل ها ، tf.train.Checkpoint بدون نیاز به متغیرهای پنهان ، حالت داخلی اشیا را ذخیره می کند. برای ثبت وضعیت یک model ، یک optimizer و یک مرحله جهانی ، آنها را به یک 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 0x7f9354a431d0>

معیارهای شی گرا

tf.keras.metrics به عنوان اشیا stored ذخیره می شوند. با انتقال داده های جدید به قابل تماس ، یک معیار را به روز کنید و نتیجه را با استفاده از روش tf.keras.metrics.result ، به عنوان مثال:

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>

خلاصه ها و TensorBoard

TensorBoard ابزاری برای تجسم ، درک اشکال زدایی و بهینه سازی روند آموزش مدل است. از وقایع خلاصه ای که هنگام اجرای برنامه نوشته شده اند استفاده می کند.

برای ثبت خلاصه های متغیر در اجرای مشتاق می توانید از tf.summary استفاده کنید. به عنوان مثال ، برای ثبت خلاصه از loss هر 100 مرحله آموزش یک بار:

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.1613010233.kokoro-gcp-ubuntu-prod-1675300897.1619.636510.v2

مباحث پیشرفته تمایز اتوماتیک

مدل های پویا

tf.GradientTape همچنین می تواند در مدل های پویا استفاده شود. این مثال برای الگوریتم جستجوی خط بازگشت به نظر می رسد مانند کد NumPy طبیعی است ، مگر اینکه شیب هایی وجود داشته باشد و با وجود جریان کنترل پیچیده ، قابل تغییر است:

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

شیب های سفارشی

شیب های سفارشی راهی آسان برای کنار زدن شیب ها است. درون تابع forward ، شیب را با توجه به ورودی ها ، خروجی ها یا نتایج میانی تعریف کنید. به عنوان مثال ، در اینجا یک روش آسان برای کوتاه کردن هنجار شیب ها در گذر عقب وجود دارد:

@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

از شیب های سفارشی معمولاً برای تهیه یک شیب پایدار عددی برای دنباله ای از عملیات استفاده می شود:

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

در اینجا ، تابع log1pexp را می توان با یک گرادیان سفارشی ساده تحلیل کرد. پیاده سازی در زیر مقدار tf.exp(x) که در هنگام عبور به جلو محاسبه می شود tf.exp(x) استفاده می کند - با حذف محاسبات زائد ، آن را کارآمدتر می کند:

@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

کارایی

محاسبات در هنگام اجرای مشتاقانه به طور خودکار به پردازنده های گرافیکی بارگیری می شود. اگر می خواهید جایی را که یک محاسبه اجرا می شود کنترل کنید می توانید آن را در یک tf.device('/gpu:0') (یا معادل پردازنده) محصور کنید:

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: 0.9964873790740967 secs
GPU: 0.04042506217956543 secs

یک شی tf.Tensor را می توان در دستگاه دیگری کپی کرد تا عملیات آن انجام شود:

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 <ipython-input-1-c99eaec55f9a>: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-1-c99eaec55f9a>: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.

معیارها

برای مدلهای سنگین محاسباتی ، مانند آموزش ResNet50 روی GPU ، عملکرد اجرای مشتاقانه با اجرای عملکرد tf.function قابل مقایسه است. اما این شکاف برای مدلهای با محاسبه کمتر بزرگتر می شود و باید کارهایی برای بهینه سازی مسیرهای کد گرم برای مدلهایی با تعداد زیادی عملیات کوچک انجام شود.

با توابع کار کنید

در حالی که اجرای مشتاق توسعه و اشکال زدایی را تعاملی تر می کند ، اجرای نمودار TensorFlow 1.x دارای مزایایی برای آموزش توزیع شده ، بهینه سازی عملکرد و استقرار تولید است. برای tf.function این شکاف ، TensorFlow 2.0 function s را از طریق tf.function API tf.function کند. برای اطلاعات بیشتر ، به راهنمای عملکرد tf.f مراجعه کنید .