Nghiên cứu điển hình về khắc phục ô nhiễm mô hình

Trong sổ tay này, chúng tôi sẽ đào tạo một bộ phân loại văn bản để xác định nội dung viết có thể được coi là độc hại hoặc có hại và áp dụng MinDiff để khắc phục một số lo ngại về tính công bằng. Trong quy trình làm việc của mình, chúng tôi sẽ:

  1. Đánh giá hiệu suất của mô hình cơ sở của chúng tôi trên văn bản chứa tham chiếu đến các nhóm nhạy cảm.
  2. Cải thiện hiệu suất của bất kỳ nhóm hoạt động kém nào bằng cách đào tạo với MinDiff.
  3. Đánh giá hiệu suất của mô hình mới dựa trên chỉ số đã chọn của chúng tôi.

Mục đích của chúng tôi là để chứng minh việc sử dụng kỹ thuật MinDiff với quy trình làm việc rất tối thiểu, chứ không phải để đưa ra phương pháp tiếp cận có nguyên tắc về tính công bằng trong học máy. Do đó, đánh giá của chúng tôi sẽ chỉ tập trung vào một danh mục nhạy cảm và một chỉ số duy nhất. Chúng tôi cũng không giải quyết những thiếu sót tiềm ẩn trong tập dữ liệu, cũng như không điều chỉnh cấu hình của chúng tôi. Trong bối cảnh sản xuất, bạn sẽ muốn tiếp cận từng điều này một cách nghiêm ngặt. Để biết thêm thông tin về đánh giá cho công bằng, xem hướng dẫn này .

Thành lập

Chúng tôi bắt đầu bằng cách cài đặt Chỉ báo công bằng và Khắc phục mô hình TensorFlow.

Số lượt cài đặt

Nhập tất cả các thành phần cần thiết, bao gồm MinDiff và Chỉ số Công bằng để đánh giá.

Nhập khẩu

Chúng tôi sử dụng một chức năng tiện ích để tải xuống dữ liệu được xử lý trước và chuẩn bị các nhãn để phù hợp với hình dạng đầu ra của mô hình. Chức năng này cũng tải dữ liệu dưới dạng TFRecords để thực hiện đánh giá sau này nhanh hơn. Ngoài ra, bạn có thể chuyển đổi Pandas DataFrame thành TFRecords bằng bất kỳ chức năng chuyển đổi tiện ích nào có sẵn.

# We use a helper utility to preprocessed data for convenience and speed.
data_train, data_validate, validate_tfrecord_file, labels_train, labels_validate = min_diff_keras_utils.download_and_process_civil_comments_data()
Downloading data from https://storage.googleapis.com/civil_comments_dataset/train_df_processed.csv
345702400/345699197 [==============================] - 8s 0us/step
Downloading data from https://storage.googleapis.com/civil_comments_dataset/validate_df_processed.csv
229974016/229970098 [==============================] - 5s 0us/step
Downloading data from https://storage.googleapis.com/civil_comments_dataset/validate_tf_processed.tfrecord
324943872/324941336 [==============================] - 9s 0us/step

Chúng tôi xác định một vài hằng số hữu ích. Chúng tôi sẽ đào tạo các mô hình trên 'comment_text' tính năng, với nhãn mục tiêu của chúng tôi như 'toxicity' . Lưu ý rằng kích thước lô ở đây được chọn tùy ý, nhưng trong cài đặt sản xuất, bạn sẽ cần điều chỉnh để có hiệu suất tốt nhất.

TEXT_FEATURE = 'comment_text'
LABEL = 'toxicity'
BATCH_SIZE = 512

Đặt hạt giống ngẫu nhiên. (Lưu ý rằng điều này không hoàn toàn ổn định kết quả.)

Hạt giống

Xác định và đào tạo mô hình cơ sở

Để giảm thời gian chạy, chúng tôi sử dụng mô hình định sẵn theo mặc định. Đây là một mô hình tuần tự Keras đơn giản với các lớp tích hợp và nhúng ban đầu, đưa ra dự đoán độc tính. Nếu muốn, bạn có thể thay đổi điều này và đào tạo lại từ đầu bằng cách sử dụng chức năng tiện ích của chúng tôi để tạo mô hình. (Lưu ý rằng vì môi trường của bạn có thể khác với môi trường của chúng tôi, bạn sẽ cần phải tùy chỉnh các ngưỡng điều chỉnh và đánh giá.)

