CelebA 데이터 세트를 사용한 TensorFlow 제한적 최적화 예

TensorFlow.org에서 보기 Google Colab에서 실행 GitHub에서 보기 노트북 다운로드

이 노트북은 TFCO 라이브러리를 사용하여 제한된 문제를 생성하고 최적화하는 쉬운 방법을 보여줍니다. 우리는 그들이 우리가 사용하여 식별 할 수있는 우리의 데이터의 다른 조각에 걸쳐 동일하게 수행하지 않는 것을 발견하면이 방법은 모델을 개선하는데 유용 할 수 있습니다 공정성 지표를 . Google의 AI 원칙 중 두 번째는 우리 기술이 불공정한 편견을 만들거나 강화하는 것을 피해야 한다는 것이며, 이 기술이 일부 상황에서 모델 공정성을 개선하는 데 도움이 될 수 있다고 믿습니다. 특히 이 노트북은 다음을 수행합니다.

  • 사용하여 이미지에있는 사람의 미소를 감지하는 간단한, 구속 신경망 모델을 훈련 tf.keras 하고 대규모 CelebFaces 속성 ( CelebA ) 데이터 세트.
  • 공정성 지표를 사용하여 연령대 전반에 걸쳐 일반적으로 사용되는 공정성 지표에 대해 모델 성능을 평가합니다.
  • 연령 그룹에 걸쳐 더 공정한 성과를 달성하기 위해 간단한 제약 최적화 문제를 설정합니다.
  • 지금은 제약 모델을 재교육하고 우리의 선택 공정성 메트릭이 향상되었는지 보장, 다시 성능을 평가한다.

마지막 업데이트: 2020년 2월 3일 11일

설치

이 노트북은에서 만든 Colaboratory 파이썬 3 구글 컴퓨 트 엔진 백엔드에 연결. 이 노트북을 다른 환경에서 호스팅하려는 경우 아래 셀에 모든 필수 패키지를 포함하면 큰 문제가 발생하지 않습니다.

pip installs를 처음 실행할 때 미리 설치된 오래된 패키지 때문에 런타임을 다시 시작하라는 메시지가 표시될 수 있습니다. 그렇게 하면 올바른 패키지가 사용됩니다.

핍 설치

아래 셀을 실행하는 시기에 따라 Colab에서 TensorFlow의 기본 버전이 곧 TensorFlow 2.X로 전환된다는 경고를 받을 수 있습니다. 이 노트북은 TensorFlow 1.X 및 2.X와 호환되도록 설계되었으므로 이 경고는 무시해도 됩니다.

모듈 가져오기

또한 모델의 성능을 평가하고 시각화하는 데 사용할 공정성 지표와 관련된 몇 가지 가져오기를 추가합니다.

TFCO는 Eager 및 그래프 실행과 호환되지만 이 노트북은 TensorFlow 2.x에서와 같이 기본적으로 Eager 실행이 활성화되어 있다고 가정합니다. 아무 것도 중단되지 않도록 아래 셀에서 즉시 실행이 활성화됩니다.

Eager Execution 및 인쇄 버전 활성화

Eager execution enabled by default.
TensorFlow 2.8.0-rc0
TFMA 0.36.0
TFDS 4.4.0
FI 0.36.0

CelebA 데이터 세트

CelebA는 대규모 얼굴 5 랜드 마크 위치 (눈, 입과 코 위치) (예 : 헤어 스타일, 패션 액세서리, 얼굴의 특징 등) (40) 속성 주석 20 만 개 이상의 유명 인사의 이미지, 각각 데이터 집합을 속성입니다. 자세한 내용을 살펴 가지고 종이를 . 소유자의 허가, 우리는 구글 클라우드 스토리지에이 데이터 집합을 저장 한 주로를 통해 액세스 TensorFlow 데이터 세트 ( tfds ) .

이 노트북에서:

  • 은 "미소"속성 *로 대표되는 우리의 모델은 이미지의 피사체가 웃고 있는지를 분류하려고 시도합니다.
  • 훈련 시 실행 시간과 메모리를 줄이기 위해 이미지 크기가 218x178에서 28x28로 조정됩니다.
  • 우리 모델의 성능은 이진 "젊음" 속성을 사용하여 연령대에 걸쳐 평가됩니다. 이 노트북에서는 이것을 "연령대"라고 부를 것입니다.

