TensorFlow موثر 2

چندین تغییر در TensorFlow 2.0 وجود دارد تا کاربران TensorFlow را پربارتر کند. TensorFlow 2.0 حذف کار برکنار رابط های برنامه کاربردی ، باعث می شود رابط های برنامه کاربردی بیشتر سازگار ( RNNs متحد ، بهینه متحد )، و به یکپارچگی بهتر با زمان اجرا پایتون با اعدام مشتاق .

بسیاری از RFC ها تغییراتی که به ساخت TensorFlow 2.0 رفته توضیح داده اند. این راهنما دیدگاهی را برای نحوه توسعه در TensorFlow 2.0 ارائه می دهد. فرض بر این است که شما با TensorFlow 1.x آشنایی دارید.

خلاصه ای مختصر از تغییرات عمده

پاکسازی API

بسیاری از رابط های برنامه کاربردی هستند یا از بین رفته و یا نقل مکان در TF 2.0. برخی از تغییرات عمده شامل حذف tf.app ، tf.flags و tf.logging به نفع اکنون منبع باز absl-PY ، rehoming پروژه هایی که در زندگی می کردند tf.contrib ، و تمیز کردن اصلی tf.* فضای نام های در حال حرکت توابع کمتر مورد استفاده به زیربستههایی مانند tf.math . - برخی از رابط های برنامه کاربردی با 2.0 معادل آنها جایگزین شده است tf.summary ، tf.keras.metrics و tf.keras.optimizers . ساده ترین راه برای به صورت خودکار اعمال این تغییر نام است که استفاده از اسکریپت ارتقا V2 .

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

TensorFlow نگارش 1.x نیاز کاربران را به صورت دستی با هم کوک درخت نحو انتزاعی (نمودار) با ساخت tf.* API تماس. پس از آن نیاز کاربران را به صورت دستی کامپایل درخت نحو انتزاعی با گذراندن یک مجموعه ای از تانسورها خروجی و تانسورها ورودی به یک session.run پاسخ. TensorFlow 2.0 با اشتیاق اجرا می شود (مانند Python به طور معمول این کار را می کند) و در 2.0 ، نمودارها و جلسات باید مانند جزئیات اجرا احساس شوند.

یک محصول جانبی قابل توجهی از اعدام مشتاق است که tf.control_dependencies است که دیگر مورد نیاز، به عنوان تمام خطوط کد را اجرا کنید در سفارش (در یک tf.function ، کد با عوارض جانبی اجرا در جهت نوشته شده است).

دیگر جهانی نیست

TensorFlow 1.x به شدت به فضاهای نامی جهانی متکی بود. هنگامی که شما به نام tf.Variable ، این امر می تواند به نمودار به طور پیش فرض قرار داده، و آن وجود دارد باقی خواهد ماند، حتی اگر مسیر شما را از متغیر پایتون اشاره به آن از دست داد. بعد از آن شما می تواند بهبود می یابند که tf.Variable ، اما تنها اگر شما نام می دانستند که آن را با ایجاد شده بود. اگر کنترل ایجاد متغیر را در دست نداشته باشید ، انجام این کار دشوار است. در نتیجه، تمام انواع مکانیسم تکثیر را به تلاش برای کمک به کاربران را دوباره پیدا کنید متغیرهای خود، و قاب برای یافتن متغیرهای کاربر ایجاد: حوزه متغیر، مجموعه جهانی، متد های کمکی مانند tf.get_global_step ، tf.global_variables_initializer شیب، بهینه به طور ضمنی محاسبه بیش از همه متغیرهای قابل آموزش و غیره. TensorFlow 2.0 حذف تمام از این مکانیسم ( متغیرهای 2.0 RFC ) در حمایت از مکانیزم پیش فرض: پیگیری از متغیرهای خود را! اگر شما از دست دادن آهنگ از tf.Variable ، آن را می شود جمع آوری زباله.

نیاز به ردیابی متغیرها کار اضافی برای کاربر ایجاد می کند ، اما با استفاده از اشیا K Keras (زیر را ببینید) ، بار به حداقل می رسد.

توابع ، نه جلسات