use_pretrained_model = True

if use_pretrained_model:
  URL = 'https://storage.googleapis.com/civil_comments_model/baseline_model.zip'
  BASE_PATH = tempfile.mkdtemp()
  ZIP_PATH = os.path.join(BASE_PATH, 'baseline_model.zip')
  MODEL_PATH = os.path.join(BASE_PATH, 'tmp/baseline_model')

  r = requests.get(URL, allow_redirects=True)
  open(ZIP_PATH, 'wb').write(r.content)

  with zipfile.ZipFile(ZIP_PATH, 'r') as zip_ref:
    zip_ref.extractall(BASE_PATH)
  baseline_model = tf.keras.models.load_model(
      MODEL_PATH, custom_objects={'KerasLayer' : hub.KerasLayer})
else:
  optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
  loss = tf.keras.losses.BinaryCrossentropy()

  baseline_model = min_diff_keras_utils.create_keras_sequential_model()

  baseline_model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])

  baseline_model.fit(x=data_train[TEXT_FEATURE],
                     y=labels_train,
                     batch_size=BATCH_SIZE,
                     epochs=20)

Chúng tôi lưu các mô hình để đánh giá bằng chỉ số Công bằng .

base_dir = tempfile.mkdtemp(prefix='saved_models')
baseline_model_location = os.path.join(base_dir, 'model_export_baseline')
baseline_model.save(baseline_model_location, save_format='tf')
INFO:tensorflow:Assets written to: /tmp/saved_models867b8d74/model_export_baseline/assets
INFO:tensorflow:Assets written to: /tmp/saved_models867b8d74/model_export_baseline/assets

Tiếp theo, chúng tôi chạy Chỉ báo Công bằng. Xin nhắc lại, chúng tôi chỉ đi để thực hiện đánh giá thái lát để lấy ý kiến tham khảo một thể loại, các nhóm tôn giáo. Trong môi trường sản xuất, chúng tôi khuyên bạn nên thực hiện một cách tiếp cận chu đáo để xác định danh mục và chỉ số nào cần đánh giá.

Để tính toán hiệu suất của mô hình, chức năng tiện ích đưa ra một số lựa chọn thuận tiện cho các ngưỡng số liệu, lát cắt và bộ phân loại.

# We use a helper utility to hide the evaluation logic for readability.
base_dir = tempfile.mkdtemp(prefix='eval')
eval_dir = os.path.join(base_dir, 'tfma_eval_result')
eval_result = fi_util.get_eval_results(
    baseline_model_location, eval_dir, validate_tfrecord_file)
WARNING:absl:Tensorflow version (2.5.0) found. Note that TFMA support for TF 2.0 is currently in beta
WARNING:apache_beam.runners.interactive.interactive_environment:Dependencies required for Interactive Beam PCollection visualization are not available, please use: `pip install apache-beam[interactive]` to install necessary dependencies to enable all data visualization features.
WARNING:apache_beam.io.tfrecordio:Couldn't find python-snappy so the implementation of _TFRecordUtil._masked_crc32c is not as fast as it could be.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_model_analysis/writers/metrics_plots_and_validations_writer.py:113: tf_record_iterator (from tensorflow.python.lib.io.tf_record) is deprecated and will be removed in a future version.
Instructions for updating:
Use eager execution and: 
`tf.data.TFRecordDataset(path)`
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_model_analysis/writers/metrics_plots_and_validations_writer.py:113: tf_record_iterator (from tensorflow.python.lib.io.tf_record) is deprecated and will be removed in a future version.
Instructions for updating:
Use eager execution and: 
`tf.data.TFRecordDataset(path)`

Kết xuất kết quả đánh giá

