pengantar
Dimungkinkan untuk mengintegrasikan MinDiff secara langsung ke dalam implementasi model Anda. Meskipun demikian tidak memiliki kenyamanan menggunakan MinDiffModel
, pilihan ini menawarkan tingkat tertinggi kontrol yang dapat sangat berguna ketika model Anda adalah subclass dari tf.keras.Model
.
Panduan ini menunjukkan bagaimana Anda dapat mengintegrasikan MinDiff langsung ke penerapan model kustom dengan menambahkan ke train_step
metode.
Mempersiapkan
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
Pertama, unduh datanya. Untuk kekompakan, logika persiapan input telah diperhitungkan keluar ke fungsi pembantu seperti yang dijelaskan dalam panduan persiapan masukan . Anda dapat membaca panduan lengkap untuk detail tentang proses ini.
# 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))
Kustomisasi Model Kustom Asli
tf.keras.Model
dirancang untuk mudah dikustomisasi melalui subclassing. Hal ini biasanya melibatkan perubahan apa yang terjadi dalam panggilan untuk fit
seperti yang dijelaskan di sini .
Panduan ini menggunakan implementasi kustom mana train_step
mirip default tf.keras.Model.train_step
. Biasanya, tidak ada gunanya melakukannya, tetapi di sini, ini akan membantu menunjukkan bagaimana mengintegrasikan 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}
Melatih model seperti yang Anda akan khas Model
menggunakan API Fungsional.
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
Mengintegrasikan MinDiff langsung ke model Anda
Menambahkan MinDiff ke train_step
Untuk mengintegrasikan MinDiff, Anda akan perlu menambahkan beberapa baris ke CustomModel
yang berganti nama di sini sebagai CustomModelWithMinDiff
.
Untuk kejelasan, panduan ini menggunakan bendera boolean disebut apply_min_diff
. Semua kode yang relevan dengan MinDiff hanya akan dijalankan jika sudah diatur untuk True
. Jika diatur ke False
maka model akan berperilaku persis sama dengan 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}
Pelatihan dengan model ini terlihat sama persis dengan sebelumnya dengan pengecualian dataset yang digunakan.
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
Membentuk kembali input Anda (opsional)
Mengingat bahwa pendekatan ini memberikan kontrol penuh, Anda dapat mengambil kesempatan ini untuk membentuk kembali input menjadi bentuk yang sedikit lebih bersih. Bila menggunakan MinDiffModel
, yang min_diff_data
perlu dikemas ke dalam komponen pertama dari setiap batch. Ini adalah kasus dengan train_with_min_diff_ds
dataset.
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'>
Dengan dicabutnya persyaratan ini, Anda dapat mengatur ulang data dalam struktur yang sedikit lebih intuitif dengan data asli dan MinDiff yang dipisahkan dengan rapi.
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)
Langkah ini sepenuhnya opsional tetapi dapat berguna untuk mengatur data dengan lebih baik. Jika Anda melakukannya, satu-satunya perbedaan dalam cara Anda menerapkan CustomModelWithMinDiff
akan bagaimana Anda membongkar data
di awal.
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)
...
Dengan langkah terakhir ini, Anda dapat sepenuhnya mengontrol format input dan bagaimana format tersebut digunakan dalam model untuk menerapkan MinDiff.
Sumber daya tambahan
- Untuk dalam diskusi mendalam mengenai evaluasi kewajaran melihat bimbingan Keadilan Indikator
- Untuk informasi umum tentang Remediasi dan MinDiff, melihat remediasi gambaran .
- Untuk rincian tentang persyaratan sekitarnya MinDiff melihat panduan ini .
- Untuk melihat tutorial end-to-end menggunakan MinDiff di Keras, lihat tutorial ini .