Настройка MinDiffModel

Введение

В большинстве случаев, используя MinDiffModel непосредственно , как описано в разделе «Интеграция с MinDiff MinDiffModel» руководство является достаточным. Однако возможно, что вам потребуется индивидуальное поведение. Для этого есть две основные причины:

  • keras.Model вы используете имеет пользовательское поведение , которое вы хотите сохранить.
  • Вы хотите MinDiffModel вести себя по- разному от значения по умолчанию.

В любом случае, вам нужно будет создать подкласс MinDiffModel для достижения желаемых результатов.

Настраивать

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 разработан , чтобы быть легко настроить с помощью подклассов , как описано здесь . Если Ваша модель настроена реализации , которые вы хотите сохранить при применении MinDiff, вам нужно будет создать подкласс MinDiffModel .

Оригинальная нестандартная модель

Чтобы увидеть , как вы можете сохранить настройки, создать модель , которая устанавливает атрибут в True , когда его заказ train_step называется. Это не полезная настройка, но она служит для иллюстрации поведения.

class CustomModel(tf.keras.Model):

  # Customized train_step
  def train_step(self, *args, **kwargs):
    self.used_custom_train_step = True  # Marker that we can check for.
    return super(CustomModel, self).train_step(*args, **kwargs)

Подготовка такой модели будет выглядеть так же , как обычная Sequential модель.

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

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

_ = model.fit(train_ds.take(1), epochs=1, verbose=0)

# Model has used the custom train_step.
print('Model used the custom train_step:')
print(hasattr(model, 'used_custom_train_step'))  # True
Model used the custom train_step:
True

Создание подкласса MinDiffModel

Если вы должны были попытаться использовать MinDiffModel непосредственно, модель не будет использовать собственный train_step .

model = tutorials_utils.get_uci_model(model_class=CustomModel)
model = min_diff.keras.MinDiffModel(model, min_diff.losses.MMDLoss())

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

_ = model.fit(train_with_min_diff_ds.take(1), epochs=1, verbose=0)

# Model has not used the custom train_step.
print('Model used the custom train_step:')
print(hasattr(model, 'used_custom_train_step'))  # False
Model used the custom train_step:
False

Для того , чтобы использовать правильный train_step метод, вам нужен пользовательский класс , который наследует от MinDiffModel и CustomModel .

class CustomMinDiffModel(min_diff.keras.MinDiffModel, CustomModel):
  pass  # No need for any further implementation.

Тренировка этой модели будет использовать train_step от CustomModel .

model = tutorials_utils.get_uci_model(model_class=CustomModel)

model = CustomMinDiffModel(model, min_diff.losses.MMDLoss())

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

_ = model.fit(train_with_min_diff_ds.take(1), epochs=1, verbose=0)

# Model has used the custom train_step.
print('Model used the custom train_step:')
print(hasattr(model, 'used_custom_train_step'))  # True
Model used the custom train_step:
True

Настройка поведения по умолчанию MinDiffModel

В других случаях, вы можете захотеть изменить определенное поведение по умолчанию MinDiffModel . Наиболее распространенный случай использования этого меняется распаковка поведение по умолчанию , чтобы правильно обрабатывать данные , если вы не используете pack_min_diff_data .

При упаковке данных в настраиваемый формат это может выглядеть следующим образом.

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)

  return ({
      'min_diff_data': min_diff_data,
      'original_inputs': original_inputs}, original_labels)

customized_train_with_min_diff_ds = train_with_min_diff_ds.map(_reformat_input)

В customized_train_with_min_diff_ds набора данных возвращает партии , состоящие из кортежей (x, y) , где x представляет собой ДИКТ , содержащий min_diff_data и original_inputs и y является original_labels .

for x, _ in customized_train_with_min_diff_ds.take(1):
  print('Type of x:', type(x))  # dict
  print('Keys of x:', x.keys())  # 'min_diff_data', 'original_inputs'
Type of x: <class 'dict'>
Keys of x: dict_keys(['min_diff_data', 'original_inputs'])

Этот формат данных является не то , что MinDiffModel ожидает по умолчанию и переходя customized_train_with_min_diff_ds к ней может привести к непредсказуемому поведению. Чтобы исправить это, вам нужно будет создать свой собственный подкласс.

class CustomUnpackingMinDiffModel(min_diff.keras.MinDiffModel):

  def unpack_min_diff_data(self, inputs):
    return inputs['min_diff_data']

  def unpack_original_inputs(self, inputs):
    return inputs['original_inputs']

С помощью этого подкласса вы можете тренироваться, как и в других примерах.

model = tutorials_utils.get_uci_model()
model = CustomUnpackingMinDiffModel(model, min_diff.losses.MMDLoss())

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

_ = model.fit(customized_train_with_min_diff_ds, epochs=1)
77/77 [==============================] - 4s 30ms/step - loss: 0.6690 - min_diff_loss: 0.0395

Ограничения настроенной MinDiffModel

Создание пользовательского MinDiffModel обеспечивает огромное количество гибкости для более сложных случаев использования. Однако есть еще некоторые крайние случаи, которые он не поддерживает.

Предварительная обработка или проверка входов перед тем call

Большое ограничение для подкласса MinDiffModel является то , что он требует x компонента входных данных (т.е. первого или единственный элемент в партии , возвращаемый tf.data.Dataset ) , которые будут передан через без предварительной обработки или проверок , чтобы call .

Это просто потому , что min_diff_data упакован в x компонент входных данных. Любая предварительная обработка или проверка не будет ожидать дополнительной структуры , содержащей min_diff_data и, скорее всего , сломается.

Если предварительная обработка или проверка легко настраиваются (например, учитываются в собственном методе), то это легко решается путем их переопределения, чтобы гарантировать правильную обработку дополнительной структуры.

Пример с проверкой может выглядеть так:

class CustomMinDiffModel(min_diff.keras.MinDiffModel, CustomModel):

  # Override so that it correctly handles additional `min_diff_data`.
  def validate_inputs(self, inputs):
    original_inputs = self.unpack_original_inputs(inputs)
    ...  # Optionally also validate min_diff_data
    # Call original validate method with correct inputs
    return super(CustomMinDiffModel, self).validate(original_inputs)

Если предварительная обработка или проверка не легко настраивается, а затем с помощью MinDiffModel не может работать для вас , и вам нужно будет интегрировать MinDiff без него , как описано в данном руководстве .

Коллизии имен методов

Вполне возможно , что ваша модель имеет методы, имена которых конфликтуют с теми , реализованы в MinDiffModel (полный список открытых методов в документации API ).

Это проблематично только в том случае, если они будут вызываться в экземпляре модели (а не внутри каким-либо другим методом). В то время как весьма маловероятно, если вы находитесь в такой ситуации вам придется либо переопределить и переименовать некоторые методы или, если это невозможно, то , возможно , потребуется рассмотреть вопрос о включении MinDiff без MinDiffModel , как описано в данном руководстве по этому вопросу .

Дополнительные ресурсы