การเตรียมข้อมูล MinDiff

บทนำ

เมื่อใช้งาน MinDiff คุณจะต้องทำการตัดสินใจที่ซับซ้อนในขณะที่คุณเลือกและกำหนดรูปแบบข้อมูลของคุณก่อนที่จะส่งต่อไปยังโมเดล การตัดสินใจเหล่านี้จะกำหนดพฤติกรรมของ MinDiff ภายในโมเดลของคุณเป็นส่วนใหญ่

คู่มือนี้จะครอบคลุมแง่มุมทางเทคนิคของกระบวนการนี้ แต่จะไม่อภิปรายถึงวิธีการประเมินแบบจำลองเพื่อความเป็นธรรม หรือวิธีการระบุส่วนและตัวชี้วัดเฉพาะสำหรับการประเมิน โปรดดู คำแนะนำความเป็นธรรมชี้วัด สำหรับรายละเอียดเกี่ยวกับเรื่องนี้

เพื่อแสดงให้เห็น MinDiff คู่มือนี้ใช้ ชุดข้อมูลรายได้ UCI งานต้นแบบคือการทำนายว่าบุคคลมีรายได้เกิน 50,000 ดอลลาร์หรือไม่ โดยพิจารณาจากคุณลักษณะส่วนบุคคลต่างๆ คู่มือนี้จะถือว่ามีช่องว่างที่มีปัญหาใน 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 Income ในการตั้งค่าการผลิตจริง ชุดข้อมูลทั้งหมดจะถูกใช้

# 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 เอกสารสำหรับรายละเอียดเกี่ยว equivalences ระหว่างสองวิธีการป้อนข้อมูล

ในคู่มือนี้ อินพุตจะถูกดาวน์โหลดเป็น 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 จากชุดย่อยของชุดข้อมูลดั้งเดิม

ในขณะที่มีไม่ได้ 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 ได้มากกว่าสามเท่า มันยังต่ำอยู่ แต่พอลองผ่านครั้งแรก

min_diff_female_ds = df_to_dataset(augmented_female_pos)

ชุดข้อมูล MinDiff ทั้งสองชุดมีขนาดเล็กกว่าตัวอย่างที่แนะนำ 5,000 รายการขึ้นไปอย่างมีนัยสำคัญ แม้ว่าจะสมเหตุสมผลที่จะพยายามใช้ 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 ตามลำดับ

การสร้างชุดข้อมูลการฝึกอบรมของคุณ

ในขั้นตอนสุดท้าย ชุดข้อมูลสามชุด (ชุดข้อมูลที่สร้างขึ้นใหม่และชุดเดิม 2 ชุด) จะต้องรวมกันเป็นชุดข้อมูลเดียวที่สามารถส่งผ่านไปยังแบบจำลองได้

แบทช์ชุดข้อมูล

ก่อนรวมชุดข้อมูลจะต้องแบทช์

  • ชุดข้อมูลดั้งเดิมสามารถใช้ชุดงานเดียวกันกับที่ใช้ก่อนที่จะรวม 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 ฟังก์ชั่นตามที่อธิบายไว้ในคู่มือนี้

คู่มือที่เหลือจะต่อยอดจากสิ่งเหล่านี้เพื่อแสดงวิธีใช้ส่วนอื่นๆ ของห้องสมุด