簡介
在大多數情況下,直接使用 MinDiffModel
(如「將 MinDiff 與 MinDiffModel 整合」指南所述) 就已足夠。但是,您可能需要自訂行為。主要有兩個原因:
- 您使用的
keras.Model
具有您想要保留的自訂行為。 - 您希望
MinDiffModel
的行為與預設行為不同。
在上述任一種情況下,您都需要子類別化 MinDiffModel
才能達到理想結果。
設定
pip install --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
。
原始自訂模型
若要瞭解如何保留自訂項目,請建立一個自訂模型,當呼叫其自訂 train_step
時,該模型會將屬性設為 True
。這不是有用的自訂項目,但可用於說明行為。
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
子類別化 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
為了使用正確的 train_step
方法,您需要一個同時子類別化 MinDiffModel
和 CustomModel
的自訂類別。
class CustomMinDiffModel(min_diff.keras.MinDiffModel, CustomModel):
pass # No need for any further implementation.
訓練此模型將會使用來自 CustomModel
的 train_step
。
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
自訂 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'
此資料格式不是 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)
自訂 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
,如關於此主題的指南中所述。
其他資源
- 如需深入瞭解公平性評估的討論,請參閱Fairness Indicators 指南
- 如需關於修正和 MinDiff 的一般資訊,請參閱修正總覽。
- 如需關於 MinDiff 相關需求的詳細資訊,請參閱本指南。
- 若要查看關於在 Keras 中使用 MinDiff 的端對端教學課程,請參閱本教學課程。