#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Explanation: Copyright 2021 The TensorFlow Authors.
End of explanation
"""


# Upgrade pip to the latest, and install TFMA.
!pip install -U pip
!pip install tensorflow-model-analysis

"""
Explanation: 참고: 이 예제는 Jupyter 스타일 노트북에서 바로 실행할 수 있으며 설정이 필요하지 않습니다. "Google Colab에서 실행"을 클릭하세요.
<div class="devsite-table-wrapper"><table class="tfo-notebook-buttons" align="left">
<td>     <a target="_blank" href="https://www.tensorflow.org/tfx/tutorials/model_analysis/tfma_basic"><img src="https://www.tensorflow.org/images/tf_logo_32px.png">TensorFlow.org에서 보기</a>
</td>
<td>     <a target="_blank" href="https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ko/tfx/tutorials/model_analysis/tfma_basic.ipynb"><img src="https://www.tensorflow.org/images/colab_logo_32px.png">Google Colab에서 실행</a>
</td>
<td><a target="_blank" href="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/tfx/tutorials/model_analysis/tfma_basic.ipynb"><img width="32px" src="https://www.tensorflow.org/images/GitHub-Mark-32px.png">GitHub에서 소스 보기</a></td>
<td><a target="_blank" href="https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ko/tfx/tutorials/model_analysis/tfma_basic.ipynb"> <img width="32px" src="https://www.tensorflow.org/images/download_logo_32px.png">노트북 다운로드</a></td>
</table></div>

TensorFlow 모델 분석
TensorFlow Extended(TFX)의 주요 구성 요소 예
TensorFlow Model Analysis(TFMA)는 다양한 데이터 조각에서 모델 평가를 수행하기 위한 라이브러리입니다. TFMA는 Apache Beam을 사용하여 대량의 데이터에 대해 분산된 방식으로 계산을 수행합니다.
이 예제 colab 노트북은 TFMA를 사용하여 데이터세트의 특성과 관련하여 모델의 성능을 조사하고 시각화하는 방법을 보여줍니다. 이전에 훈련한 모델을 사용하고 이제 결과를 만져볼 수 있습니다! 학습한 모델은 Chicago Taxi 예제를 위한 것이었고, 이를 위해 시카고 시에서 공개한 Taxi Trips 데이터세트가 사용됩니다. BigQuery UI에서 전체 데이터세트를 살펴보세요.
모델러 및 개발자로서 이 데이터가 어떻게 사용되는지, 그리고 모델의 예측이 초래할 수 있는 잠재적인 이점과 피해에 대해 생각해보세요. 이와 같은 모델은 사회적 편견과 불균형을 강화시킬 수 있습니다. 기능이 해결하려는 문제와 관련이 있습니까? 아니면 편견을 유발합니까? 자세한 내용은 <a target="_blank" href="https://developers.google.com/machine-learning/fairness-overview/">ML 공정성</a>에 대해 읽어보세요.
참고: TFMA 및 TFMA가 Apache Beam에서 작동하는 방식을 이해하려면 Apache Beam 자체에 대해 조금은 알아야 합니다. <a target="_blank" href="https://beam.apache.org/documentation/programming-guide/">Beam 프로그래밍 가이드</a>는 이를 위한 좋은 출발점입니다.
데이터세트의 열은 다음과 같습니다.
<table>
<tr>
<td>pickup_community_area</td>
<td>fare</td>
<td>trip_start_month</td>
</tr>
<tr>
<td>trip_start_hour</td>
<td>trip_start_day</td>
<td>trip_start_timestamp</td>
</tr>
<tr>
<td>pickup_latitude</td>
<td>pickup_longitude</td>
<td>dropoff_latitude</td>
</tr>
<tr>
<td>dropoff_longitude</td>
<td>trip_miles</td>
<td>pickup_census_tract</td>
</tr>
<tr>
<td>dropoff_census_tract</td>
<td>payment_type</td>
<td>company</td>
</tr>
<tr>
<td>trip_seconds</td>
<td>dropoff_community_area</td>
<td>tips</td>
</tr>
</table>

