MinDiffデータの準備

序章

MinDiffを実装する場合、モデルに渡す前に、入力を選択して形成するときに複雑な決定を行う必要があります。これらの決定は、主にモデル内のMinDiffの動作を決定します。

このガイドでは、このプロセスの技術的な側面について説明しますが、モデルの公平性を評価する方法や、評価のために特定のスライスとメトリックを特定する方法については説明しません。参照してください公正指標指導これに関する詳細については、を。

MinDiffを実証するために、このガイドでは、使用していますUCIの収入データセットを。モデルタスクは、さまざまな個人属性に基づいて、個人の収入が5万ドルを超えるかどうかを予測することです。このガイドでは、間FNR(偽陰性率)で問題とギャップがあると仮定し"Male""Female"のスライスとモデルの所有者(あなたが)問題に対処するためにMinDiffを適用することを決定しました。 1はMinDiffを適用することを選択する可能性のあるシナリオの詳細については、を参照要件のページを

MinDiffは、2つのデータセットの例間の分布スコアの違いにペナルティを課すことによって機能します。このガイドでは、これらの追加のMinDiffセットを選択して構築する方法と、トレーニング用のモデルに渡すことができるようにすべてをパッケージ化する方法を示します。

設定

pip install -q --upgrade tensorflow-model-remediation
import tensorflow as tf
from tensorflow_model_remediation import min_diff
from tensorflow_model_remediation.tools.tutorials_utils import uci as tutorials_utils

元のデータ

デモンストレーションの目的と実行時間を短縮するために、このガイドではUCI収入データセットのサンプル部分のみを使用します。実際の本番環境では、完全なデータセットが利用されます。

# Sampled at 0.3 for reduced runtimes.
train = tutorials_utils.get_uci_data(split='train', sample=0.3)

print(len(train), 'train examples')
9768 train examples

変換tf.data.Dataset

MinDiffModel 、入力があることが必要tf.data.Dataset 。 MinDiffを統合する前に別の形式の入力を使用していた場合は、入力データを変換する必要があります。

使用tf.data.Dataset.from_tensor_slicesに変換することtf.data.Dataset

dataset = tf.data.Dataset.from_tensor_slices((x, y, weights))
dataset.shuffle(...)  # Optional.
dataset.batch(batch_size)

参照してくださいModel.fit入力の2つの方法の間の等価性の詳細については、マニュアルを参照して。

このガイドでは、入力はPandas DataFrameとしてダウンロードされるため、この変換が必要です。

# Function to convert a DataFrame into a tf.data.Dataset.
def df_to_dataset(dataframe, shuffle=True):
  dataframe = dataframe.copy()
  labels = dataframe.pop('target')
  ds = tf.data.Dataset.from_tensor_slices((dict(dataframe), labels))
  if shuffle:
    ds = ds.shuffle(buffer_size=5000)  # Reasonable but arbitrary buffer_size.
  return ds

# Convert the train DataFrame into a Dataset.
original_train_ds = df_to_dataset(train)

MinDiffデータの作成

トレーニング中、MinDiffは、2つの追加データセット(元のデータセットの例を含む場合があります)間の予測の違いを減らすようにモデルを推奨します。これら2つのデータセットの選択は、MinDiffがモデルに与える影響を決定する重要な決定です。

2つのデータセットは、修正しようとしているパフォーマンスの不一致が明白でよく表されるように選択する必要があります。目標の間FNRの隙間を減少させることであるので"Male"および"Female"スライス、1つのつのみ標識付きデータセット作成手段、この"Male"だけ正側と実施例と別の"Female"の例を。これらはMinDiffデータセットになります。

まず、存在するデータを調べます。

female_pos = train[(train['sex'] == ' Female') & (train['target'] == 1)]
male_pos = train[(train['sex'] == ' Male') & (train['target'] == 1)]
print(len(female_pos), 'positively labeled female examples')
print(len(male_pos), 'positively labeled male examples')
385 positively labeled female examples
2063 positively labeled male examples

元のデータセットのサブセットからMinDiffデータセットを作成することは完全に許容されます。

5,000以上の正存在しませんが"Male"で推奨しているような例としては要件ガイダンス、そこに2,000を超えていると、より多くのデータを収集する前にその多くをしようとするのが合理的です。

min_diff_male_ds = df_to_dataset(male_pos)

正の"Female"として、しかし、これはおそらく良好なパフォーマンスのためには小さすぎるので、追加の例に引いて必要となる385で非常に乏しいです。

full_uci_train = tutorials_utils.get_uci_data(split='train')
augmented_female_pos = full_uci_train[((full_uci_train['sex'] == ' Female') &
                                       (full_uci_train['target'] == 1))]
print(len(augmented_female_pos), 'positively labeled female examples')
1179 positively labeled female examples

完全なデータセットを使用すると、MinDiffに使用できる例の数が3倍以上になります。それはまだ低いですが、最初のパスとして試すには十分です。

min_diff_female_ds = df_to_dataset(augmented_female_pos)

両方のMinDiffデータセットは、推奨される5,000以上の例よりも大幅に小さくなっています。現在のデータでMinDiffを適用することは合理的ですが、トレーニング中にパフォーマンスの低下や過剰適合が見られる場合は、追加のデータの収集を検討する必要があります。

使用tf.data.Dataset.filter

また、あなたは、変換元から直接2つのMinDiffデータセットを作成することができるDataset