*이 데이터 집합에 대한 표시 방법에 대한 가능한 작은 정보가 있지만, 우리는 "미소"속성은 피사체의 얼굴에 만족, 친절하고, 즐겁게 또는 식에 의해 결정되었다고 가정합니다. 이 사례 연구의 목적을 위해 우리는 이러한 레이블을 기본 정보로 사용할 것입니다.

gcs_base_dir = "gs://celeb_a_dataset/"
celeb_a_builder = tfds.builder("celeb_a", data_dir=gcs_base_dir, version='2.0.0')

celeb_a_builder.download_and_prepare()

num_test_shards_dict = {'0.3.0': 4, '2.0.0': 2} # Used because we download the test dataset separately
version = str(celeb_a_builder.info.version)
print('Celeb_A dataset version: %s' % version)
Celeb_A dataset version: 2.0.0

데이터세트 도우미 기능 테스트

주의 사항

계속 진행하기 전에 CelebA를 사용할 때 염두에 두어야 할 몇 가지 고려 사항이 있습니다.

  • 원칙적으로 이 노트북은 얼굴 이미지의 모든 데이터 세트를 사용할 수 있지만 CelebA는 공인의 공개 도메인 이미지를 포함하기 때문에 선택되었습니다.
  • CelebA의 모든 속성 주석은 이진 범주로 운영됩니다. 예를 들어, "젊은" 속성(데이터 세트 레이블러에 의해 결정됨)은 이미지에 존재하거나 없는 것으로 표시됩니다.
  • CelebA의 분류는 속성의 실제 인간 다양성을 반영하지 않습니다.
  • 이 노트북의 목적을 위해 "젊은" 속성을 포함하는 기능을 "연령 그룹"이라고 하며, 여기서 이미지에 "젊은" 속성이 있는 경우 "젊은" 연령 그룹의 구성원으로 레이블이 지정되고 "젊음" 속성이 없으면 "젊지 않음" 연령 그룹의 구성원으로 레이블이 지정됩니다. 이들은이 정보가 언급되지 않는 만들어 가정입니다 원래 종이 .
  • 따라서 이 노트북에서 훈련된 모델의 성능은 CelebA 작성자가 속성을 조작하고 주석을 추가한 방식과 관련이 있습니다.
  • 이 모델은 위반과 상업적인 목적으로 사용할 수 없습니다 CelebA의 비상업적 연구 계약을 .

입력 기능 설정

후속 셀은 입력 파이프라인을 간소화하고 성능을 시각화하는 데 도움이 됩니다.

먼저 일부 데이터 관련 변수를 정의하고 필수 전처리 기능을 정의합니다.

변수 정의

전처리 함수 정의

그런 다음 나머지 colab에 필요한 데이터 기능을 구축합니다.

# Train data returning either 2 or 3 elements (the third element being the group)
def celeb_a_train_data_wo_group(batch_size):
  celeb_a_train_data = celeb_a_builder.as_dataset(split='train').shuffle(1024).repeat().batch(batch_size).map(preprocess_input_dict)
  return celeb_a_train_data.map(get_image_and_label)
def celeb_a_train_data_w_group(batch_size):
  celeb_a_train_data = celeb_a_builder.as_dataset(split='train').shuffle(1024).repeat().batch(batch_size).map(preprocess_input_dict)
  return celeb_a_train_data.map(get_image_label_and_group)

# Test data for the overall evaluation
celeb_a_test_data = celeb_a_builder.as_dataset(split='test').batch(1).map(preprocess_input_dict).map(get_image_label_and_group)
# Copy test data locally to be able to read it into tfma
copy_test_files_to_local()

간단한 DNN 모델 구축

이 노트북이 TFCO에 초점을 맞추고 있기 때문에, 우리는 간단 구속 조립합니다 tf.keras.Sequential 모델.

우리는 약간의 복잡성(예: 더 조밀하게 연결된 레이어, 다른 활성화 기능 탐색, 이미지 크기 증가)을 추가하여 모델 성능을 크게 향상시킬 수 있지만 TFCO 라이브러리를 적용하는 것이 얼마나 쉬운지 보여주는 목표에서 산만해질 수 있습니다. 케라스와 함께 일할 때. 이러한 이유로 모델은 단순하게 유지되지만 이 공간을 탐색하는 것이 좋습니다.