Jupyter 확장 프로그램 설치하기
참고: 로컬 Jupyter 노트북에서 실행 중인 경우 Jupyter를 실행하기 전에 이러한 Jupyter 확장 프로그램을 환경에 설치해야 합니다.
bash
jupyter nbextension enable --py widgetsnbextension --sys-prefix
jupyter nbextension install --py --symlink tensorflow_model_analysis --sys-prefix
jupyter nbextension enable --py tensorflow_model_analysis --sys-prefix
TensorFlow Model Analysis(TFMA) 설치하기
이것은 모든 종속성을 가져오고 1분 정도 걸립니다.
End of explanation
"""


# This setup was tested with TF 2.5 and TFMA 0.31 (using colab), but it should
# also work with the latest release.
import sys

# Confirm that we're using Python 3
assert sys.version_info.major==3, 'This notebook must be run using Python 3.'

import tensorflow as tf
print('TF version: {}'.format(tf.__version__))
import apache_beam as beam
print('Beam version: {}'.format(beam.__version__))
import tensorflow_model_analysis as tfma
print('TFMA version: {}'.format(tfma.__version__))

"""
Explanation: 이제 아래 셀을 실행하기 전에 런타임을 다시 시작해야 합니다.
End of explanation
"""


# Download the tar file from GCP and extract it
import io, os, tempfile
TAR_NAME = 'saved_models-2.2'
BASE_DIR = tempfile.mkdtemp()
DATA_DIR = os.path.join(BASE_DIR, TAR_NAME, 'data')
MODELS_DIR = os.path.join(BASE_DIR, TAR_NAME, 'models')
SCHEMA = os.path.join(BASE_DIR, TAR_NAME, 'schema.pbtxt')
OUTPUT_DIR = os.path.join(BASE_DIR, 'output')

!curl -O https://storage.googleapis.com/artifacts.tfx-oss-public.appspot.com/datasets/{TAR_NAME}.tar
!tar xf {TAR_NAME}.tar
!mv {TAR_NAME} {BASE_DIR}
!rm {TAR_NAME}.tar

print("Here's what we downloaded:")
!ls -R {BASE_DIR}

"""
Explanation: 참고: 계속하기 전에 위의 출력에 오류가 없어야 합니다. 여전히 오류가 보이면 설치를 다시 실행하세요. 또한 다음 단계로 이동하기 전에 런타임/커널을 다시 시작해야 합니다.
파일 로드하기
필요한 모든 것이 포함된 tar 파일을 다운로드합니다. 여기에는 다음이 포함됩니다.

