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

TensorFlow موثر 2

چندین تغییر در TensorFlow 2.0 وجود دارد تا کاربران TensorFlow را پربارتر کند. TensorFlow 2.0 API های زائد را برطرف می کند ، API ها را سازگارتر می کند ( Unified RNNs ، Unified Optimizer ) و با اجرای Pager با اجرای Eager بهتر ادغام می شود.

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

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

پاکسازی API

بسیاری از API ها از بین رفته یا در TF 2.0 جابجا شده اند. برخی از تغییرات عمده شامل حذف tf.app ، tf.flags و tf.logging به نفع absl-py اکنون با منبع باز ، بازگرداندن پروژه هایی که در tf.contrib زندگی می tf.contrib و تمیز کردن نام اصلی tf.* namespace توسط انتقال توابع کمتر استفاده شده به tf.math هایی مانند tf.math . برخی از API ها با معادل 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 تمام این مکانیزم ها ( Variables 2.0 RFC ) را به نفع مکانیزم پیش فرض از بین می برد: متغیرهای خود را پیگیری کنید! اگر رد یک tf.Variable از دست tf.Variable ، زباله جمع می شود.

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

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

فراخوانی session.run() تقریباً مانند فراخوانی تابع است: ورودی ها و عملکردی را که باید فراخوانی شود تعیین می کنید و مجموعه ای از خروجی ها را پس می گیرید. در TensorFlow 2.0 ، شما می توانید یک تابع Python را با استفاده از tf.function() برای علامت گذاری آن برای جمع آوری JIT تزئین کنید تا tf.function() آن را به صورت یک نمودار اجرا کند ( Functions 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 ، از نوشتن مجدد کد خود جلوگیری کنند ، AutoGraph زیرمجموعه ای از ساختارهای پایتون را به معادل 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.train.Checkpointable و با @tf.function یکپارچه شده است ، این امکان را می دهد که به طور مستقیم CheckdModels را از اشیا K Keras بررسی کنید یا صادر کنید. برای استفاده از این ادغام ها ، لزوماً نباید از API Keras .fit() استفاده کنید.

در اینجا یک مثال یادگیری انتقال وجود دارد که نشان می دهد چگونه 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 بهترین راه برای جریان دادن اطلاعات آموزش از دیسک است. مجموعه های داده تکرار پذیر هستند (تکرار کننده نیستند) ، و درست مانند سایر تکرارهای پایتون در حالت Eager کار می کنند. با قرار دادن کد خود در tf.function() ، که عملیات تکراری پایتون را با استفاده از AutoGraph جایگزین تکرار پایتون می کند ، می توانید از ویژگی های پیش فرض / پخش جریانی همزمان داده به طور کامل استفاده کنید.

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

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

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

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

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 ، خلاصه ها مستقیماً به نویسنده ارسال می شوند. هیچ عملیات جداگانه "ادغام" و هیچ تماس جداگانه add_summary() ، به این معنی که مقدار step باید در سایت فراخوانی ارائه شود.

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

برای جمع آوری داده ها قبل از ثبت آنها به عنوان خلاصه ، از tf.metrics استفاده کنید. .result() دارند: آنها با جمع کردن .result() مقادیر را جمع می کنند و نتیجه تجمعی را .result() . مقادیر جمع شده را با .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.experimental_run_functions_eagerly () استفاده کنید

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

مثلا:

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

tf.config.experimental_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.experimental_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.experimental_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.experimental_run_functions_eagerly(True)
 19     model = CustomModel()
 20     model(tf.constant([-2, -4]))