모델 수정 사례 연구

이 노트북에서 우리는 텍스트 분류기를 훈련하여 유독하거나 유해한 것으로 간주될 수 있는 서면 콘텐츠를 식별하고 MinDiff를 적용하여 일부 공정성 문제를 수정할 것입니다. 워크플로에서 다음을 수행합니다.

  1. 민감한 그룹에 대한 참조가 포함된 텍스트에 대한 기준 모델의 성능을 평가합니다.
  2. MinDiff로 훈련하여 성과가 저조한 그룹의 성과를 개선하십시오.
  3. 선택한 측정항목에 대해 새 모델의 성능을 평가합니다.

우리의 목적은 기계 학습의 공정성에 대한 원칙적인 접근 방식을 제시하는 것이 아니라 매우 최소한의 워크플로로 MinDiff 기술의 사용을 시연하는 것입니다. 따라서 우리의 평가는 하나의 민감한 카테고리와 단일 측정항목에만 초점을 맞출 것입니다. 또한 데이터 세트의 잠재적인 단점을 해결하거나 구성을 조정하지 않습니다. 프로덕션 환경에서는 이들 각각에 엄격하게 접근하고 싶을 것입니다. 공정성에 대한 평가에 대한 자세한 내용은 이 가이드를 .

설정

공정성 지표 및 TensorFlow 모델 수정을 설치하는 것으로 시작합니다.

설치

평가를 위해 MinDiff 및 공정성 지표를 포함하여 필요한 모든 구성 요소를 가져옵니다.

수입품

유틸리티 함수를 사용하여 전처리된 데이터를 다운로드하고 모델의 출력 모양과 일치하도록 레이블을 준비합니다. 이 기능은 또한 데이터를 TFRecord로 다운로드하여 나중에 평가를 더 빠르게 수행할 수 있도록 합니다. 또는 사용 가능한 유틸리티 변환 기능을 사용하여 Pandas DataFrame을 TFRecord로 변환할 수 있습니다.

# 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

몇 가지 유용한 상수를 정의합니다. 우리는에 모델을 학습합니다 'comment_text' 우리의 목표 라벨, 기능 'toxicity' . 여기서 배치 크기는 임의로 선택되지만 프로덕션 설정에서는 최상의 성능을 위해 조정해야 합니다.

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

임의의 시드를 설정합니다. (이렇게 해도 결과가 완전히 안정화되지는 않습니다.)

씨앗

기준 모델 정의 및 학습

런타임을 줄이기 위해 기본적으로 사전 훈련된 모델을 사용합니다. 독성 예측을 출력하는 초기 임베딩 및 컨볼루션 레이어가 있는 간단한 Keras 순차 모델입니다. 원하는 경우 이를 변경하고 유틸리티 기능을 사용하여 모델을 생성하여 처음부터 훈련할 수 있습니다. (사용자의 환경이 우리와 다를 수 있으므로 조정 및 평가 임계값을 사용자 정의해야 합니다.)

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)

우리는 사용 평가하기 위해 모델을 저장 공정성 지표를 .

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

다음으로 공정성 지표를 실행합니다. 다시 말씀 드리지만, 우리는 단지 하나 개의 범주, 종교 단체를 참조 의견을 슬라이스 평가를 수행 할 것입니다. 프로덕션 환경에서는 평가할 범주와 메트릭을 결정할 때 신중하게 접근하는 것이 좋습니다.

모델 성능을 계산하기 위해 유틸리티 함수는 메트릭, 슬라이스 및 분류자 임계값에 대해 몇 가지 편리한 선택을 합니다.

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

평가 결과 렌더링

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

평가 결과를 살펴보자. 임계값이 0.450인 메트릭 FPR(오탐지율)을 선택하십시오. 우리는 모델이 다른 종교 그룹과 마찬가지로 일부 종교 그룹에 대해 잘 수행되지 않고 훨씬 더 높은 FPR을 표시함을 알 수 있습니다. 일부 그룹에는 예가 너무 적기 때문에 넓은 신뢰 구간에 유의하십시오. 이로 인해 이러한 슬라이스의 성능에 상당한 차이가 있다고 확실히 말하기는 어렵습니다. 이 문제를 해결하기 위해 더 많은 예를 수집할 수 있습니다. 그러나 실적이 저조하다고 확신하는 두 그룹에 MinDiff를 적용할 수 있습니다.

FPR이 높을수록 이러한 ID 그룹을 참조하는 댓글이 다른 댓글보다 유독한 것으로 잘못 표시될 가능성이 더 높기 때문에 우리는 FPR에 집중하기로 결정했습니다. 이는 종교에 대한 대화에 참여하는 사용자에게 불공평한 결과를 초래할 수 있지만 다른 측정항목의 차이는 다른 유형의 피해로 이어질 수 있습니다.

MinDiff 모델 정의 및 훈련

이제 실적이 저조한 종교 단체에 대한 FPR을 개선하기 위해 노력할 것입니다. 우리는 사용 그렇게하려고 할 것이다 MinDiff , 훈련 기간 동안 성능 격차를 처벌하여 데이터의 조각에서 오류 비율의 균형을 추구 재조정 기술을. MinDiff를 적용하면 다른 슬라이스에서 모델 성능이 약간 저하될 수 있습니다. 따라서 MinDiff의 목표는 다음과 같습니다.

  • 실적이 저조한 그룹의 성능 향상
  • 다른 그룹 및 전체 성능에 대한 제한된 성능 저하