훈련 및 평가 데이터세트
데이터 스키마
저장된 모델(keras 및 estimator) 및 eval 저장된 모델(estimator) 훈련 및 제공
End of explanation
"""


import tensorflow as tf
from google.protobuf import text_format
from tensorflow.python.lib.io import file_io
from tensorflow_metadata.proto.v0 import schema_pb2
from tensorflow.core.example import example_pb2

schema = schema_pb2.Schema()
contents = file_io.read_file_to_string(SCHEMA)
schema = text_format.Parse(contents, schema)

"""
Explanation: 스키마 구문 분석하기
다운로드한 항목 중에는 TensorFlow Data Validation에서 생성한 데이터 스키마가 있습니다. 이제 TFMA와 함께 사용할 수 있도록 이 스키마 구문을 분석해 보겠습니다.
End of explanation
"""


import csv

datafile = os.path.join(DATA_DIR, 'eval', 'data.csv')
reader = csv.DictReader(open(datafile, 'r'))
examples = []
for line in reader:
  example = example_pb2.Example()
  for feature in schema.feature:
    key = feature.name
    if feature.type == schema_pb2.FLOAT:
      example.features.feature[key].float_list.value[:] = (
          [float(line[key])] if len(line[key]) > 0 else [])
    elif feature.type == schema_pb2.INT:
      example.features.feature[key].int64_list.value[:] = (
          [int(line[key])] if len(line[key]) > 0 else [])
    elif feature.type == schema_pb2.BYTES:
      example.features.feature[key].bytes_list.value[:] = (
          [line[key].encode('utf8')] if len(line[key]) > 0 else [])
  # Add a new column 'big_tipper' that indicates if tips was > 20% of the fare. 
  # TODO(b/157064428): Remove after label transformation is supported for Keras.
  big_tipper = float(line['tips']) > float(line['fare']) * 0.2
  example.features.feature['big_tipper'].float_list.value[:] = [big_tipper]
  examples.append(example)

tfrecord_file = os.path.join(BASE_DIR, 'train_data.rio')
with tf.io.TFRecordWriter(tfrecord_file) as writer:
  for example in examples:
    writer.write(example.SerializeToString())

!ls {tfrecord_file}

"""
Explanation: 스키마를 사용하여 TFRecord 생성하기
TFMA에 데이터세트에 대한 액세스 권한을 부여해야 하므로 TFRecords 파일을 생성하겠습니다. 스키마를 사용하여 이 파일을 생성할 수 있는데, 각 특성에 대한 올바른 유형을 제공하기 때문입니다.
End of explanation
"""


import tensorflow_model_analysis as tfma

# Setup tfma.EvalConfig settings
keras_eval_config = text_format.Parse("""
  ## Model information
  model_specs {
    # For keras (and serving models) we need to add a `label_key`.
    label_key: "big_tipper"
  }

  ## Post training metric information. These will be merged with any built-in
  ## metrics from training.
  metrics_specs {
    metrics { class_name: "ExampleCount" }
    metrics { class_name: "BinaryAccuracy" }
    metrics { class_name: "BinaryCrossentropy" }
    metrics { class_name: "AUC" }
    metrics { class_name: "AUCPrecisionRecall" }
    metrics { class_name: "Precision" }
    metrics { class_name: "Recall" }
    metrics { class_name: "MeanLabel" }
    metrics { class_name: "MeanPrediction" }
    metrics { class_name: "Calibration" }
    metrics { class_name: "CalibrationPlot" }
    metrics { class_name: "ConfusionMatrixPlot" }
    # ... add additional metrics and plots ...
  }

  ## Slicing information
  slicing_specs {}  # overall slice
  slicing_specs {
    feature_keys: ["trip_start_hour"]
  }
  slicing_specs {
    feature_keys: ["trip_start_day"]
  }
  slicing_specs {
    feature_values: {
      key: "trip_start_month"
      value: "1"
    }
  }
  slicing_specs {
    feature_keys: ["trip_start_hour", "trip_start_day"]
  }
