ادغام MinDiff بدون MinDiffModel

معرفی

امکان ادغام MinDiff مستقیماً در پیاده سازی مدل شما وجود دارد. در حالی که انجام این کار به سهولت استفاده ندارد MinDiffModel ، این گزینه را ارائه می دهد بالاترین سطح از کنترل است که می تواند به ویژه زمانی مفید است که مدل خود را یک زیر کلاس از است tf.keras.Model .

این راهنما نشان میدهد که چگونه شما می توانید به طور مستقیم به MinDiff اجرای یک مدل سفارشی با اضافه کردن به ادغام train_step روش.

برپایی

pip install -q --upgrade tensorflow-model-remediation
import tensorflow as tf
tf.get_logger().setLevel('ERROR')  # Avoid TF warnings.
from tensorflow_model_remediation import min_diff
from tensorflow_model_remediation.tools.tutorials_utils import uci as tutorials_utils

ابتدا داده ها را دانلود کنید. نمیکشد، منطق آماده سازی ورودی است به توابع کمکی آن لحاظ شده است به عنوان توضیح داده شده در راهنمای آماده سازی ورودی . برای جزئیات بیشتر در مورد این فرآیند می توانید راهنمای کامل را بخوانید.

# Original Dataset for training, sampled at 0.3 for reduced runtimes.
train_df = tutorials_utils.get_uci_data(split='train', sample=0.3)
train_ds = tutorials_utils.df_to_dataset(train_df, batch_size=128)

# Dataset needed to train with MinDiff.
train_with_min_diff_ds = (
    tutorials_utils.get_uci_with_min_diff_dataset(split='train', sample=0.3))

سفارشی سازی های مدل سفارشی اصلی

tf.keras.Model طراحی شده است که به راحتی از طریق subclassing سفارشی. این معمولا شامل تغییر چه اتفاقی می افتد در پاسخ به fit به عنوان توضیح در اینجا .

این راهنما با استفاده از یک اجرای سفارشی که در آن train_step شباهت به طور پیش فرض tf.keras.Model.train_step . به طور معمول، انجام این کار هیچ فایده ای ندارد، اما در اینجا، به نشان دادن نحوه ادغام MinDiff کمک می کند.

class CustomModel(tf.keras.Model):

  def train_step(self, data):
    # Unpack the data.
    x, y, sample_weight = tf.keras.utils.unpack_x_y_sample_weight(data)

    with tf.GradientTape() as tape:
      y_pred = self(x, training=True)  # Forward pass.
      loss = self.compiled_loss(
          y, y_pred, sample_weight, regularization_losses=self.losses)
      # Compute the loss value.
      loss = self.compiled_loss(
          y, y_pred, sample_weight, regularization_losses=self.losses)

    # Compute gradients and update weights.
    self.optimizer.minimize(loss, self.trainable_variables, tape=tape)
    # Update and return metrics.
    self.compiled_metrics.update_state(y, y_pred, sample_weight)
    return {m.name: m.result() for m in self.metrics}

آموزش مدل به عنوان شما می توانید یک نمونه Model با استفاده از API کاربردی.

model = tutorials_utils.get_uci_model(model_class=CustomModel)  # Use CustomModel.

model.compile(optimizer='adam', loss='binary_crossentropy')

_ = model.fit(train_ds, epochs=1)
77/77 [==============================] - 3s 22ms/step - loss: 0.7273

ادغام MinDiff به طور مستقیم در مدل شما

اضافه کردن MinDiff به train_step

به ادغام MinDiff، شما نیاز به اضافه کردن برخی از خطوط به CustomModel که در اینجا به عنوان تغییر نام CustomModelWithMinDiff .

برای وضوح، این راهنمای استفاده از پرچم منطقی به نام apply_min_diff . تمام کد مربوط به MinDiff تنها اجرا خواهد شد اگر آن را به مجموعه ای True . اگر به مجموعه ای False پس از آن مدل دقیقا رفتار همان CustomModel .

min_diff_loss_fn = min_diff.losses.MMDLoss()  # Hard coded for convenience.
min_diff_weight = 2  # Arbitrary number for example, hard coded for convenience.
apply_min_diff = True  # Flag to help show where the additional lines are.

