Chuẩn bị dữ liệu MinDiff

Giới thiệu

Khi triển khai MinDiff, bạn sẽ cần phải đưa ra các quyết định phức tạp khi bạn chọn và định hình đầu vào của mình trước khi chuyển nó cho mô hình. Những quyết định này sẽ xác định phần lớn hành vi của MinDiff trong mô hình của bạn.

Hướng dẫn này sẽ đề cập đến các khía cạnh kỹ thuật của quy trình này, nhưng sẽ không thảo luận về cách đánh giá mô hình cho công bằng, hoặc cách xác định các phần và số liệu cụ thể để đánh giá. Xin vui lòng xem các hướng dẫn chỉ số Công bằng để biết chi tiết về vấn đề này.

Để chứng minh MinDiff, hướng dẫn này sử dụng số liệu thu nhập UCI . Nhiệm vụ của mô hình là dự đoán liệu một cá nhân có thu nhập vượt quá $ 50k hay không, dựa trên các thuộc tính cá nhân khác nhau. Hướng dẫn này giả định có một khoảng cách có vấn đề trong FNR (tỷ lệ âm tính giả) giữa "Male""Female" lát và chủ sở hữu mô hình (bạn) đã quyết định áp dụng MinDiff để giải quyết vấn đề này. Để biết thêm thông tin về các tình huống trong đó người ta có thể chọn áp dụng MinDiff, xem trang yêu cầu .

MinDiff hoạt động bằng cách phạt sự khác biệt về điểm phân phối giữa các ví dụ trong hai bộ dữ liệu. Hướng dẫn này sẽ trình bày cách chọn và xây dựng các bộ MinDiff bổ sung này cũng như cách gói mọi thứ lại với nhau để có thể chuyển nó đến một mô hình để đào tạo.

Thành lập

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

Dữ liệu gốc

Đối với mục đích trình diễn và để giảm thời gian chạy, hướng dẫn này chỉ sử dụng một phần mẫu của tập dữ liệu Thu nhập UCI. Trong cài đặt sản xuất thực, tập dữ liệu đầy đủ sẽ được sử dụng.

# 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

Chuyển đổi sang tf.data.Dataset

MinDiffModel yêu cầu đầu vào là một tf.data.Dataset . Nếu bạn đang sử dụng định dạng đầu vào khác trước khi tích hợp MinDiff, bạn sẽ phải chuyển đổi dữ liệu đầu vào của mình.

Sử dụng tf.data.Dataset.from_tensor_slices chuyển đổi sang tf.data.Dataset .

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

Xem Model.fit tài liệu hướng dẫn để biết chi tiết về tương đồng giữa hai phương pháp đầu vào.

Trong hướng dẫn này, đầu vào được tải xuống dưới dạng Pandas DataFrame và do đó, cần chuyển đổi này.

# 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)

Tạo dữ liệu MinDiff

Trong quá trình đào tạo, MinDiff sẽ khuyến khích mô hình giảm bớt sự khác biệt về dự đoán giữa hai tập dữ liệu bổ sung (có thể bao gồm các ví dụ từ tập dữ liệu gốc). Việc lựa chọn hai tập dữ liệu này là quyết định quan trọng sẽ xác định tác động của MinDiff đối với mô hình.

Hai tập dữ liệu nên được chọn sao cho sự chênh lệch về hiệu suất mà bạn đang cố gắng khắc phục là rõ ràng và được thể hiện tốt. Vì mục đích là để giảm bớt một khoảng trống trong FNR giữa "Male""Female" lát, điều này có nghĩa là tạo ra một bộ dữ liệu với chỉ dán nhãn một cách tích cực "Male" ví dụ và khác với chỉ dán nhãn một cách tích cực "Female" ví dụ; đây sẽ là các tập dữ liệu MinDiff.

Đầu tiên, hãy kiểm tra dữ liệu hiện tại.

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

Hoàn toàn có thể chấp nhận được việc tạo tập dữ liệu MinDiff từ các tập con của tập dữ liệu gốc.

Trong khi không có 5.000 hoặc tích cực hơn "Male" ví dụ như đề nghị trong hướng dẫn yêu cầu , có hơn 2.000 và nó là hợp lý để cố gắng với nhiều trước khi thu thập nhiều dữ liệu hơn.

min_diff_male_ds = df_to_dataset(male_pos)

Tích cực "Female" ví dụ, tuy nhiên, nhiều khan hiếm tại 385. Đây có lẽ là quá nhỏ so với hiệu suất tốt và như vậy sẽ đòi hỏi kéo trong ví dụ bổ sung.

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

Việc sử dụng tập dữ liệu đầy đủ đã tăng hơn gấp ba lần số lượng ví dụ có thể được sử dụng cho MinDiff. Nó vẫn còn thấp nhưng nó là đủ để cố gắng như một lần vượt qua đầu tiên.

min_diff_female_ds = df_to_dataset(augmented_female_pos)