def create_model():
  # For this notebook, accuracy will be used to evaluate performance.
  METRICS = [
    tf.keras.metrics.BinaryAccuracy(name='accuracy')
  ]

  # The model consists of:
  # 1. An input layer that represents the 28x28x3 image flatten.
  # 2. A fully connected layer with 64 units activated by a ReLU function.
  # 3. A single-unit readout layer to output real-scores instead of probabilities.
  model = keras.Sequential([
      keras.layers.Flatten(input_shape=(IMAGE_SIZE, IMAGE_SIZE, 3), name='image'),
      keras.layers.Dense(64, activation='relu'),
      keras.layers.Dense(1, activation=None)
  ])

  # TFCO by default uses hinge loss — and that will also be used in the model.
  model.compile(
      optimizer=tf.keras.optimizers.Adam(0.001),
      loss='hinge',
      metrics=METRICS)
  return model

또한 재현 가능한 결과를 보장하기 위해 시드를 설정하는 함수를 정의합니다. 이 colab은 교육용 도구이며 미세 조정된 프로덕션 파이프라인의 안정성이 없습니다. 시드를 설정하지 않고 실행하면 다양한 결과가 나타날 수 있습니다.

def set_seeds():
  np.random.seed(121212)
  tf.compat.v1.set_random_seed(212121)

공정성 지표 도우미 함수

모델을 훈련하기 전에 공정성 지표를 통해 모델의 성능을 평가할 수 있는 여러 도우미 함수를 정의합니다.

먼저 모델을 훈련시킨 후 저장하는 도우미 함수를 만듭니다.

def save_model(model, subdir):
  base_dir = tempfile.mkdtemp(prefix='saved_models')
  model_location = os.path.join(base_dir, subdir)
  model.save(model_location, save_format='tf')
  return model_location

다음으로 데이터를 TFMA에 올바르게 전달하기 위해 데이터를 사전 처리하는 데 사용되는 함수를 정의합니다.

데이터 전처리 기능

마지막으로 TFMA에서 결과를 평가하는 함수를 정의합니다.

def get_eval_results(model_location, eval_subdir):
  base_dir = tempfile.mkdtemp(prefix='saved_eval_results')
  tfma_eval_result_path = os.path.join(base_dir, eval_subdir)

  eval_config_pbtxt = """
        model_specs {
          label_key: "%s"
        }
        metrics_specs {
          metrics {
            class_name: "FairnessIndicators"
            config: '{ "thresholds": [0.22, 0.5, 0.75] }'
          }
          metrics {
            class_name: "ExampleCount"
          }
        }
        slicing_specs {}
        slicing_specs { feature_keys: "%s" }
        options {
          compute_confidence_intervals { value: False }
          disabled_outputs{values: "analysis"}
        }
      """ % (LABEL_KEY, GROUP_KEY)

  eval_config = text_format.Parse(eval_config_pbtxt, tfma.EvalConfig())

  eval_shared_model = tfma.default_eval_shared_model(
        eval_saved_model_path=model_location, tags=[tf.saved_model.SERVING])

  schema_pbtxt = """
        tensor_representation_group {
          key: ""
          value {
            tensor_representation {
              key: "%s"
              value {
                dense_tensor {
                  column_name: "%s"
                  shape {
                    dim { size: 28 }
                    dim { size: 28 }
                    dim { size: 3 }
                  }
                }
              }
            }
          }
        }
        feature {
          name: "%s"
          type: FLOAT
        }
        feature {
          name: "%s"
          type: FLOAT
        }
        feature {
          name: "%s"
          type: BYTES
        }
        """ % (IMAGE_KEY, IMAGE_KEY, IMAGE_KEY, LABEL_KEY, GROUP_KEY)
  schema = text_format.Parse(schema_pbtxt, schema_pb2.Schema())
  coder = tf_example_record.TFExampleBeamRecord(
      physical_format='inmem', schema=schema,
      raw_record_column_name=tfma.ARROW_INPUT_COLUMN)
  tensor_adapter_config = tensor_adapter.TensorAdapterConfig(
    arrow_schema=coder.ArrowSchema(),
    tensor_representations=coder.TensorRepresentations())
  # Run the fairness evaluation.
  with beam.Pipeline() as pipeline:
    _ = (
          tfds_as_pcollection(pipeline, 'celeb_a', 'test')
          | 'ExamplesToRecordBatch' >> coder.BeamSource()
          | 'ExtractEvaluateAndWriteResults' >>
          tfma.ExtractEvaluateAndWriteResults(
              eval_config=eval_config,
              eval_shared_model=eval_shared_model,
              output_path=tfma_eval_result_path,
              tensor_adapter_config=tensor_adapter_config)
    )
  return tfma.load_eval_result(output_path=tfma_eval_result_path)