class CustomModelWithMinDiff(tf.keras.Model):

  def train_step(self, data):
    # Unpack the data.
    x, y, sample_weight = tf.keras.utils.unpack_x_y_sample_weight(data)

    # Unpack the MinDiff data.
    if apply_min_diff:
      min_diff_data = min_diff.keras.utils.unpack_min_diff_data(x)
      min_diff_x, membership, min_diff_sample_weight = (
          tf.keras.utils.unpack_x_y_sample_weight(min_diff_data))
      x = min_diff.keras.utils.unpack_original_inputs(x)

    with tf.GradientTape() as tape:
      y_pred = self(x, training=True)  # Forward pass.
      loss = self.compiled_loss(
          y, y_pred, sample_weight, regularization_losses=self.losses)
      # Compute the loss value.
      loss = self.compiled_loss(
          y, y_pred, sample_weight, regularization_losses=self.losses)

      # Calculate and add the min_diff_loss. This must be done within the scope
      # of tf.GradientTape().
      if apply_min_diff:
        min_diff_predictions = self(min_diff_x, training=True)
        min_diff_loss = min_diff_weight * min_diff_loss_fn(
            min_diff_predictions, membership, min_diff_sample_weight)
        loss += min_diff_loss

    # Compute gradients and update weights.
    self.optimizer.minimize(loss, self.trainable_variables, tape=tape)
    # Update and return metrics.
    self.compiled_metrics.update_state(y, y_pred, sample_weight)
    return {m.name: m.result() for m in self.metrics}

آموزش با این مدل به استثنای مجموعه داده استفاده شده، دقیقاً مانند قبلی است.

model = tutorials_utils.get_uci_model(model_class=CustomModelWithMinDiff)

model.compile(optimizer='adam', loss='binary_crossentropy')

_ = model.fit(train_with_min_diff_ds, epochs=1)
77/77 [==============================] - 4s 30ms/step - loss: 0.7799

تغییر شکل ورودی شما (اختیاری)

با توجه به اینکه این رویکرد کنترل کامل را فراهم می کند، می توانید از این فرصت برای تغییر شکل ورودی به شکل کمی تمیزتر استفاده کنید. هنگام استفاده از MinDiffModel از min_diff_data نیاز دارد را به جزء اول از هر دسته ای بسته بندی می شود. این مورد با است train_with_min_diff_ds مجموعه داده.

for x, y in train_with_min_diff_ds.take(1):
  print('Type of x:', type(x))  # MinDiffPackedInputs
  print('Type of y:', type(y))  # Tensor (original labels)
Type of x: <class 'tensorflow_model_remediation.min_diff.keras.utils.input_utils.MinDiffPackedInputs'>
Type of y: <class 'tensorflow.python.framework.ops.EagerTensor'>

با رفع این نیاز، می‌توانید داده‌ها را در ساختاری کمی بصری‌تر با جداسازی داده‌های اصلی و MinDiff دوباره سازماندهی کنید.

def _reformat_input(inputs, original_labels):
  min_diff_data = min_diff.keras.utils.unpack_min_diff_data(inputs)
  original_inputs = min_diff.keras.utils.unpack_original_inputs(inputs)
  original_data = (original_inputs, original_labels)

  return {
      'min_diff_data': min_diff_data,
      'original_data': original_data}

customized_train_with_min_diff_ds = train_with_min_diff_ds.map(_reformat_input)

این مرحله کاملا اختیاری است اما می تواند برای سازماندهی بهتر داده ها مفید باشد. اگر شما این کار، تنها تفاوت در چگونه می توانید پیاده سازی CustomModelWithMinDiff خواهد بود که چگونه شما باز data در ابتدا.

class CustomModelWithMinDiff(tf.keras.Model):

  def train_step(self, data):
    # Unpack the MinDiff data from the custom structure.
    if apply_min_diff:
      min_diff_data = data['min_diff_data']
      min_diff_x, membership, min_diff_sample_weight = (
          tf.keras.utils.unpack_x_y_sample_weight(min_diff_data))
      data = data['original_data']

    ... # possible preprocessing or validation on data before unpacking.

    x, y, sample_weight = tf.keras.utils.unpack_x_y_sample_weight(data)

    ...

با این مرحله آخر، می‌توانید فرمت ورودی و نحوه استفاده از آن را در مدل برای اعمال MinDiff به طور کامل کنترل کنید.

منابع اضافی