在 TensorFlow.org 上查看
|
在 Google Colab 中运行
|
在 GitHub 上查看
|
下载笔记本
|
概览
在本次活动中,您将使用 公平性指标 (Fairness Indicators) 来探索 FaceSSD 在“野外标记人脸 (Labeled Faces in the Wild)”数据集上的预测结果。公平性指标是一套构建于 TensorFlow 模型分析 (TensorFlow Model Analysis) 之上的工具,旨在支持在产品流水线中对公平性指标进行常规评估。
关于数据集
在本练习中,您将使用 FaceSSD 预测数据集,其中包含约 20 万条由 FaceSSD API 生成的不同图像预测结果和真实值 (groundtruths)。
关于工具
TensorFlow 模型分析 (TensorFlow Model Analysis) 是一个用于评估 TensorFlow 和非 TensorFlow 机器学习模型的库。它允许用户以分布式方式在大规模数据上评估模型,计算图内指标及其他指标在不同数据切片上的表现,并可在笔记本中进行可视化。
TensorFlow 数据验证 (TensorFlow Data Validation) 是您可以用来分析数据的工具之一。您可以使用它来查找数据中的潜在问题(例如缺失值和数据不平衡),这些问题可能会导致公平性差异。
使用 公平性指标 (Fairness Indicators),用户能够:
- 评估模型性能,并按定义的用户群进行切片(sliced)
- 通过置信区间和多阈值评估,确信结果的可靠性
导入
运行以下代码以安装 fairness_indicators 库。此包包含我们在本练习中将要使用的工具。系统可能会要求重启运行时,但这不是必须的。
pip install apache_beampip install fairness-indicatorspip 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),也称为召回率 (recall)。使用左侧的选择器选择 true_positive_rate 的图表。这些指标值与模型卡上显示的值相匹配。
对于某些照片,如果照片中的人年龄太小而无法进行准确标注,则其性别被标记为“young”(年幼),而不是男性或女性。
widget_view.render_fairness_indicator(eval_result=eval_result,
slicing_column=slice_key)
在 TensorFlow.org 上查看
在 Google Colab 中运行
在 GitHub 上查看
下载笔记本