إعداد البيانات MinDiff

مقدمة

عند تنفيذ MinDiff ، ستحتاج إلى اتخاذ قرارات معقدة كما تختار وتشكل مدخلاتك قبل تمريرها إلى النموذج. ستحدد هذه القرارات إلى حد كبير سلوك MinDiff داخل نموذجك.

سيغطي هذا الدليل الجوانب الفنية لهذه العملية ، لكنه لن يناقش كيفية تقييم نموذج للعدالة ، أو كيفية تحديد شرائح ومقاييس معينة للتقييم. يرجى الاطلاع على إرشادات مؤشرات الإنصاف لمزيد من التفاصيل حول هذا الموضوع.

لإثبات MinDiff، يستخدم هذا دليل بيانات الدخل UCI . تتمثل مهمة النموذج في التنبؤ بما إذا كان دخل الفرد يتجاوز 50 ألف دولار ، بناءً على السمات الشخصية المختلفة. يفترض هذا الدليل هو وجود فجوة إشكالية في FNR (معدل سلبية كاذبة) بين "Male" و "Female" شرائح وصاحب نموذج (أنت) قد قررت التقدم بطلب MinDiff لمعالجة هذه المسألة. لمزيد من المعلومات حول السيناريوهات التي يمكن للمرء أن يختار تطبيق MinDiff، راجع صفحة متطلبات .

يعمل MinDiff عن طريق معاقبة الاختلاف في درجات التوزيع بين الأمثلة في مجموعتين من البيانات. سيوضح هذا الدليل كيفية اختيار مجموعات 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 الوثائق للاطلاع على تفاصيل معادلات بين الطريقتين من المدخلات.

في هذا الدليل ، يتم تنزيل الإدخال باعتباره 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 النموذج على تقليل الاختلافات في التنبؤات بين مجموعتي بيانات إضافيتين (والتي قد تتضمن أمثلة من مجموعة البيانات الأصلية). يعد اختيار مجموعتي البيانات هاتين القرار الأساسي الذي سيحدد تأثير MinDiff على النموذج.

يجب اختيار مجموعتي البيانات بحيث يكون التباين في الأداء الذي تحاول إصلاحه واضحًا وممثلًا جيدًا. لأن الهدف هو تقليل الفجوة في FNR بين "Male" و "Female" شرائح، يعني ذلك خلق مجموعة بيانات واحدة فقط مع المسمى إيجابيا "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 من مجموعات فرعية من مجموعة البيانات الأصلية.

في حين ليست هناك 5000 أو أكثر إيجابية "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 أكثر من ثلاثة أضعاف. لا يزال منخفضًا ولكن يكفي المحاولة كتمريرة أولى.

min_diff_female_ds = df_to_dataset(augmented_female_pos)

كلا مجموعتي البيانات MinDiff أصغر بكثير من 5000 أو أكثر من الأمثلة الموصى بها. في حين أنه من المعقول محاولة تطبيق MinDiff مع البيانات الحالية ، فقد تحتاج إلى التفكير في جمع بيانات إضافية إذا لاحظت ضعف الأداء أو فرط التجهيز أثناء التدريب.

باستخدام tf.data.Dataset.filter

بدلا من ذلك، يمكنك إنشاء اثنين من مجموعات البيانات 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_ds و alternate_min_diff_female_ds سوف يكون معادلا في الإخراج إلى min_diff_male_ds و min_diff_female_ds على التوالي.

بناء مجموعة بيانات التدريب الخاصة بك

كخطوة أخيرة ، يجب دمج مجموعات البيانات الثلاث (مجموعتان تم إنشاؤهما حديثًا والأصلية) في مجموعة بيانات واحدة يمكن تمريرها إلى النموذج.

تجميع مجموعات البيانات

قبل الدمج ، يجب تجميع مجموعات البيانات.

  • يمكن لمجموعة البيانات الأصلية استخدام نفس التجميع الذي تم استخدامه قبل دمج MinDiff.
  • لا تحتاج مجموعات البيانات MinDiff إلى نفس حجم الدُفعة مثل مجموعة البيانات الأصلية. في جميع الاحتمالات ، سيؤدي أداء أصغر أيضًا. على الرغم من أنهم لا يحتاجون حتى إلى نفس حجم الدُفعة مثل بعضهم البعض ، فمن المستحسن القيام بذلك للحصول على أفضل أداء.

في حين ليس من الضروري بدقة، فمن المستحسن استخدام drop_remainder=True لاثنين من مجموعات البيانات 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

بمجرد إعداد مجموعات البيانات ، قم بتجميعها في مجموعة بيانات واحدة والتي سيتم بعد ذلك تمريرها إلى النموذج. ستحتوي دفعة واحدة من مجموعة البيانات الناتجة على دفعة واحدة من كل مجموعة من مجموعات البيانات الثلاث التي أعددتها مسبقًا.

يمكنك القيام بذلك عن طريق استخدام المقدمة 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 في نموذجك! لمعرفة كيف يتم ذلك، يرجى إلقاء نظرة على أدلة أخرى بدءا دمج MinDiff مع MinDiffModel .

استخدام تنسيق تغليف مخصص (اختياري)

قد تقرر تجميع مجموعات البيانات الثلاث معًا بأي طريقة تختارها. الشرط الوحيد هو أنك ستحتاج إلى التأكد من أن النموذج يعرف كيفية تفسير البيانات. تطبيق الافتراضي 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 التي تحتوي على بيانات الدخل UCI من الانقسام المحددة للعينات في كل ما معدل يشار إلى (100٪ إذا كان غير محدد).
  • df_to_dataset : هذه الوظيفة بتحويل DataFrame إلى tf.data.Dataset كما هو مفصل في هذا الدليل مع وظيفة إضافية تتمثل في أن تكون قادرة على تمرير batch_size كمعلمة.
  • get_uci_with_min_diff_dataset : هذه الوظيفة عائدات tf.data.Dataset تحتوي على كل البيانات الأصلية والبيانات MinDiff معبأة معا باستخدام مكتبة علاج نموذج UTIL وظائف على النحو المبين في هذا الدليل.

سيتم إنشاء بقية الأدلة من هذه لتوضيح كيفية استخدام أجزاء أخرى من المكتبة.