שילוב 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.

משאבים נוספים