# Male
def male_predicate(x, y):
  return tf.equal(x['sex'], b' Male') and tf.equal(y, 0)

alternate_min_diff_male_ds = original_train_ds.filter(male_predicate).cache()

# Female
def female_predicate(x, y):
  return tf.equal(x['sex'], b' Female') and tf.equal(y, 0)

full_uci_train_ds = df_to_dataset(full_uci_train)
alternate_min_diff_female_ds = full_uci_train_ds.filter(female_predicate).cache()

alternate_min_diff_male_dsalternate_min_diff_female_dsへ出力に等しくなるmin_diff_male_dsmin_diff_female_dsそれぞれ。

トレーニングデータセットの構築

最後のステップとして、3つのデータセット(新しく作成された2つのデータセットと元のデータセット)を、モデルに渡すことができる1つのデータセットにマージする必要があります。

データセットのバッチ処理

マージする前に、データセットをバッチ処理する必要があります。

  • 元のデータセットは、MinDiffを統合する前に使用されたものと同じバッチ処理を使用できます。
  • MinDiffデータセットは、元のデータセットと同じバッチサイズである必要はありません。おそらく、小さい方でも同様に機能します。バッチサイズを同じにする必要はありませんが、最高のパフォーマンスを得るにはそうすることをお勧めします。

厳密には必要ではないが、使用に推奨されるdrop_remainder=True彼らは一貫性のバッチサイズを持っていることを確認します。このように2つのMinDiffデータセットのために。

original_train_ds = original_train_ds.batch(128)  # Same as before MinDiff.

# The MinDiff datasets can have a different batch_size from original_train_ds
min_diff_female_ds = min_diff_female_ds.batch(32, drop_remainder=True)
# Ideally we use the same batch size for both MinDiff datasets.
min_diff_male_ds = min_diff_male_ds.batch(32, drop_remainder=True)

データセットを梱包pack_min_diff_data

データセットが準備されたら、それらを単一のデータセットにパックし、モデルに渡します。結果のデータセットからの単一のバッチには、前に準備した3つのデータセットのそれぞれからの1つのバッチが含まれます。

あなたは提供使ってこれを行うことができますutilsに機能をtensorflow_model_remediationパッケージ:

train_with_min_diff_ds = min_diff.keras.utils.pack_min_diff_data(
    original_dataset=original_train_ds,
    sensitive_group_dataset=min_diff_female_ds,
    nonsensitive_group_dataset=min_diff_male_ds)

以上です!あなたは他の使用することができるようになりますutil必要に応じてアンパック個々のバッチへのパッケージの関数を。

for inputs, original_labels in train_with_min_diff_ds.take(1):
  # Unpacking min_diff_data
  min_diff_data = min_diff.keras.utils.unpack_min_diff_data(inputs)
  min_diff_examples, min_diff_membership = min_diff_data
  # Unpacking original data
  original_inputs = min_diff.keras.utils.unpack_original_inputs(inputs)

新しく形成されたデータを使用して、モデルにMinDiffを適用する準備が整いました。これがどのように行われるかについては、で始まる他のガイドをご覧なってくださいMinDiffModelでMinDiffの統合を

カスタムパッキングフォーマットの使用(オプション)

選択した方法で3つのデータセットを一緒にパックすることを決定できます。唯一の要件は、モデルがデータの解釈方法を知っていることを確認する必要があることです。デフォルトの実装MinDiffModelデータを使用してパックされたことを前提としていmin_diff.keras.utils.pack_min_diff_data

あなたが好きなあなたの入力をフォーマットする簡単な方法は、あなたが使用した後、最後のステップとして、データを変換することですmin_diff.keras.utils.pack_min_diff_data

# Reformat input to be a dict.
def _reformat_input(inputs, original_labels):
  unpacked_min_diff_data = min_diff.keras.utils.unpack_min_diff_data(inputs)
  unpacked_original_inputs = min_diff.keras.utils.unpack_original_inputs(inputs)

  return {
      'min_diff_data': unpacked_min_diff_data,
      'original_data': (unpacked_original_inputs, original_labels)}

customized_train_with_min_diff_ds = train_with_min_diff_ds.map(_reformat_input)

あなたのモデルはで説明するように、このカスタマイズされた入力を読み取る方法を知っておく必要がありますカスタマイズMinDiffModelガイド

for batch in customized_train_with_min_diff_ds.take(1):
  # Customized unpacking of min_diff_data
  min_diff_data = batch['min_diff_data']
  # Customized unpacking of original_data
  original_data = batch['original_data']

追加リソース

このガイドでは、MinDiffを適用するときに従うことができるプロセスと意思決定の概要を説明します。残りのガイドは、このフレームワークを基に構築されています。これを簡単にするために、このガイドにあるロジックがヘルパー関数に組み込まれています。

  • get_uci_data :この機能は、すでにこのガイドで使用されています。これは、戻りDataFrame (不特定の場合100%)が示されているどのようなレートでサンプリング指示スプリットからUCI所得データを含有します。
  • df_to_dataset :この関数は、変換DataFrametf.data.DatasetパラメータとしてBATCH_SIZEを通過することができるという追加機能と、このガイドで詳述されるように。
  • get_uci_with_min_diff_dataset :この関数は返すtf.data.Datasetこのマニュアルに記載されているように、元のデータとMinDiffデータの両方を含む、関数utilのモデル修正ライブラリを使用して一緒にパック。

残りのガイドは、ライブラリの他の部分の使用方法を示すために、これらを基に構築されます。