session.run پاسخ است که تقریبا مانند یک فراخوانی تابع: شما در ورودی و تابع به نام مشخص، و شما به عقب بر گردیم مجموعه ای از خروجی. در TensorFlow 2.0، شما می توانید با استفاده از یک تابع پایتون تزئین tf.function به آن علامت برای کامپایل JIT به طوری که آن را اجرا می TensorFlow به عنوان یک تک نمودار ( توابع 2.0 RFC ). این مکانیسم به TensorFlow 2.0 اجازه می دهد تا تمام مزایای حالت نمودار را بدست آورد:

  • عملکرد: عملکرد را می توان بهینه کرد (هرس گره ، همجوشی هسته و غیره)
  • حمل: این تابع را می توان صادر / دوباره وارد ( SavedModel 2.0 RFC )، اجازه می دهد تا کاربران را به استفاده مجدد و سهم توابع TensorFlow مدولار.
# TensorFlow 1.X
outputs = session.run(f(placeholder), feed_dict={placeholder: input})
# TensorFlow 2.0
outputs = f(input)

با استفاده از قدرت تداخل آزاد در کد پایتون و TensorFlow ، کاربران می توانند از بیانی پایتون استفاده کنند. اما TensorFlow قابل حمل در متن بدون مفسر پایتون مانند تلفن همراه ، C ++ و JavaScript اجرا می شود. به کاربران کمک به جلوگیری از نیاز به بازنویسی کد خود را در هنگام اضافه کردن @tf.function ، دستخط یک زیر مجموعه از سازه پایتون تبدیل به معادل TensorFlow خود:

  • for / while -> tf.while_loop ( break و continue پشتیبانی می شوند)
  • if -> tf.cond
  • for _ in dataset -> dataset.reduce

AutoGraph از لانه های دلخواه جریان کنترل پشتیبانی می کند ، که اجرای کامل و مختصر بسیاری از برنامه های پیچیده ML مانند مدل های توالی ، یادگیری تقویت ، حلقه های آموزش سفارشی و موارد دیگر را امکان پذیر می کند.

توصیه هایی برای اصطلاح TensorFlow 2.0

کد خود را به عملکردهای کوچکتر تبدیل کنید

یک الگوی استفاده رایج در TensorFlow 1.X به "سینک آشپزخانه" استراتژی، که در آن اتحاد همه محاسبات ممکن را پیشگیرانه گذاشته شد نبود، و تانسورها سپس انتخاب شده از طریق بررسی قرار گرفت session.run . در TensorFlow 2.0 ، کاربران باید کد خود را به عملکردهای کوچکتر تبدیل کنند که در صورت لزوم فراخوانی می شوند. به طور کلی، لازم است که برای تزئین هر یک از این توابع کوچکتر با tf.function ؛ تنها با استفاده از tf.function برای تزئین محاسبات در سطح بالا - برای مثال، یک گام آموزش یا پاس رو به جلو از مدل خود را.

برای مدیریت متغیرها از لایه ها و مدل های Keras استفاده کنید

مدل Keras و لایه های ارائه مناسب variables و trainable_variables خواص، که به صورت بازگشتی جمع آوری تمام متغیرهای وابسته. این کار مدیریت متغیرها را به صورت محلی و محلی که از آنها استفاده می شود ، آسان می کند.

تضاد:

def dense(x, W, b):
  return tf.nn.sigmoid(tf.matmul(x, W) + b)

@tf.function
def multilayer_perceptron(x, w0, b0, w1, b1, w2, b2 ...):
  x = dense(x, w0, b0)
  x = dense(x, w1, b1)
  x = dense(x, w2, b2)
  ...

# You still have to manage w_i and b_i, and their shapes are defined far away from the code.

با نسخه Keras:

# Each layer can be called, with a signature equivalent to linear(x)
layers = [tf.keras.layers.Dense(hidden_size, activation=tf.nn.sigmoid) for _ in range(n)]
perceptron = tf.keras.Sequential(layers)

# layers[3].trainable_variables => returns [w3, b3]
# perceptron.trainable_variables => returns [w0, b0, ...]

لایه Keras / مدل های از به ارث می برند tf.train.Checkpointable و با یکپارچه @tf.function ، که باعث می شود این امکان را به طور مستقیم و یا پاسگاه SavedModels صادرات Keras اشیاء. شما لزوما مجبور به استفاده از Keras است Model.fit API را به استفاده از این یکپارچگی.

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