widget_view.render_fairness_indicator(eval_result)
FairnessIndicatorViewer(slicingMetrics=[{'sliceValue': 'Overall', 'slice': 'Overall', 'metrics': {'accuracy': …

Hãy cùng nhìn vào kết quả đánh giá. Hãy thử chọn tỷ lệ dương tính giả theo chỉ số (FPR) với ngưỡng 0,450. Chúng ta có thể thấy rằng mô hình không hoạt động tốt đối với một số nhóm tôn giáo cũng như đối với những nhóm khác, hiển thị FPR cao hơn nhiều. Lưu ý khoảng tin cậy rộng trên một số nhóm vì chúng có quá ít ví dụ. Điều này làm cho khó có thể nói một cách chắc chắn rằng có sự khác biệt đáng kể về hiệu suất cho các lát cắt này. Chúng tôi có thể muốn thu thập thêm các ví dụ để giải quyết vấn đề này. Tuy nhiên, chúng tôi có thể thử áp dụng MinDiff cho hai nhóm mà chúng tôi tin rằng đang hoạt động kém hiệu quả.

Chúng tôi đã chọn tập trung vào FPR, vì FPR cao hơn có nghĩa là các nhận xét đề cập đến các nhóm nhận dạng này có nhiều khả năng bị gắn cờ không chính xác là độc hại hơn các nhận xét khác. Điều này có thể dẫn đến kết quả không công bằng cho những người dùng tham gia vào cuộc đối thoại về tôn giáo, nhưng lưu ý rằng sự chênh lệch về các chỉ số khác có thể dẫn đến các loại tác hại khác.

Xác định và đào tạo mô hình MinDiff

Bây giờ, chúng tôi sẽ cố gắng cải thiện FPR cho các nhóm tôn giáo hoạt động kém hiệu quả. Chúng tôi sẽ cố gắng làm như vậy bằng MinDiff , một kỹ thuật khắc phục mà tìm cách cân bằng tỷ lệ lỗi trên lát dữ liệu của bạn bằng cách xử phạt chênh lệch trong việc thực hiện quá trình đào tạo. Khi chúng tôi áp dụng MinDiff, hiệu suất của mô hình có thể giảm nhẹ trên các phần khác. Như vậy, mục tiêu của chúng tôi với MinDiff sẽ là:

  • Cải thiện hiệu suất cho các nhóm hoạt động kém
  • Sự suy giảm hạn chế đối với các nhóm khác và hiệu suất tổng thể

Chuẩn bị dữ liệu của bạn

Để sử dụng MinDiff, chúng tôi tạo hai phần tách dữ liệu bổ sung:

  • Sự phân chia cho các ví dụ không độc hại đề cập đến các nhóm thiểu số: Trong trường hợp của chúng tôi, điều này sẽ bao gồm các nhận xét có tham chiếu đến các điều khoản nhận dạng hoạt động kém hiệu quả của chúng tôi. Chúng tôi không bao gồm một số nhóm vì có quá ít ví dụ, dẫn đến độ không chắc chắn cao hơn với phạm vi khoảng tin cậy rộng.
  • Sự phân chia cho các ví dụ không độc hại tham chiếu đến nhóm đa số.

Điều quan trọng là phải có đủ các ví dụ về các lớp kém hiệu quả. Dựa trên kiến ​​trúc mô hình, phân phối dữ liệu và cấu hình MinDiff của bạn, lượng dữ liệu cần thiết có thể thay đổi đáng kể. Trong các ứng dụng trước đây, chúng tôi đã thấy MinDiff hoạt động tốt với 5.000 ví dụ trong mỗi lần phân chia dữ liệu.

Trong trường hợp của chúng tôi, các nhóm trong nhóm thiểu số có số lượng ví dụ là 9,688 và 3,906. Lưu ý sự mất cân bằng của lớp trong tập dữ liệu; trong thực tế, điều này có thể gây lo ngại, nhưng chúng tôi sẽ không tìm cách giải quyết chúng trong sổ ghi chép này vì mục đích của chúng tôi chỉ là chứng minh MinDiff.

Chúng tôi chỉ chọn các ví dụ tiêu cực cho các nhóm này để MinDiff có thể tối ưu hóa việc đưa các ví dụ này vào đúng. Nó có thể có vẻ phản trực giác để carve ra bộ ví dụ tiêu cực thực địa nếu chúng ta chủ yếu quan tâm đến việc chênh lệch trong tỷ lệ dương tính giả, nhưng hãy nhớ rằng một dự đoán dương tính giả là một ví dụ thực địa tiêu cực đó là không đúng phân loại là tích cực, đó là chúng ta vấn đề đang cố gắng giải quyết.

Tạo MinDiff DataFrames

# Create masks for the sensitive and nonsensitive groups
minority_mask = data_train.religion.apply(
    lambda x: any(religion in x for religion in ('jewish', 'muslim')))
majority_mask = data_train.religion.apply(lambda x: x == "['christian']")

# Select nontoxic examples, so MinDiff will be able to reduce sensitive FP rate.
true_negative_mask = data_train['toxicity'] == 0

data_train_main = copy.copy(data_train)
data_train_sensitive = data_train[minority_mask & true_negative_mask]
data_train_nonsensitive = data_train[majority_mask & true_negative_mask]

Chúng tôi cũng cần chuyển đổi Pandas DataFrames thành Tensorflow Datasets cho đầu vào MinDiff. Lưu ý rằng không giống như API mô hình Keras cho Pandas DataFrames, sử dụng Tập dữ liệu có nghĩa là chúng ta cần cung cấp các tính năng và nhãn đầu vào của mô hình cùng nhau trong một Tập dữ liệu. Dưới đây chúng tôi cung cấp các 'comment_text' như một tính năng đầu vào và định hình lại nhãn để phù hợp với sản lượng dự kiến của mô hình.

Chúng tôi cũng chia lô Tập dữ liệu ở giai đoạn này, vì MinDiff yêu cầu Tập dữ liệu theo lô. Lưu ý rằng chúng tôi điều chỉnh lựa chọn kích thước lô giống như cách nó được điều chỉnh cho mô hình cơ sở, có tính đến tốc độ đào tạo và các cân nhắc về phần cứng trong khi cân bằng với hiệu suất của mô hình. Ở đây chúng tôi đã chọn cùng một kích thước lô cho cả ba tập dữ liệu nhưng đây không phải là một yêu cầu bắt buộc, mặc dù thực tiễn tốt là có hai kích thước lô MinDiff tương đương nhau.

Tạo tập dữ liệu MinDiff

# Convert the pandas DataFrames to Datasets.
dataset_train_main = tf.data.Dataset.from_tensor_slices(
    (data_train_main['comment_text'].values, 
     data_train_main.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)
dataset_train_sensitive = tf.data.Dataset.from_tensor_slices(
    (data_train_sensitive['comment_text'].values, 
     data_train_sensitive.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)
dataset_train_nonsensitive = tf.data.Dataset.from_tensor_slices(
    (data_train_nonsensitive['comment_text'].values, 
     data_train_nonsensitive.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)

Đào tạo và đánh giá mô hình

Để đào tạo với MinDiff, chỉ cần đi theo mô hình ban đầu và bọc nó trong một MinDiffModel với một tương ứng với lossloss_weight . Chúng tôi đang sử dụng 1,5 như là mặc định loss_weight , nhưng đây là một tham số mà cần phải được điều chỉnh đối với trường hợp sử dụng của bạn, vì nó phụ thuộc vào yêu cầu của mô hình và sản phẩm của bạn. Bạn có thể thử nghiệm với việc thay đổi giá trị để xem nó tác động như thế nào đến mô hình, lưu ý rằng việc tăng giá trị sẽ đẩy hiệu suất của nhóm thiểu số và đa số đến gần nhau hơn nhưng có thể đi kèm với sự đánh đổi rõ rệt hơn.

Sau đó, chúng tôi biên dịch mô hình bình thường (sử dụng mất mát không phải MinDiff thông thường) và phù hợp để đào tạo.

Train MinDiffModel

use_pretrained_model = True

base_dir = tempfile.mkdtemp(prefix='saved_models')
min_diff_model_location = os.path.join(base_dir, 'model_export_min_diff')

if use_pretrained_model:
  BASE_MIN_DIFF_PATH = tempfile.mkdtemp()
  MIN_DIFF_URL = 'https://storage.googleapis.com/civil_comments_model/min_diff_model.zip'
  ZIP_PATH = os.path.join(BASE_PATH, 'min_diff_model.zip')
  MIN_DIFF_MODEL_PATH = os.path.join(BASE_MIN_DIFF_PATH, 'tmp/min_diff_model')
  DIRPATH = '/tmp/min_diff_model'

  r = requests.get(MIN_DIFF_URL, allow_redirects=True)
  open(ZIP_PATH, 'wb').write(r.content)

  with zipfile.ZipFile(ZIP_PATH, 'r') as zip_ref:
    zip_ref.extractall(BASE_MIN_DIFF_PATH)
  min_diff_model = tf.keras.models.load_model(
      MIN_DIFF_MODEL_PATH, custom_objects={'KerasLayer' : hub.KerasLayer})

  min_diff_model.save(min_diff_model_location, save_format='tf')

else:
  min_diff_weight = 1.5

  # Create the dataset that will be passed to the MinDiffModel during training.
  dataset = md.keras.utils.input_utils.pack_min_diff_data(
      dataset_train_main, dataset_train_sensitive, dataset_train_nonsensitive)

  # Create the original model.
  original_model = min_diff_keras_utils.create_keras_sequential_model()

  # Wrap the original model in a MinDiffModel, passing in one of the MinDiff
  # losses and using the set loss_weight.
  min_diff_loss = md.losses.MMDLoss()
  min_diff_model = md.keras.MinDiffModel(original_model,
                                         min_diff_loss,
                                         min_diff_weight)

  # Compile the model normally after wrapping the original model.  Note that
  # this means we use the baseline's model's loss here.
  optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
  loss = tf.keras.losses.BinaryCrossentropy()
  min_diff_model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])

  min_diff_model.fit(dataset, epochs=20)

  min_diff_model.save_original_model(min_diff_model_location, save_format='tf')
INFO:tensorflow:Assets written to: /tmp/saved_modelsb3zkcos_/model_export_min_diff/assets
INFO:tensorflow:Assets written to: /tmp/saved_modelsb3zkcos_/model_export_min_diff/assets

Tiếp theo chúng tôi đánh giá kết quả.

min_diff_eval_subdir = os.path.join(base_dir, 'tfma_eval_result')
min_diff_eval_result = fi_util.get_eval_results(
    min_diff_model_location,
    min_diff_eval_subdir,
    validate_tfrecord_file,
    slice_selection='religion')
WARNING:absl:Tensorflow version (2.5.0) found. Note that TFMA support for TF 2.0 is currently in beta

Để đảm bảo chúng tôi đánh giá một mô hình mới một cách chính xác, chúng tôi cần chọn một ngưỡng giống như cách chúng tôi làm với mô hình cơ sở. Trong cài đặt sản xuất, điều này có nghĩa là đảm bảo rằng các chỉ số đánh giá đáp ứng các tiêu chuẩn ra mắt. Trong trường hợp của chúng tôi, chúng tôi sẽ chọn ngưỡng dẫn đến FPR tổng thể tương tự như mô hình cơ sở. Ngưỡng này có thể khác với ngưỡng bạn đã chọn cho mô hình cơ sở. Thử chọn tỷ lệ dương tính giả với ngưỡng 0,400. (Lưu ý rằng các nhóm con với các ví dụ về số lượng rất thấp có khoảng tin cậy rất rộng và không có kết quả dự đoán.)

widget_view.render_fairness_indicator(min_diff_eval_result)
FairnessIndicatorViewer(slicingMetrics=[{'sliceValue': 'Overall', 'slice': 'Overall', 'metrics': {'accuracy': …

Xem xét các kết quả này, bạn có thể nhận thấy rằng FPR cho các nhóm mục tiêu của chúng tôi đã được cải thiện. Khoảng cách giữa nhóm hoạt động kém nhất của chúng tôi và nhóm đa số đã được cải thiện từ 0,24 lên 0,006. Với những cải tiến mà chúng tôi đã quan sát được và hiệu suất mạnh mẽ tiếp tục cho nhóm đa số, chúng tôi đã thỏa mãn cả hai mục tiêu của mình. Tùy thuộc vào sản phẩm, có thể cần phải cải tiến thêm, nhưng cách tiếp cận này đã đưa mô hình của chúng tôi tiến gần hơn một bước đến việc hoạt động công bằng cho tất cả người dùng.