""", tfma.EvalConfig())

# Create a tfma.EvalSharedModel that points at our keras model.
keras_model_path = os.path.join(MODELS_DIR, 'keras', '2')
keras_eval_shared_model = tfma.default_eval_shared_model(
    eval_saved_model_path=keras_model_path,
    eval_config=keras_eval_config)

keras_output_path = os.path.join(OUTPUT_DIR, 'keras')

# Run TFMA
keras_eval_result = tfma.run_model_analysis(
    eval_shared_model=keras_eval_shared_model,
    eval_config=keras_eval_config,
    data_location=tfrecord_file,
    output_path=keras_output_path)

"""
Explanation: TFMA 설정 및 실행하기
TFMA는 TF keras 모델, 일반 TF2 서명 API 기반 모델, TF estimator 기반 모델을 비롯한 다양한 모델 유형을 지원합니다. get_started 가이드에 지원되는 모델 유형의 전체 목록과 제한 사항이 나와 있습니다. 이 예제에서는 EvalSavedModel로 저장된 estimator 기반 모델뿐만 아니라 keras 기반 모델을 구성하는 방법을 보여줄 것입니다. 다른 구성 예는 FAQ를 참조하세요.
TFMA는 훈련 시간에 사용된 메트릭(예: 내장 메트릭)뿐만 아니라 모델이 TFMA 구성 설정의 일부로 저장된 후 정의된 메트릭의 계산도 지원합니다. keras 설정의 경우, 구성의 일부로 메트릭 및 플롯을 수동으로 추가하는 방법을 보여줄 것입니다(지원되는 메트릭 및 플롯에 대한 정보는 메트릭 가이드 참조). Estimator 설정을 위해 모델과 함께 저장된 내장 메트릭을 사용합니다. 또한 설정에는 다음 섹션에서 자세히 설명하는 여러 슬라이싱 사양도 포함되어 있습니다.
tfma.EvalConfig 및 tfma.EvalSharedModel을 만든 후, tfma.run_model_analysis를 사용하여 TFMA를 실행할 수 있습니다. 그러면 나중에 메트릭과 플롯을 렌더링하는 데 사용할 수 있는 tfma.EvalResult가 생성됩니다.
Keras
End of explanation
"""


import tensorflow_model_analysis as tfma

# Setup tfma.EvalConfig settings
estimator_eval_config = text_format.Parse("""
  ## Model information
  model_specs {
    # To use EvalSavedModel set `signature_name` to "eval".
    signature_name: "eval"
  }

  ## Post training metric information. These will be merged with any built-in
  ## metrics from training.
  metrics_specs {
    metrics { class_name: "ConfusionMatrixPlot" }
    # ... add additional metrics and plots ...
  }

  ## Slicing information
  slicing_specs {}  # overall slice
  slicing_specs {
    feature_keys: ["trip_start_hour"]
  }
  slicing_specs {
    feature_keys: ["trip_start_day"]
  }
  slicing_specs {
    feature_values: {
      key: "trip_start_month"
      value: "1"
    }
  }
  slicing_specs {
    feature_keys: ["trip_start_hour", "trip_start_day"]
  }
""", tfma.EvalConfig())

# Create a tfma.EvalSharedModel that points at our eval saved model.
estimator_base_model_path = os.path.join(
    MODELS_DIR, 'estimator', 'eval_model_dir')
estimator_model_path = os.path.join(
    estimator_base_model_path, os.listdir(estimator_base_model_path)[0])
estimator_eval_shared_model = tfma.default_eval_shared_model(
    eval_saved_model_path=estimator_model_path,
    eval_config=estimator_eval_config)

estimator_output_path = os.path.join(OUTPUT_DIR, 'estimator')

# Run TFMA
estimator_eval_result = tfma.run_model_analysis(
    eval_shared_model=estimator_eval_shared_model,
    eval_config=estimator_eval_config,
    data_location=tfrecord_file,
    output_path=estimator_output_path)

"""
Explanation: Estimator
End of explanation
"""


eval_result = keras_eval_result
# eval_result = estimator_eval_result

"""
Explanation: 메트릭 및 플롯 시각화하기
이제 평가를 실행했으므로 TFMA를 사용하여 시각화를 살펴보겠습니다. 다음 예제에서는 keras 모델에서 평가를 실행한 결과를 시각화합니다. Estimator 기반 모델을 보려면 estimator_eval_result 변수를 가리키도록 eval_result를 업데이트합니다.
End of explanation
"""


tfma.view.render_slicing_metrics(eval_result, slicing_column='trip_start_hour')

"""
Explanation: 메트릭 렌더링하기
메트릭을 보려면 tfma.view.render_slicing_metrics를 사용합니다.
기본적으로, 보기는 Overall 조각을 표시합니다. 특정 조각을 보려면 열 이름을 사용하거나(slicing_column을 설정하여) tfma.SlicingSpec를 제공할 수 있습니다.
메트릭 시각화는 다음 상호 작용을 지원합니다.

클릭하고 끌어서 이동
스크롤하여 확대/축소
마우스 오른쪽 버튼을 클릭하여 보기 재설정
원하는 데이터 포인트 위로 마우스를 가져가 자세한 정보 표시
하단의 선택 항목을 사용하여 네 가지 유형의 보기 중에서 선택