trunk = tf.keras.Sequential([...])
head1 = tf.keras.Sequential([...])
head2 = tf.keras.Sequential([...])

path1 = tf.keras.Sequential([trunk, head1])
path2 = tf.keras.Sequential([trunk, head2])

# Train on primary dataset
for x, y in main_dataset:
  with tf.GradientTape() as tape:
    # training=True is only needed if there are layers with different
    # behavior during training versus inference (e.g. Dropout).
    prediction = path1(x, training=True)
    loss = loss_fn_head1(prediction, y)
  # Simultaneously optimize trunk and head1 weights.
  gradients = tape.gradient(loss, path1.trainable_variables)
  optimizer.apply_gradients(zip(gradients, path1.trainable_variables))

# Fine-tune second head, reusing the trunk
for x, y in small_dataset:
  with tf.GradientTape() as tape:
    # training=True is only needed if there are layers with different
    # behavior during training versus inference (e.g. Dropout).
    prediction = path2(x, training=True)
    loss = loss_fn_head2(prediction, y)
  # Only optimize head2 weights, not trunk weights
  gradients = tape.gradient(loss, head2.trainable_variables)
  optimizer.apply_gradients(zip(gradients, head2.trainable_variables))

# You can publish just the trunk computation for other people to reuse.
tf.saved_model.save(trunk, output_path)

tf.data.Datasets و @ tf.function را ترکیب کنید

هنگام تکرار داده های آموزشی متناسب با حافظه ، در صورت تمایل از تکرار منظم پایتون استفاده کنید. در غیر این صورت، tf.data.Dataset بهترین راه را برای جریان داده های آموزشی را از روی دیسک است. مجموعه داده ها iterables (نه تکرارکننده) ، و کار درست مثل دیگر iterables پایتون در حالت مشتاق. شما به طور کامل می تواند استفاده مجموعه داده ای async واکشی اولیه / جریان از ویژگی های با بسته بندی کد خود را در tf.function ، که جایگزین پایتون تکرار با عملیات نمودار معادل با استفاده از دستخط.

@tf.function
def train(model, dataset, optimizer):
  for x, y in dataset:
    with tf.GradientTape() as tape:
      # training=True is only needed if there are layers with different
      # behavior during training versus inference (e.g. Dropout).
      prediction = model(x, training=True)
      loss = loss_fn(prediction, y)
    gradients = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))

در صورت استفاده از Keras Model.fit API، شما نمی خواهد به نگرانی در مورد مجموعه داده تکرار دارند.

model.compile(optimizer=optimizer, loss=loss_fn)
model.fit(dataset)

با جریان کنترل پایتون از AutoGraph استفاده کنید

دستخط راهی برای تبدیل وابسته به داده های جریان کنترل به معادل نمودار حالت مانند فراهم می کند tf.cond و tf.while_loop .

یک مکان معمول که جریان کنترل وابسته به داده در آن ظاهر می شود ، مدل های توالی است. tf.keras.layers.RNN کاری ادامه داده اند یک سلول RNN، اجازه می دهد شما را به هم آماری یا به صورت پویا باز شدن عود. به خاطر تظاهرات ، می توانید باز کردن پویا را به صورت زیر انجام دهید:

class DynamicRNN(tf.keras.Model):

  def __init__(self, rnn_cell):
    super(DynamicRNN, self).__init__(self)
    self.cell = rnn_cell

  def call(self, input_data):
    # [batch, time, features] -> [time, batch, features]
    input_data = tf.transpose(input_data, [1, 0, 2])
    outputs = tf.TensorArray(tf.float32, input_data.shape[0])
    state = self.cell.zero_state(input_data.shape[1], dtype=tf.float32)
    for i in tf.range(input_data.shape[0]):
      output, state = self.cell(input_data[i], state)
      outputs = outputs.write(i, output)
    return tf.transpose(outputs.stack(), [1, 0, 2]), state

برای جزییات بیشتر بیشتر از ویژگی های AUTOGRAPH، نگاه کنید به راهنمای .

tf.metrics داده ها را جمع کرده و tf.summary آنها را ثبت می کند