Cả hai tập dữ liệu MinDiff đều nhỏ hơn đáng kể so với 5.000 ví dụ được đề xuất trở lên. Mặc dù việc cố gắng áp dụng MinDiff với dữ liệu hiện tại là hợp lý, nhưng bạn có thể cần cân nhắc thu thập thêm dữ liệu nếu bạn quan sát thấy hiệu suất kém hoặc trang bị quá mức trong quá trình đào tạo.

Sử dụng tf.data.Dataset.filter

Ngoài ra, bạn có thể tạo ra hai tập dữ liệu MinDiff trực tiếp từ bản gốc được chuyển đổi 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()

Kết quả alternate_min_diff_male_dsalternate_min_diff_female_ds sẽ tương đương với sản lượng để min_diff_male_dsmin_diff_female_ds tương ứng.

Xây dựng tập dữ liệu đào tạo của bạn

Bước cuối cùng, ba tập dữ liệu (hai tập dữ liệu mới được tạo và tập dữ liệu ban đầu) cần được hợp nhất thành một tập dữ liệu duy nhất có thể được chuyển đến mô hình.

Kết hợp các bộ dữ liệu

Trước khi hợp nhất, các tập dữ liệu cần phải được phân lô.

  • Tập dữ liệu ban đầu có thể sử dụng cùng một lô đã được sử dụng trước khi tích hợp MinDiff.
  • Tập dữ liệu MinDiff không cần phải có cùng kích thước lô với tập dữ liệu gốc. Trong tất cả các khả năng, một cái nhỏ hơn cũng sẽ hoạt động tốt. Mặc dù chúng thậm chí không cần phải có cùng kích thước lô với nhau, nhưng bạn nên làm như vậy để có hiệu suất tốt nhất.

Mặc dù không thực sự cần thiết, nó được khuyến khích để sử dụng drop_remainder=True cho hai tập dữ liệu MinDiff vì điều này sẽ đảm bảo rằng họ có kích thước hàng loạt quán.

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)

Đóng gói các Datasets với pack_min_diff_data

Khi các tập dữ liệu được chuẩn bị, hãy đóng gói chúng thành một tập dữ liệu duy nhất, sau đó sẽ được chuyển đến mô hình. Một lô duy nhất từ ​​tập dữ liệu kết quả sẽ chứa một lô từ mỗi trong ba tập dữ liệu mà bạn đã chuẩn bị trước đó.

Bạn có thể làm điều này bằng cách sử dụng cung cấp utils chức năng trong tensorflow_model_remediation gói:

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)

Và đó là nó! Bạn sẽ có thể sử dụng khác util chức năng trong gói đến lô cá nhân giải nén nếu cần thiết.

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)

Với dữ liệu mới được hình thành của bạn, bây giờ bạn đã sẵn sàng áp dụng MinDiff trong mô hình của mình! Để tìm hiểu cách này được thực hiện, xin hãy xem các hướng dẫn khác bắt đầu với Lồng ghép MinDiff với MinDiffModel .

Sử dụng định dạng đóng gói tùy chỉnh (tùy chọn)

Bạn có thể quyết định gói ba bộ dữ liệu lại với nhau theo bất kỳ cách nào bạn chọn. Yêu cầu duy nhất là bạn sẽ cần đảm bảo mô hình biết cách diễn giải dữ liệu. Việc thực hiện mặc định của MinDiffModel giả định rằng các dữ liệu đã được đóng gói bằng min_diff.keras.utils.pack_min_diff_data .

Một cách dễ dàng để định dạng đầu vào của bạn như bạn muốn là để chuyển đổi dữ liệu như một bước cuối cùng sau khi bạn đã sử dụng 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)

Mô hình của bạn sẽ cần phải biết làm thế nào để đọc đầu vào tùy chỉnh này được nêu chi tiết trong hướng dẫn Tuỳ chỉnh 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']

Tài nguyên bổ sung

Hướng dẫn này phác thảo quy trình và việc ra quyết định mà bạn có thể làm theo bất cứ khi nào áp dụng MinDiff. Phần còn lại của các hướng dẫn xây dựng dựa trên khuôn khổ này. Để làm cho việc này dễ dàng hơn, logic tìm thấy trong hướng dẫn này đã được phân tích thành các hàm trợ giúp:

  • get_uci_data : Chức năng này đã được sử dụng trong hướng dẫn này. Nó trả về một DataFrame chứa dữ liệu thu nhập UCI từ sự chia rẽ chỉ định lấy mẫu tại bất kỳ tỷ lệ được chỉ định (100% nếu không xác định).
  • df_to_dataset : Chức năng này chuyển đổi một DataFrame thành một tf.data.Dataset được nêu chi tiết trong hướng dẫn này với các tính năng bổ sung của việc có thể để vượt qua batch_size như một tham số.
  • get_uci_with_min_diff_dataset : Chức năng này trả về một tf.data.Dataset chứa cả dữ liệu gốc và dữ liệu MinDiff đóng gói lại với nhau bằng cách sử dụng mẫu Xử lý ô nhiễm Library util chức năng như mô tả trong hướng dẫn này.

Phần còn lại của các hướng dẫn sẽ dựa trên những hướng dẫn này để chỉ ra cách sử dụng các phần khác của thư viện.