데이터 준비

MinDiff를 사용하기 위해 두 개의 추가 데이터 분할을 생성합니다.

  • 소수 집단을 언급하는 무해한 예에 대한 분할: 우리의 경우 여기에는 실적이 저조한 정체성 용어에 대한 언급이 포함됩니다. 예가 너무 적어서 넓은 신뢰 구간 범위에서 더 높은 불확실성으로 이어지기 때문에 일부 그룹은 포함하지 않았습니다.
  • 다수 그룹을 참조하는 무독성 사례에 대한 분할.

실적이 저조한 클래스에 속하는 충분한 예제를 갖는 것이 중요합니다. 모델 아키텍처, 데이터 배포 및 MinDiff 구성에 따라 필요한 데이터 양이 크게 다를 수 있습니다. 과거 애플리케이션에서 우리는 MinDiff가 각 데이터 분할에서 5,000개의 예제와 잘 작동하는 것을 보았습니다.

우리의 경우 소수 분할에 있는 그룹의 예시 수량은 9,688 및 3,906입니다. 데이터 세트의 클래스 불균형에 유의하십시오. 실제로 이것은 우려의 원인이 될 수 있지만 우리의 의도는 MinDiff를 시연하는 것이므로 이 노트북에서 다루지 않을 것입니다.

MinDiff가 이러한 예를 올바르게 얻는 데 최적화할 수 있도록 이러한 그룹에 대해 부정적인 예만 선택합니다. 우리가 주로 위양성률의 불균형에 관심을하는 경우 지상 진실 부정적인 예제 세트를 개척, 그러나 거짓 긍정적 인 예측이 문제에 우리가 어떤 잘못 긍정적으로 분류있어 접지 진실 부정적인 예입니다 것을 기억하는 것이 직관적 보일 수 있습니다 해결하려고 합니다.

MinDiff 데이터 프레임 생성

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

또한 Pandas DataFrames를 MinDiff 입력을 위한 Tensorflow Datasets로 변환해야 합니다. Pandas DataFrames용 Keras 모델 API와 달리 Datasets를 사용한다는 것은 하나의 Dataset에서 모델의 입력 기능과 레이블을 함께 제공해야 함을 의미합니다. 여기에 우리가 제공하는 'comment_text' 입력 기능 등을하고 모델의 예상 출력과 일치하는 라벨을 바꿀.

MinDiff는 일괄 처리된 데이터 세트를 필요로 하기 때문에 이 단계에서도 데이터 세트를 일괄 처리합니다. 모델 성능과 균형을 유지하면서 훈련 속도와 하드웨어 고려 사항을 고려하여 기준 모델에 대해 조정된 것과 동일한 방식으로 배치 크기 선택을 조정합니다. 여기에서는 세 가지 데이터 세트 모두에 대해 동일한 배치 크기를 선택했지만 이것이 필수 사항은 아니지만 두 개의 MinDiff 배치 크기를 동일하게 하는 것이 좋습니다.

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)

모델 학습 및 평가

MinDiff와 함께 훈련을하려면 원래 모델을 가지고 대응으로 MinDiffModel에 포장 lossloss_weight . 우리는 기본 1.5 사용하는 loss_weight 하지만 모델 및 제품 요구 사항에 의존하기 때문에 이것은, 사용 사례에 맞게 조정해야하는 매개 변수입니다. 값을 변경하는 실험을 통해 모델에 미치는 영향을 확인할 수 있습니다. 값을 늘리면 소수 그룹과 다수 그룹의 성과가 더 가까워지지만 더 분명한 절충안이 생길 수 있습니다.

그런 다음 모델을 정상적으로 컴파일하고(MinDiff가 아닌 일반 손실 사용) 훈련에 적합합니다.

MinDiff 모델 훈련

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

다음으로 결과를 평가합니다.

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

새 모델을 올바르게 평가하려면 기준 모델과 동일한 방식으로 임계값을 선택해야 합니다. 프로덕션 환경에서 이는 평가 지표가 출시 표준을 충족하는지 확인하는 것을 의미합니다. 우리의 경우 기본 모델과 유사한 전체 FPR을 초래하는 임계값을 선택합니다. 이 임계값은 기준 모델에 대해 선택한 임계값과 다를 수 있습니다. 임계값이 0.400인 위양성 비율을 선택하십시오. (예를 들어 양이 매우 적은 부분군은 신뢰 범위 구간이 매우 넓고 예측 가능한 결과가 없습니다.)

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

이 결과를 검토하면 대상 그룹에 대한 FPR이 개선되었음을 알 수 있습니다. 가장 낮은 성과 그룹과 다수 그룹 간의 격차가 .024에서 .006으로 개선되었습니다. 우리가 관찰한 개선 사항과 다수 그룹의 지속적인 강력한 성능을 감안할 때 우리는 두 가지 목표를 모두 충족했습니다. 제품에 따라 추가 개선이 필요할 수 있지만 이 접근 방식을 통해 우리 모델은 모든 사용자에게 공평한 성능을 발휘하는 데 한 걸음 더 가까워졌습니다.