برای ورود خلاصه، استفاده از tf.summary.(scalar|histogram|...) و هدایت آن را به یک نویسنده با استفاده از یک مدیر زمینه. (اگر مدیر زمینه را حذف کنید ، هیچ اتفاقی نمی افتد.) برخلاف TF 1.x ، خلاصه ها مستقیماً به نویسنده ارسال می شوند. هیچ جداگانه "ادغام" op و هیچ جداگانه وجود دارد add_summary پاسخ، که بدان معنی است که step ارزش باید در callsite فراهم شود.

summary_writer = tf.summary.create_file_writer('/tmp/summaries')
with summary_writer.as_default():
  tf.summary.scalar('loss', 0.1, step=42)

برای جمع آوری داده قبل از ورود آنها را به عنوان خلاصه، استفاده از tf.metrics . متریک stateful به: آنها جمع ارزش ها و بازگشت به یک نتیجه تجمعی زمانی که شما پاسخ result روش (مانند Mean.result ). پاک کردن ارزش ها را با انباشته Model.reset_states .

def train(model, optimizer, dataset, log_freq=10):
  avg_loss = tf.keras.metrics.Mean(name='loss', dtype=tf.float32)
  for images, labels in dataset:
    loss = train_step(model, optimizer, images, labels)
    avg_loss.update_state(loss)
    if tf.equal(optimizer.iterations % log_freq, 0):
      tf.summary.scalar('loss', avg_loss.result(), step=optimizer.iterations)
      avg_loss.reset_states()

def test(model, test_x, test_y, step_num):
  # training=False is only needed if there are layers with different
  # behavior during training versus inference (e.g. Dropout).
  loss = loss_fn(model(test_x, training=False), test_y)
  tf.summary.scalar('loss', loss, step=step_num)

train_summary_writer = tf.summary.create_file_writer('/tmp/summaries/train')
test_summary_writer = tf.summary.create_file_writer('/tmp/summaries/test')

with train_summary_writer.as_default():
  train(model, optimizer, dataset)

with test_summary_writer.as_default():
  test(model, test_x, test_y, optimizer.iterations)

با نشان دادن TensorBoard به فهرست ثبت خلاصه ، خلاصه های تولید شده را تجسم کنید:

tensorboard --logdir /tmp/summaries

هنگام رفع اشکال از tf.config.run_functions_eagly استفاده کنید

در TensorFlow 2.0 ، اجرای Eager به شما امکان می دهد تا کد را مرحله به مرحله اجرا کنید تا اشکال ، انواع داده ها و مقادیر را بررسی کند. API های خاص، مثل tf.function ، tf.keras ، و غیره طراحی شده برای استفاده اعدام نمودار، برای عملکرد و قابلیت حمل آسان. هنگام اشکال زدایی، استفاده tf.config.run_functions_eagerly(True) به استفاده از اعدام مشتاق در داخل این کد.

مثلا:

@tf.function
def f(x):
  if x > 0:
    import pdb
    pdb.set_trace()
    x = x + 1
  return x

tf.config.run_functions_eagerly(True)
f(tf.constant(1))
f()
-> x = x + 1
(Pdb) l
  6     @tf.function
  7     def f(x):
  8       if x > 0:
  9         import pdb
 10         pdb.set_trace()
 11  ->     x = x + 1
 12       return x
 13
 14     tf.config.run_functions_eagerly(True)
 15     f(tf.constant(1))
[EOF]

این همچنین در داخل مدلهای Keras و سایر API هایی که از اجرای Eager پشتیبانی می کنند نیز کار می کند:

class CustomModel(tf.keras.models.Model):

  @tf.function
  def call(self, input_data):
    if tf.reduce_mean(input_data) > 0:
      return input_data
    else:
      import pdb
      pdb.set_trace()
      return input_data // 2


tf.config.run_functions_eagerly(True)
model = CustomModel()
model(tf.constant([-2, -4]))
call()
-> return input_data // 2
(Pdb) l
 10         if tf.reduce_mean(input_data) > 0:
 11           return input_data
 12         else:
 13           import pdb
 14           pdb.set_trace()
 15  ->       return input_data // 2
 16
 17
 18     tf.config.run_functions_eagerly(True)
 19     model = CustomModel()
 20     model(tf.constant([-2, -4]))