ML 커뮤니티 데이는 11월 9일입니다! TensorFlow, JAX에서 업데이트를 우리와 함께, 더 자세히 알아보기

모델 수정 사례 연구

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

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

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

설정

공정성 표시기 및 TensorFlow 모델 수정 설치부터 시작합니다.

설치

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

수입품

유틸리티 함수를 사용하여 전처리 된 데이터를 다운로드하고 모델의 출력 모양과 일치하도록 레이블을 준비합니다. 이 함수는 또한 데이터를 TFRecords로 다운로드하여 나중에 더 빨리 평가할 수 있도록합니다. 또는 사용 가능한 유틸리티 변환 기능을 사용하여 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

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

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 (false positive rate)을 선택해보십시오. 우리는 모델이 다른 종교 단체와 마찬가지로 일부 종교 단체에서 잘 수행되지 않고 훨씬 더 높은 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 데이터 프레임을 MinDiff 입력을 위해 Tensorflow 데이터 세트로 변환해야합니다. Pandas DataFrames 용 Keras 모델 API와 달리 데이터 세트를 사용한다는 것은 모델의 입력 기능과 레이블을 하나의 데이터 세트에 함께 제공해야 함을 의미합니다. 여기서는 '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로 학습하려면 원래 모델을 가져 와서 해당되는 lossloss_weight 로 MinDiffModel에 래핑하면됩니다. 1.5를 기본 loss_weight 하고 있지만 이는 모델 및 제품 요구 사항에 따라 loss_weight 때문에 사용 사례에 맞게 조정해야하는 매개 변수입니다. 값을 변경하여 모델에 어떤 영향을 미치는지 실험 할 수 있습니다. 값을 높이면 소수 그룹과 다수 그룹의 성능이 더 가까워 지지만 더 뚜렷한 절충이있을 수 있습니다.

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

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

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

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으로 개선되었습니다. 우리가 관찰 한 개선 사항과 다수 그룹의 지속적인 강력한 성과를 감안할 때 우리는 두 가지 목표를 모두 충족했습니다. 제품에 따라 추가 개선이 필요할 수 있지만이 접근 방식은 모든 사용자에게 공평한 성능을 발휘하는 데 한 단계 더 가까워졌습니다.