예를 들어, 이전 slicing_specs의 trip_start_hour 특성을 살펴보도록 slicing_column을 설정합니다.
End of explanation
"""


tfma.view.render_slicing_metrics(eval_result, slicing_column='trip_start_day')

"""
Explanation: 조각 개요
기본 시각화는 조각 수가 적을 때 조각 개요이며, 각 조각에 대한 메트릭 값을 보여줍니다. 위에서 trip_start_hour를 선택했기 때문에 각 시간에 대한 정확도 및 AUC와 같은 메트릭을 보여주며, 이를 통해 다른 시간이 아닌 특정 시간에 관련된 문제를 찾을 수 있습니다.
위의 시각화에서:

열 머리글을 클릭하여 trip_start_hours 특성인 특성 열을 정렬해봅니다.
정밀도를 기준으로 정렬해보고 예제에서 일부 시간의 정밀도가 0인 것에 주목하세요. 이것은 문제를 나타낼 수 있습니다.

차트를 사용하여 조각에서 여러 메트릭을 선택하고 표시할 수도 있습니다.

"표시" 메뉴에서 여러 메트릭을 선택해봅니다.
"표시" 메뉴에서 리콜을 선택해봅니다. 예제에서 일부 시간에 대한 리콜이 0인 것에 주목하세요. 이것은 문제를 나타낼 수 있습니다.

더 적은 수의 예제 또는 "가중치"를 사용하여 조각을 필터링하도록 임계값을 설정할 수도 있습니다. 최소한의 예를 입력하거나 조각을 사용할 수 있습니다.
메트릭 히스토그램
이 보기는 또한 조각 수가 많을 때 기본 보기인 대체 시각화로 메트릭 히스토그램을 지원합니다. 결과는 버킷으로 나뉘며 조각 수/총 가중치/둘 모두를 시각화할 수 있습니다. 열 머리글을 클릭하여 열을 정렬할 수 있습니다. 가중치가 작은 조각은 임계값을 설정하여 필터링할 수 있습니다. 회색 밴드를 끌어서 추가 필터링을 적용할 수 있습니다. 범위를 재설정하려면 밴드를 두 번 클릭합니다. 필터링을 사용하여 시각화 및 메트릭 테이블에서 이상 값을 제거할 수도 있습니다. 기어 아이콘을 클릭하여 선형 스케일 대신 로그 스케일로 전환합니다.

시각화 메뉴에서 "메트릭 히스토그램"을 선택해봅니다.