제약 없는 모델 훈련 및 평가

이제 모델이 정의되고 입력 파이프라인이 준비되었으므로 이제 모델을 훈련할 준비가 되었습니다. 실행 시간과 메모리 양을 줄이기 위해 몇 번만 반복하여 데이터를 작은 배치로 슬라이싱하여 모델을 훈련할 것입니다.

TensorFlow에서이 노트북 <2.0.0을 실행하는 것은 더 이상 사용되지 경고가 발생할 수 있습니다 np.where . TensorFlow를 사용하여 2.X에서이 주소로 안전하게이 경고를 무시 tf.where 대신 np.where .

BATCH_SIZE = 32

# Set seeds to get reproducible results
set_seeds()

model_unconstrained = create_model()
model_unconstrained.fit(celeb_a_train_data_wo_group(BATCH_SIZE), epochs=5, steps_per_epoch=1000)
Epoch 1/5
1000/1000 [==============================] - 12s 6ms/step - loss: 0.5038 - accuracy: 0.7733
Epoch 2/5
1000/1000 [==============================] - 7s 7ms/step - loss: 0.3800 - accuracy: 0.8301
Epoch 3/5
1000/1000 [==============================] - 6s 6ms/step - loss: 0.3598 - accuracy: 0.8427
Epoch 4/5
1000/1000 [==============================] - 25s 25ms/step - loss: 0.3435 - accuracy: 0.8474
Epoch 5/5
1000/1000 [==============================] - 5s 5ms/step - loss: 0.3402 - accuracy: 0.8479
<keras.callbacks.History at 0x7f0f5c476350>

테스트 데이터에서 모델을 평가하면 최종 정확도 점수가 85%가 조금 넘습니다. 미세 조정이 없는 단순한 모델 치고는 나쁘지 않습니다.

print('Overall Results, Unconstrained')
celeb_a_test_data = celeb_a_builder.as_dataset(split='test').batch(1).map(preprocess_input_dict).map(get_image_label_and_group)
results = model_unconstrained.evaluate(celeb_a_test_data)
Overall Results, Unconstrained
19962/19962 [==============================] - 50s 2ms/step - loss: 0.2125 - accuracy: 0.8636

그러나 연령 그룹에 걸쳐 평가된 성과는 몇 가지 단점을 드러낼 수 있습니다.

이를 더 탐구하기 위해 공정성 지표(TFMA를 통해)로 모델을 평가합니다. 특히 가양성 비율로 평가했을 때 '젊은' 카테고리와 '젊지 않은' 카테고리 사이에 상당한 성능 차이가 있는지 여부에 관심이 쏠린다.

모델이 포지티브 클래스를 잘못 예측하면 가양성 오류가 발생합니다. 이런 맥락에서, ground truth가 연예인의 '미소짓지 않음' 이미지이고 모델이 '미소짓기'를 예측할 때 위양성 결과가 발생합니다. 확장하여 위의 시각화에 사용된 위양성 비율은 테스트의 정확도를 측정한 것입니다. 이것은 이 맥락에서 저지르는 비교적 평범한 오류이지만, 가양성 오류는 때때로 더 문제가 되는 동작을 유발할 수 있습니다. 예를 들어 스팸 분류기의 오탐지 오류로 인해 사용자가 중요한 이메일을 놓칠 수 있습니다.

