مشاهده در TensorFlow.org | در Google Colab اجرا شود | در GitHub مشاهده کنید | دانلود دفترچه یادداشت |
این نوت بوک راه آسانی را برای ایجاد و بهینه سازی مسائل محدود با استفاده از کتابخانه TFCO نشان می دهد. این روش می تواند در بهبود مدل زمانی مفید است که در می یابیم که آنها در حال انجام نیست به همان اندازه نیز در سراسر برش های مختلف از داده های ما، که ما می توانیم شناسایی با استفاده از شاخص انصاف . دومین اصل از اصول هوش مصنوعی گوگل بیان میکند که فناوری ما باید از ایجاد یا تقویت سوگیری ناعادلانه اجتناب کند، و ما معتقدیم این تکنیک میتواند به بهبود عادلانه بودن مدل در برخی شرایط کمک کند. به طور خاص، این نوت بوک:
- آموزش ساده، مدل شبکه عصبی نامحدود برای تشخیص لبخند یک فرد را در تصاویر با استفاده از
tf.keras
و CelebFaces در مقیاس بزرگ صفات ( CelebA ) مجموعه داده. - با استفاده از شاخصهای انصاف، عملکرد مدل را در برابر معیار انصاف رایج در بین گروههای سنی ارزیابی کنید.
- برای دستیابی به عملکرد عادلانه تر در گروه های سنی، یک مسئله بهینه سازی محدود ساده را تنظیم کنید.
- آموزش مجدد مدل در حال حاضر محدود و ارزیابی عملکرد دوباره، اطمینان حاصل کرد که متریک انصاف انتخاب ما بهبود یافته است.
آخرین به روز رسانی: 3/11 فوریه 2020
نصب و راه اندازی
این نوت بوک در ایجاد شد Colaboratory ، متصل به پایتون 3 باطن موتور محاسباتی. اگر میخواهید این نوتبوک را در محیط دیگری میزبانی کنید، به شرط اینکه تمام بستههای مورد نیاز را در سلولهای زیر قرار دهید، نباید با مشکل عمده مواجه شوید.
توجه داشته باشید که اولین باری که نصب های پیپ را اجرا می کنید، ممکن است از شما خواسته شود که زمان اجرا را مجدداً راه اندازی کنید زیرا بسته های قدیمی از قبل نصب شده اند. پس از انجام این کار، از بسته های صحیح استفاده می شود.
Pip نصب می کند
!pip install -q -U pip==20.2
!pip install git+https://github.com/google-research/tensorflow_constrained_optimization
!pip install -q tensorflow-datasets tensorflow
!pip install fairness-indicators \
"absl-py==0.12.0" \
"apache-beam<3,>=2.34" \
"avro-python3==1.9.1" \
"pyzmq==17.0.0"
توجه داشته باشید که بسته به زمانی که سلول زیر را اجرا می کنید، ممکن است به زودی اخطاری در مورد تغییر نسخه پیش فرض TensorFlow در Colab به TensorFlow 2.X دریافت کنید. میتوانید با خیال راحت این هشدار را نادیده بگیرید زیرا این نوت بوک برای سازگاری با TensorFlow 1.X و 2.X طراحی شده است.
وارد کردن ماژول ها
import os
import sys
import tempfile
import urllib
import tensorflow as tf
from tensorflow import keras
import tensorflow_datasets as tfds
tfds.disable_progress_bar()
import numpy as np
import tensorflow_constrained_optimization as tfco
from tensorflow_metadata.proto.v0 import schema_pb2
from tfx_bsl.tfxio import tensor_adapter
from tfx_bsl.tfxio import tf_example_record
بهعلاوه، چند واردات خاص به شاخصهای انصاف اضافه میکنیم که از آنها برای ارزیابی و تجسم عملکرد مدل استفاده میکنیم.
واردات مرتبط با شاخص های انصاف
import tensorflow_model_analysis as tfma
import fairness_indicators as fi
from google.protobuf import text_format
import apache_beam as beam
اگرچه TFCO با اجرای اشتیاق و گراف سازگار است، این نوت بوک فرض می کند که اجرای مشتاق به طور پیش فرض فعال است، همانطور که در TensorFlow 2.x فعال است. برای اطمینان از اینکه هیچ چیز خراب نمی شود، اجرای مشتاق در سلول زیر فعال می شود.
Eager Execution و Print Versions را فعال کنید
if tf.__version__ < "2.0.0":
tf.compat.v1.enable_eager_execution()
print("Eager execution enabled.")
else:
print("Eager execution enabled by default.")
print("TensorFlow " + tf.__version__)
print("TFMA " + tfma.VERSION_STRING)
print("TFDS " + tfds.version.__version__)
print("FI " + fi.version.__version__)
Eager execution enabled by default. TensorFlow 2.8.0-rc0 TFMA 0.36.0 TFDS 4.4.0 FI 0.36.0
مجموعه داده CelebA
CelebA یک چهره در مقیاس بزرگ ویژگی های مجموعه داده با بیش از 200،000 تصاویر مشهور، هر کدام با 40 حاشیه نویسی ویژگی (مانند نوع مو، لوازم جانبی مد، ویژگی های صورت، و غیره) و مکان های 5 نقطه عطفی (چشم ها، دهان و موقعیت بینی). برای اطلاعات بیشتر نگاهی به این مقاله . با کسب اجازه از صاحبان، ما این مجموعه داده در Google Cloud Storage ذخیره می شود و بیشتر آن را از طریق دسترسی به 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
تست توابع کمکی مجموعه داده
local_root = tempfile.mkdtemp(prefix='test-data')
def local_test_filename_base():
return local_root
def local_test_file_full_prefix():
return os.path.join(local_test_filename_base(), "celeb_a-test.tfrecord")
def copy_test_files_to_local():
filename_base = local_test_file_full_prefix()
num_test_shards = num_test_shards_dict[version]
for shard in range(num_test_shards):
url = "https://storage.googleapis.com/celeb_a_dataset/celeb_a/%s/celeb_a-test.tfrecord-0000%s-of-0000%s" % (version, shard, num_test_shards)
filename = "%s-0000%s-of-0000%s" % (filename_base, shard, num_test_shards)
res = urllib.request.urlretrieve(url, filename)
هشدارها
قبل از حرکت به جلو، در استفاده از CelebA باید چندین نکته را در نظر داشت:
- اگرچه در اصل این نوت بوک می توانست از هر مجموعه داده ای از تصاویر چهره استفاده کند، CelebA انتخاب شد زیرا حاوی تصاویر مالکیت عمومی از شخصیت های عمومی است.
- تمام حاشیه نویسی ویژگی ها در CelebA به عنوان دسته های باینری عملیاتی می شوند. به عنوان مثال، ویژگی "Young" (همانطور که توسط برچسبگذاران مجموعه داده تعیین میشود) به صورت موجود یا غایب در تصویر نشان داده میشود.
- دسته بندی های CelebA منعکس کننده تنوع واقعی صفات انسانی نیست.
- برای اهداف این دفترچه، ویژگی حاوی ویژگی "جوان" به عنوان "گروه سنی" نامیده می شود، که در آن وجود ویژگی "جوان" در یک تصویر به عنوان عضوی از گروه سنی "جوان" و عدم وجود ویژگی "جوان" به عنوان عضوی از گروه سنی "جوان نیست" برچسب زده می شود. این فرضیات ساخته شده به عنوان این اطلاعات در ذکر نشده است مقاله اصلی .
- به این ترتیب، عملکرد در مدلهای آموزشدیدهشده در این نوتبوک به روشهایی که ویژگیها توسط نویسندگان CelebA عملیاتی شده و حاشیهنویسی شدهاند، مرتبط است.
- این مدل باید برای مقاصد تجاری به عنوان که نقض استفاده نمی شود شرایط تحقیقات غیر تجاری CelebA است .
تنظیم توابع ورودی
سلول های بعدی به ساده سازی خط لوله ورودی و همچنین تجسم عملکرد کمک می کنند.
ابتدا برخی از متغیرهای مرتبط با داده را تعریف می کنیم و یک تابع پیش پردازش لازم را تعریف می کنیم.
متغیرها را تعریف کنید
ATTR_KEY = "attributes"
IMAGE_KEY = "image"
LABEL_KEY = "Smiling"
GROUP_KEY = "Young"
IMAGE_SIZE = 28
توابع پیش پردازش را تعریف کنید
def preprocess_input_dict(feat_dict):
# Separate out the image and target variable from the feature dictionary.
image = feat_dict[IMAGE_KEY]
label = feat_dict[ATTR_KEY][LABEL_KEY]
group = feat_dict[ATTR_KEY][GROUP_KEY]
# Resize and normalize image.
image = tf.cast(image, tf.float32)
image = tf.image.resize(image, [IMAGE_SIZE, IMAGE_SIZE])
image /= 255.0
# Cast label and group to float32.
label = tf.cast(label, tf.float32)
group = tf.cast(group, tf.float32)
feat_dict[IMAGE_KEY] = image
feat_dict[ATTR_KEY][LABEL_KEY] = label
feat_dict[ATTR_KEY][GROUP_KEY] = group
return feat_dict
get_image_and_label = lambda feat_dict: (feat_dict[IMAGE_KEY], feat_dict[ATTR_KEY][LABEL_KEY])
get_image_label_and_group = lambda feat_dict: (feat_dict[IMAGE_KEY], feat_dict[ATTR_KEY][LABEL_KEY], feat_dict[ATTR_KEY][GROUP_KEY])
سپس، توابع دادهای را که در بقیه قسمتهای کولب نیاز داریم، ایجاد میکنیم.
# 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 منحرف شود. هنگام کار با Keras به همین دلیل، مدل ساده نگه داشته خواهد شد - اما برای کشف این فضا تشویق شوید.
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
ما همچنین یک تابع برای تنظیم دانه ها برای اطمینان از نتایج تکرارپذیر تعریف می کنیم. توجه داشته باشید که این کولب به عنوان یک ابزار آموزشی در نظر گرفته شده است و ثبات یک خط لوله تولید دقیق را ندارد. دویدن بدون گذاشتن دانه ممکن است به نتایج متفاوتی منجر شود.
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 استفاده می شود.
توابع پیش پردازش داده برای
def tfds_filepattern_for_split(dataset_name, split):
return f"{local_test_file_full_prefix()}*"
class PreprocessCelebA(object):
"""Class that deserializes, decodes and applies additional preprocessing for CelebA input."""
def __init__(self, dataset_name):
builder = tfds.builder(dataset_name)
self.features = builder.info.features
example_specs = self.features.get_serialized_info()
self.parser = tfds.core.example_parser.ExampleParser(example_specs)
def __call__(self, serialized_example):
# Deserialize
deserialized_example = self.parser.parse_example(serialized_example)
# Decode
decoded_example = self.features.decode_example(deserialized_example)
# Additional preprocessing
image = decoded_example[IMAGE_KEY]
label = decoded_example[ATTR_KEY][LABEL_KEY]
# Resize and scale image.
image = tf.cast(image, tf.float32)
image = tf.image.resize(image, [IMAGE_SIZE, IMAGE_SIZE])
image /= 255.0
image = tf.reshape(image, [-1])
# Cast label and group to float32.
label = tf.cast(label, tf.float32)
group = decoded_example[ATTR_KEY][GROUP_KEY]
output = tf.train.Example()
output.features.feature[IMAGE_KEY].float_list.value.extend(image.numpy().tolist())
output.features.feature[LABEL_KEY].float_list.value.append(label.numpy())
output.features.feature[GROUP_KEY].bytes_list.value.append(b"Young" if group.numpy() else b'Not Young')
return output.SerializeToString()
def tfds_as_pcollection(beam_pipeline, dataset_name, split):
return (
beam_pipeline
| 'Read records' >> beam.io.ReadFromTFRecord(tfds_filepattern_for_split(dataset_name, split))
| 'Preprocess' >> beam.Map(PreprocessCelebA(dataset_name))
)
در نهایت تابعی را تعریف می کنیم که نتایج را در 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) ارزیابی میکنیم. به طور خاص، ما علاقه مندیم ببینیم که آیا شکاف قابل توجهی در عملکرد بین دستههای "جوان" و "نه جوان" هنگام ارزیابی نرخ مثبت کاذب وجود دارد یا خیر.
یک خطای مثبت کاذب زمانی رخ می دهد که مدل کلاس مثبت را به اشتباه پیش بینی کند. در این زمینه، یک پیامد مثبت کاذب زمانی اتفاق میافتد که حقیقت اصلی تصویری از یک سلبریتی «نه لبخند» باشد و مدل «خندان» را پیشبینی کند. با بسط، نرخ مثبت کاذب، که در تصویرسازی بالا استفاده میشود، معیاری برای دقت یک تست است. در حالی که این یک خطای نسبتاً پیش پا افتاده در این زمینه است، اشتباهات مثبت کاذب گاهی اوقات می توانند باعث بروز رفتارهای مشکل سازتر شوند. به عنوان مثال، یک خطای مثبت کاذب در یک طبقهبندی کننده هرزنامه میتواند باعث شود کاربر یک ایمیل مهم را از دست بدهد.
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)`
همانطور که در بالا ذکر شد، ما روی نرخ مثبت کاذب تمرکز می کنیم. نسخه فعلی Fairness Indicators (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 است ، یاران چند که آن را آسان تر برای محدود کردن مشکل وجود دارد:
-
tfco.rate_context()
- این چیزی است که می شود در ساخت یک محدودیت برای هر دسته بندی گروه سنی استفاده می شود. -
tfco.RateMinimizationProblem()
- عبارت نرخ به اینجا حداقل برسد خواهد بود کاذب موضوع نرخ مثبت به گروه سنی است. به عبارت دیگر، عملکرد اکنون بر اساس تفاوت بین نرخ های مثبت کاذب گروه سنی و مجموعه داده کلی ارزیابی می شود. برای این نمایش، نرخ مثبت کاذب کمتر یا مساوی 5% به عنوان محدودیت تعیین می شود. -
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.
مانند دفعه قبل که از Fairness Indicators استفاده کردیم، 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 توانست مدلی پیدا کند که نزدیک به ارضای محدودیت باشد و اختلاف بین گروه ها را تا حد امکان کاهش دهد.