더 많은 조각
처음의 tfma.EvalConfig는 slicing_specs의 전체 목록을 생성했으며 tfma.view.render_slicing_metrics로 전달된 조각 정보를 업데이트하여 이를 시각화할 수 있습니다. 여기에서는 trip_start_day 조각(요일)을 선택합니다. <strong data-md-type="double_emphasis">trip_start_day를 <code data-md-type="codespan">trip_start_month</code>로 변경하고 다시 렌더링하여 다른 조각을 살펴봅니다.</strong>
End of explanation
"""


tfma.view.render_slicing_metrics(
    eval_result,
    slicing_spec=tfma.SlicingSpec(
        feature_keys=['trip_start_hour', 'trip_start_day']))

"""
Explanation: TFMA는 또한 특성의 조합을 분석하기 위한 특성 교차 생성도 지원합니다. 원래 설정에서는 교차 trip_start_hour 및 trip_start_day를 생성했습니다.
End of explanation
"""


tfma.view.render_slicing_metrics(
    eval_result,
    slicing_spec=tfma.SlicingSpec(
        feature_keys=['trip_start_day'], feature_values={'trip_start_hour': '12'}))

"""
Explanation: 두 열을 교차하면 많은 조합이 생성됩니다! 정오에 시작하는 이동만 살펴보도록 교차를 좁혀 보겠습니다. 그런 다음 시각화에서 binary_accuracy를 선택합니다.
End of explanation
"""


tfma.view.render_plot(
    eval_result,
    tfma.SlicingSpec(feature_values={'trip_start_hour': '1'}))

"""
Explanation: 플롯 렌더링하기
사후 훈련 metric_specs로 tfma.EvalConfig에 추가된 플롯은 tfma.view.render_plot을 사용하여 표시할 수 있습니다.
메트릭과 마찬가지로 플롯을 조각별로 볼 수 있습니다. 메트릭과 달리 특정 조각 값에 대한 플롯만 표시할 수 있으므로 tfma.SlicingSpec을 사용해야 하며 조각 특성 이름과 값을 모두 지정해야 합니다. 조각이 제공되지 않으면 Overall 조각에 대한 플롯이 사용됩니다.
아래 예에서는 trip_start_hour:1 조각에 대해 계산된 CalibrationPlot 및 ConfusionMatrixPlot 플롯을 표시합니다.
End of explanation
"""


# Note this re-uses the EvalConfig from the keras setup.

# Run eval on each saved model
output_paths = []
for i in range(3):
  # Create a tfma.EvalSharedModel that points at our saved model.
  eval_shared_model = tfma.default_eval_shared_model(
      eval_saved_model_path=os.path.join(MODELS_DIR, 'keras', str(i)),
      eval_config=keras_eval_config)

  output_path = os.path.join(OUTPUT_DIR, 'time_series', str(i))
  output_paths.append(output_path)

  # Run TFMA
  tfma.run_model_analysis(eval_shared_model=eval_shared_model,
                          eval_config=keras_eval_config,
                          data_location=tfrecord_file,
                          output_path=output_path)

"""
Explanation: 시간 경과에 따른 모델 성능 추적하기
훈련 데이터세트는 모델 훈련에 사용되며, 바라건데 테스트 데이터세트와 프로덕션에서 모델로 전송될 데이터를 대표할 것입니다. 그러나 추론 요청의 데이터는 훈련 데이터와 동일하게 유지될 수 있지만 많은 경우 모델의 성능이 변경될 정도로 충분히 변하기 시작합니다.
즉, 변화를 인식하고 이에 대응할 수 있도록 지속적으로 모델의 성능을 모니터링하고 측정해야 합니다. TFMA가 어떤 도움을 주는지 살펴보겠습니다.
3개의 다른 모델 실행을 로드하고 TFMA를 사용하여 render_time_series에서 어떻게 비교되는지 살펴보겠습니다.
End of explanation
"""


eval_results_from_disk = tfma.load_eval_results(output_paths[:2])

tfma.view.render_time_series(eval_results_from_disk)

"""
Explanation: 먼저, 어제 모델을 훈련하고 배포했다고 가정하고 이제는 오늘 들어오는 새 데이터에 대해 모델이 어떻게 작동하는지 보려고 합니다. 시각화는 AUC를 표시하는 것으로 시작됩니다. UI에서 다음을 수행할 수 있습니다.

"메트릭 시리즈 추가" 메뉴를 사용하여 다른 메트릭을 추가합니다.
x를 클릭하여 원하지 않는 그래프를 닫습니다.
자세한 내용을 보려면 데이터 포인트(그래프의 선분 끝) 위로 마우스를 가져갑니다.

