![]() |
![]() |
![]() |
![]() |
總覽
在此活動中,您將使用公平性指標來探索 Labeled Faces in the Wild 資料集上的 FaceSSD 預測。公平性指標是一套建構於 TensorFlow Model Analysis 之上的工具,能夠定期評估產品管線中的公平性指標。
關於資料集
在本練習中,您將使用 FaceSSD 預測資料集,其中包含大約 20 萬個不同的圖像預測和由 FaceSSD API 產生的真實值。
關於工具
TensorFlow Model Analysis 是一個用於評估 TensorFlow 和非 TensorFlow 機器學習模型的程式庫。它允許使用者以分散式方式在大量資料上評估其模型,計算圖內和其他指標在不同資料切片上的值,並在筆記本中視覺化。
TensorFlow Data Validation 是您可以使用的其中一種工具,用於分析您的資料。您可以使用它來找出資料中的潛在問題,例如缺失值和資料不平衡,這些問題可能會導致公平性差距。
透過公平性指標,使用者將能夠
- 評估模型效能,依使用者定義群組進行切片
- 對結果感到有信心,具有信賴區間和在多個閾值下的評估
匯入
執行以下程式碼以安裝 fairness_indicators 程式庫。此套件包含我們將在本練習中使用的工具。可能會要求重新啟動執行階段,但不是必要的。
pip install apache_beam
pip install fairness-indicators
pip install witwidget
import os
import tempfile
import apache_beam as beam
import numpy as np
import pandas as pd
from datetime import datetime
import tensorflow_hub as hub
import tensorflow as tf
import tensorflow_model_analysis as tfma
import tensorflow_data_validation as tfdv
from tensorflow_model_analysis.addons.fairness.post_export_metrics import fairness_indicators
from tensorflow_model_analysis.addons.fairness.view import widget_view
from tensorflow_model_analysis.model_agnostic_eval import model_agnostic_predict as agnostic_predict
from tensorflow_model_analysis.model_agnostic_eval import model_agnostic_evaluate_graph
from tensorflow_model_analysis.model_agnostic_eval import model_agnostic_extractor
from witwidget.notebook.visualization import WitConfigBuilder
from witwidget.notebook.visualization import WitWidget
下載並了解資料
Labeled Faces in the Wild 是一個公開基準資料集,用於人臉驗證,也稱為配對比對。LFW 包含超過 13,000 張從網路收集的人臉圖像。
我們在此資料集上執行 FaceSSD 預測,以預測給定影像中是否有人臉。在此 Colab 中,我們將依性別切片資料,以觀察不同性別群組的模型效能是否存在任何顯著差異。
如果影像中有多張人臉,性別會標記為「MISSING」。
為了方便起見,我們已將資料集託管在 Google Cloud Platform 上。執行以下程式碼以從 GCP 下載資料,資料大約需要一分鐘下載和分析。
data_location = tf.keras.utils.get_file('lfw_dataset.tf', 'https://storage.googleapis.com/facessd_dataset/lfw_dataset.tfrecord')
stats = tfdv.generate_statistics_from_tfrecord(data_location=data_location)
tfdv.visualize_statistics(stats)
定義常數
BASE_DIR = tempfile.gettempdir()
tfma_eval_result_path = os.path.join(BASE_DIR, 'tfma_eval_result')
compute_confidence_intervals = True
slice_key = 'object/groundtruth/Gender'
label_key = 'object/groundtruth/face'
prediction_key = 'object/prediction/face'
feature_map = {
slice_key:
tf.io.FixedLenFeature([], tf.string, default_value=['none']),
label_key:
tf.io.FixedLenFeature([], tf.float32, default_value=[0.0]),
prediction_key:
tf.io.FixedLenFeature([], tf.float32, default_value=[0.0]),
}
用於 TFMA 的模型不可知配置
model_agnostic_config = agnostic_predict.ModelAgnosticConfig(
label_keys=[label_key],
prediction_keys=[prediction_key],
feature_spec=feature_map)
model_agnostic_extractors = [
model_agnostic_extractor.ModelAgnosticExtractor(
model_agnostic_config=model_agnostic_config, desired_batch_size=3),
tfma.extractors.slice_key_extractor.SliceKeyExtractor(
[tfma.slicer.SingleSliceSpec(),
tfma.slicer.SingleSliceSpec(columns=[slice_key])])
]
公平性回呼與計算公平性指標
# Helper class for counting examples in beam PCollection
class CountExamples(beam.CombineFn):
def __init__(self, message):
self.message = message
def create_accumulator(self):
return 0
def add_input(self, current_sum, element):
return current_sum + 1
def merge_accumulators(self, accumulators):
return sum(accumulators)
def extract_output(self, final_sum):
if final_sum:
print("%s: %d"%(self.message, final_sum))
metrics_callbacks = [
tfma.post_export_metrics.fairness_indicators(
thresholds=[0.1, 0.3, 0.5, 0.7, 0.9],
labels_key=label_key,
target_prediction_keys=[prediction_key]),
tfma.post_export_metrics.auc(
curve='PR',
labels_key=label_key,
target_prediction_keys=[prediction_key]),
]
eval_shared_model = tfma.types.EvalSharedModel(
add_metrics_callbacks=metrics_callbacks,
construct_fn=model_agnostic_evaluate_graph.make_construct_fn(
add_metrics_callbacks=metrics_callbacks,
config=model_agnostic_config))
with beam.Pipeline() as pipeline:
# Read data.
data = (
pipeline
| 'ReadData' >> beam.io.ReadFromTFRecord(data_location))
# Count all examples.
data_count = (
data | 'Count number of examples' >> beam.CombineGlobally(
CountExamples('Before filtering "Gender:MISSING"')))
# If there are more than one face in image, the gender feature is 'MISSING'
# and we are filtering that image out.
def filter_missing_gender(element):
example = tf.train.Example.FromString(element)
if example.features.feature[slice_key].bytes_list.value[0] != b'MISSING':
yield element
filtered_data = (
data
| 'Filter Missing Gender' >> beam.ParDo(filter_missing_gender))
# Count after filtering "Gender:MISSING".
filtered_data_count = (
filtered_data | 'Count number of examples after filtering'
>> beam.CombineGlobally(
CountExamples('After filtering "Gender:MISSING"')))
# Because LFW data set has always faces by default, we are adding
# labels as 1.0 for all images.
def add_face_groundtruth(element):
example = tf.train.Example.FromString(element)
example.features.feature[label_key].float_list.value[:] = [1.0]
yield example.SerializeToString()
final_data = (
filtered_data
| 'Add Face Groundtruth' >> beam.ParDo(add_face_groundtruth))
# Run TFMA.
_ = (
final_data
| 'ExtractEvaluateAndWriteResults' >>
tfma.ExtractEvaluateAndWriteResults(
eval_shared_model=eval_shared_model,
compute_confidence_intervals=compute_confidence_intervals,
output_path=tfma_eval_result_path,
extractors=model_agnostic_extractors))
eval_result = tfma.load_eval_result(output_path=tfma_eval_result_path)
呈現公平性指標
使用匯出的評估結果呈現公平性指標小工具。
在下方您將看到長條圖,顯示資料每個切片在選定指標上的效能。您可以使用視覺化頂部的下拉式選單,調整基準比較切片以及顯示的閾值。
此用例的相關指標是真陽性率,也稱為召回率。使用左側的選擇器,選擇 true_positive_rate 的圖表。這些指標值與模型卡上顯示的值相符。
對於某些照片,如果照片中的人太年輕而無法準確標註,性別會標記為年輕,而不是男性或女性。
widget_view.render_fairness_indicator(eval_result=eval_result,
slicing_column=slice_key)