model_location = save_model(model_unconstrained, 'model_export_unconstrained')
eval_results_unconstrained = get_eval_results(model_location, 'eval_results_unconstrained')
2022-01-07 18:46:05.881112: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: /tmp/saved_modelswhxcqdry/model_export_unconstrained/assets
INFO:tensorflow:Assets written to: /tmp/saved_modelswhxcqdry/model_export_unconstrained/assets
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:root:Make sure that locally built Python SDK docker image has Python 3.7 interpreter.
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:107: 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:107: 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)`

위에서 언급했듯이 우리는 위양성 비율에 집중하고 있습니다. 공정성 지표(0.1.2)의 현재 버전은 기본적으로 위음성 비율을 선택합니다. 아래 줄을 실행한 후 false_negative_rate를 선택 취소하고 false_positive_rate를 선택하여 관심 있는 메트릭을 확인합니다.

tfma.addons.fairness.view.widget_view.render_fairness_indicator(eval_results_unconstrained)
FairnessIndicatorViewer(slicingMetrics=[{'sliceValue': 'Young', 'slice': 'Young:Young', 'metrics': {'example_c…

결과는 위의 표시로서, 우리는 "영"과 "하지 젊은"범주 사이의 불균형 격차를 볼 수 없습니다.

여기서 TFCO는 위양성 비율을 허용 가능한 기준 내로 제한함으로써 도움을 줄 수 있습니다.

구속된 모델 설정

에 설명 된대로 TFCO 도서관 , 쉽게 문제를 제한 할 수 있도록하는 몇 가지 헬퍼가있다 :

  1. tfco.rate_context() - 이는 각 연령 집단 범주에 대한 제약 조건을 구성하는데 사용되는 것입니다.
  2. tfco.RateMinimizationProblem() - 속도 발현은 연령 그룹에 위양성률의 대상이 될 것입니다 여기 최소화 할 수 있습니다. 즉, 이제 연령 그룹과 전체 데이터 세트의 위양성 비율의 차이를 기반으로 성능이 평가됩니다. 이 데모에서는 5% 이하의 거짓 긍정 비율이 제약 조건으로 설정됩니다.
  3. tfco.ProxyLagrangianOptimizerV2() - 이것은 실제로 속도 제한 문제를 해결할 도우미입니다.

아래 셀은 공정성 제약 조건으로 모델 훈련을 설정하기 위해 이러한 도우미를 호출합니다.

# The batch size is needed to create the input, labels and group tensors.
# These tensors are initialized with all 0's. They will eventually be assigned
# the batch content to them. A large batch size is chosen so that there are
# enough number of "Young" and "Not Young" examples in each batch.
set_seeds()
model_constrained = create_model()
BATCH_SIZE = 32

# Create input tensor.
input_tensor = tf.Variable(
    np.zeros((BATCH_SIZE, IMAGE_SIZE, IMAGE_SIZE, 3), dtype="float32"),
    name="input")

# Create labels and group tensors (assuming both labels and groups are binary).
labels_tensor = tf.Variable(
    np.zeros(BATCH_SIZE, dtype="float32"), name="labels")
groups_tensor = tf.Variable(
    np.zeros(BATCH_SIZE, dtype="float32"), name="groups")

# Create a function that returns the applied 'model' to the input tensor
# and generates constrained predictions.
def predictions():
  return model_constrained(input_tensor)

# Create overall context and subsetted context.
# The subsetted context contains subset of examples where group attribute < 1
# (i.e. the subset of "Not Young" celebrity images).
# "groups_tensor < 1" is used instead of "groups_tensor == 0" as the former
# would be a comparison on the tensor value, while the latter would be a
# comparison on the Tensor object.
context = tfco.rate_context(predictions, labels=lambda:labels_tensor)
context_subset = context.subset(lambda:groups_tensor < 1)

# Setup list of constraints.
# In this notebook, the constraint will just be: FPR to less or equal to 5%.
constraints = [tfco.false_positive_rate(context_subset) <= 0.05]

# Setup rate minimization problem: minimize overall error rate s.t. constraints.
problem = tfco.RateMinimizationProblem(tfco.error_rate(context), constraints)

# Create constrained optimizer and obtain train_op.
# Separate optimizers are specified for the objective and constraints
optimizer = tfco.ProxyLagrangianOptimizerV2(
      optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
      constraint_optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
      num_constraints=problem.num_constraints)

# A list of all trainable variables is also needed to use TFCO.
var_list = (model_constrained.trainable_weights + list(problem.trainable_variables) +
            optimizer.trainable_variables())

이제 모델이 설정되었으며 연령 그룹 전반에 걸쳐 위양성 비율 제약 조건으로 학습할 준비가 되었습니다.

구속 된 모델의 마지막 반복이 반드시 정의 된 제약 조건의 측면에서 실적이 가장 좋은 모델이 될 않을 수 있기 때문에 지금의 TFCO 라이브러리가 장착되어 tfco.find_best_candidate_index() 캔 도움이 사람의 반복 처리를 최고의 밖으로 선택하는 것이 각 후 발견 시대. 생각 tfco.find_best_candidate_index() 별도로 학습 데이터에 대한 정확성과 공평성 제약 (연령층에 걸쳐이 경우 위양성율) 결과에 기초하여 각각의 순위를 추가 휴리스틱있다. 그렇게 하면 전체 정확도와 공정성 제약 사이에서 더 나은 균형을 찾을 수 있습니다.

다음 셀은 반복당 최고의 성능 모델을 찾는 동시에 제약 조건으로 훈련을 시작합니다.

# Obtain train set batches.

NUM_ITERATIONS = 100  # Number of training iterations.
SKIP_ITERATIONS = 10  # Print training stats once in this many iterations.

# Create temp directory for saving snapshots of models.
temp_directory = tempfile.mktemp()
os.mkdir(temp_directory)

# List of objective and constraints across iterations.
objective_list = []
violations_list = []

# Training iterations.
iteration_count = 0
for (image, label, group) in celeb_a_train_data_w_group(BATCH_SIZE):
  # Assign current batch to input, labels and groups tensors.
  input_tensor.assign(image)
  labels_tensor.assign(label)
  groups_tensor.assign(group)

  # Run gradient update.
  optimizer.minimize(problem, var_list=var_list)

  # Record objective and violations.
  objective = problem.objective()
  violations = problem.constraints()

  sys.stdout.write(
      "\r Iteration %d: Hinge Loss = %.3f, Max. Constraint Violation = %.3f"
      % (iteration_count + 1, objective, max(violations)))

  # Snapshot model once in SKIP_ITERATIONS iterations.
  if iteration_count % SKIP_ITERATIONS == 0:
    objective_list.append(objective)
    violations_list.append(violations)

    # Save snapshot of model weights.
    model_constrained.save_weights(
        temp_directory + "/celeb_a_constrained_" +
        str(iteration_count / SKIP_ITERATIONS) + ".h5")

  iteration_count += 1
  if iteration_count >= NUM_ITERATIONS:
    break

# Choose best model from recorded iterates and load that model.
best_index = tfco.find_best_candidate_index(
    np.array(objective_list), np.array(violations_list))

model_constrained.load_weights(
    temp_directory + "/celeb_a_constrained_" + str(best_index) + ".0.h5")

# Remove temp directory.
os.system("rm -r " + temp_directory)
Iteration 100: Hinge Loss = 0.614, Max. Constraint Violation = 0.268
0

제약 조건을 적용한 후 공정성 지표를 사용하여 다시 한 번 결과를 평가합니다.

model_location = save_model(model_constrained, 'model_export_constrained')
eval_result_constrained = get_eval_results(model_location, 'eval_results_constrained')
INFO:tensorflow:Assets written to: /tmp/saved_modelsbztxt9fy/model_export_constrained/assets
INFO:tensorflow:Assets written to: /tmp/saved_modelsbztxt9fy/model_export_constrained/assets
WARNING:root:Make sure that locally built Python SDK docker image has Python 3.7 interpreter.

공정성 지표를 사용한 이전 시간과 마찬가지로 false_negative_rate를 선택 취소하고 false_positive_rate를 선택하여 관심 있는 메트릭을 확인합니다.

우리 모델의 두 버전을 공정하게 비교하려면 전체 오탐지율을 대략 동일하게 설정하는 임계값을 사용하는 것이 중요합니다. 이렇게 하면 단순히 임계값 경계를 이동하는 것과 동일한 모델의 이동이 아닌 실제 변경을 볼 수 있습니다. 우리의 경우 0.5에서 제약이 없는 모델과 0.22에서 제약이 있는 모델을 비교하면 모델을 공정하게 비교할 수 있습니다.

eval_results_dict = {
    'constrained': eval_result_constrained,
    'unconstrained': eval_results_unconstrained,
}
tfma.addons.fairness.view.widget_view.render_fairness_indicator(multi_eval_results=eval_results_dict)
FairnessIndicatorViewer(evalName='constrained', evalNameCompare='unconstrained', slicingMetrics=[{'sliceValue'…

더 복잡한 요구 사항을 속도 제약으로 표현할 수 있는 TFCO의 능력을 통해 우리는 이 모델이 전체 성능에 거의 영향을 미치지 않으면서 보다 바람직한 결과를 얻을 수 있도록 도왔습니다. 물론 아직 개선의 여지가 있지만 최소한 TFCO는 제약 조건을 충족하고 그룹 간의 격차를 최대한 줄이는 모델을 찾을 수 있었습니다.