참고: 메트릭 시리즈 차트에서 X축은 검사 중인 모델 실행의 모델 디렉터리 이름입니다. 이러한 이름 자체는 의미가 없습니다.
End of explanation
"""


eval_results_from_disk = tfma.load_eval_results(output_paths)

tfma.view.render_time_series(eval_results_from_disk)

"""
Explanation: 이제 또 하루가 지나갔다고 가정하고 이전 이틀과 비교하여 오늘 들어오는 새로운 데이터에서 어떻게 작동하는지 보려고합니다.
End of explanation
"""


# Setup tfma.EvalConfig setting
eval_config_with_thresholds = text_format.Parse("""
  ## Model information
  model_specs {
    name: "candidate"
    # For keras we need to add a `label_key`.
    label_key: "big_tipper"
  }
  model_specs {
    name: "baseline"
    # For keras we need to add a `label_key`.
    label_key: "big_tipper"
    is_baseline: true
  }

  ## Post training metric information
  metrics_specs {
    metrics { class_name: "ExampleCount" }
    metrics { class_name: "BinaryAccuracy" }
    metrics { class_name: "BinaryCrossentropy" }
    metrics {
      class_name: "AUC"
      threshold {
        # Ensure that AUC is always > 0.9
        value_threshold {
          lower_bound { value: 0.9 }
        }
        # Ensure that AUC does not drop by more than a small epsilon
        # e.g. (candidate - baseline) > -1e-10 or candidate > baseline - 1e-10
        change_threshold {
          direction: HIGHER_IS_BETTER
          absolute { value: -1e-10 }
        }
      }
    }
    metrics { class_name: "AUCPrecisionRecall" }
    metrics { class_name: "Precision" }
    metrics { class_name: "Recall" }
    metrics { class_name: "MeanLabel" }
    metrics { class_name: "MeanPrediction" }
    metrics { class_name: "Calibration" }
    metrics { class_name: "CalibrationPlot" }
    metrics { class_name: "ConfusionMatrixPlot" }
    # ... add additional metrics and plots ...
  }

  ## Slicing information
  slicing_specs {}  # overall slice
  slicing_specs {
    feature_keys: ["trip_start_hour"]
  }
  slicing_specs {
    feature_keys: ["trip_start_day"]
  }
  slicing_specs {
    feature_keys: ["trip_start_month"]
  }
  slicing_specs {
    feature_keys: ["trip_start_hour", "trip_start_day"]
  }
""", tfma.EvalConfig())

# Create tfma.EvalSharedModels that point at our keras models.
candidate_model_path = os.path.join(MODELS_DIR, 'keras', '2')
baseline_model_path = os.path.join(MODELS_DIR, 'keras', '1')
eval_shared_models = [
  tfma.default_eval_shared_model(
      model_name=tfma.CANDIDATE_KEY,
      eval_saved_model_path=candidate_model_path,
      eval_config=eval_config_with_thresholds),
  tfma.default_eval_shared_model(
      model_name=tfma.BASELINE_KEY,
      eval_saved_model_path=baseline_model_path,
      eval_config=eval_config_with_thresholds),
]

validation_output_path = os.path.join(OUTPUT_DIR, 'validation')

# Run TFMA
eval_result_with_validation = tfma.run_model_analysis(
    eval_shared_models,
    eval_config=eval_config_with_thresholds,
    data_location=tfrecord_file,
    output_path=validation_output_path,
    schema=schema)

"""
Explanation: 모델 검증
TFMA는 동시에 여러 모델을 평가하도록 구성할 수 있습니다. 일반적으로, 이것은 새로운 모델을 기준선(예: 현재 제공되는 모델)과 비교하여 메트릭(예: AUC 등)의 어떤 성능 차이가 기준선과 관련이 있는지 확인하기 위해 수행됩니다. 임계값이 구성되면 TFMA는 성능이 기대와 일치하는지 여부를 나타내는 tfma.ValidationResult 레코드를 생성합니다.
keras 평가를 다시 구성하여 후보와 기준선의 두 모델을 비교해 보겠습니다. 또한 AUC 메트릭에서 tmfa.MetricThreshold를 설정하여 기준선에 대비한 후보의 성능을 검증합니다.
End of explanation
"""


tfma.view.render_time_series(eval_result_with_validation)

"""
Explanation: 기준선에 대비해 하나 이상의 모델로 평가를 실행할 때 TFMA는 평가 중에 계산된 모든 메트릭에 대해 diff 메트릭을 자동으로 추가합니다. 이러한 메트릭은 해당 메트릭의 이름을 따서 명명되지만 메트릭 이름에 _diff가 붙습니다.
실행으로 생성된 메트릭을 살펴보겠습니다.
End of explanation
"""


validation_result = tfma.load_validation_result(validation_output_path)
print(validation_result.validation_ok)

"""
Explanation: 이제 검증 검사의 출력을 살펴보겠습니다. 검증 결과를 보려면 tfma.load_validator_result를 사용합니다. 이 예의 경우 AUC가 임계값 미만이므로 검사에 실패합니다.
End of explanation
"""


#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Explanation: Copyright © 2020 The TensorFlow Authors.
End of explanation
"""


