مثال على التحسين المقيد TensorFlow باستخدام مجموعة بيانات CelebA

عرض على TensorFlow.org تشغيل في Google Colab عرض على جيثب تحميل دفتر

يوضح هذا الكمبيوتر الدفتري طريقة سهلة لإنشاء المشكلات المقيدة وتحسينها باستخدام مكتبة TFCO. يمكن أن يكون هذا الأسلوب مفيدا في تحسين النماذج عندما نجد انهم لا يؤدون جيدا بالتساوي عبر شرائح مختلفة من البيانات لدينا، ونحن يمكن أن تحدد باستخدام مؤشرات الإنصاف . ينص المبدأ الثاني من مبادئ الذكاء الاصطناعي في Google على أن تقنيتنا يجب أن تتجنب خلق التحيز غير العادل أو تعزيزه ، ونعتقد أن هذه التقنية يمكن أن تساعد في تحسين عدالة النموذج في بعض المواقف. على وجه الخصوص ، سوف يقوم هذا الكمبيوتر الدفتري بما يلي:

  • تدريب بسيط، غير المقيد نموذج الشبكة العصبية للكشف عن ابتسامة الشخص في الصور باستخدام tf.keras وCelebFaces على نطاق واسع سمات ( CelebA ) البيانات.
  • قم بتقييم أداء النموذج مقابل مقياس الإنصاف الشائع الاستخدام عبر الفئات العمرية ، باستخدام مؤشرات الإنصاف.
  • قم بإعداد مشكلة تحسين مقيد بسيطة لتحقيق أداء أكثر عدلاً عبر الفئات العمرية.
  • الإبقاء على النموذج مقيدة الآن وتقييم الأداء مرة أخرى، وضمان أن لدينا قياس عدالة المختار قد تحسن.

آخر تحديث: 3/11 فبراير 2020

التركيب

تم إنشاء هذا الكمبيوتر الدفتري في Colaboratory ، متصلا بيثون 3 جوجل حساب محرك الخلفية. إذا كنت ترغب في استضافة هذا الكمبيوتر الدفتري في بيئة مختلفة ، فيجب ألا تواجه أي مشكلات كبيرة بشرط تضمين جميع الحزم المطلوبة في الخلايا أدناه.

لاحظ أنه في المرة الأولى التي تقوم فيها بتشغيل تثبيتات النقطة ، قد يُطلب منك إعادة تشغيل وقت التشغيل بسبب الحزم القديمة المثبتة مسبقًا. بمجرد القيام بذلك ، سيتم استخدام الحزم الصحيحة.

تثبيت Pip

لاحظ أنه بناءً على وقت تشغيل الخلية أدناه ، قد تتلقى تحذيرًا بشأن الإصدار الافتراضي من TensorFlow في Colab بالتبديل إلى TensorFlow 2.X قريبًا. يمكنك تجاهل هذا التحذير بأمان حيث تم تصميم هذا الكمبيوتر الدفتري ليكون متوافقًا مع TensorFlow 1.X و 2.X.

وحدات الاستيراد

بالإضافة إلى ذلك ، نضيف بعض الواردات الخاصة بمؤشرات الإنصاف التي سنستخدمها لتقييم وتصور أداء النموذج.

على الرغم من أن TFCO متوافقة مع التنفيذ الجاد والرسم البياني ، إلا أن هذا الكمبيوتر المحمول يفترض أن التنفيذ الحثيث يتم تمكينه افتراضيًا كما هو الحال في TensorFlow 2.x. لضمان عدم تعطل أي شيء ، سيتم تمكين التنفيذ الجاد في الخلية أدناه.

تمكين التنفيذ الحثيث وطباعة النسخ

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 ) .

في هذا الكمبيوتر الدفتري:

  • سيكون لدينا نموذج محاولة لتصنيف ما إذا كان موضوع الصورة يبتسم، ممثلا في "يبتسم" سمة *.
  • سيتم تغيير حجم الصور من 218 × 178 إلى 28 × 28 لتقليل وقت التنفيذ والذاكرة عند التدريب.
  • سيتم تقييم أداء نموذجنا عبر الفئات العمرية ، باستخدام السمة الثنائية "الشباب". سوف نسمي هذه "الفئة العمرية" في هذه المفكرة.

* في حين أن هناك القليل من المعلومات المتاحة عن منهجية وضع العلامات حول هذه البينات، فإننا نفترض أن "يبتسم" السمة تم تحديد من قبل يسر والتعبير نوع، أو مسليا على وجهه في هذا الموضوع. لغرض دراسة الحالة هذه ، سنأخذ هذه الملصقات على أنها حقيقة أساسية.

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 ل .

إعداد وظائف الإدخال

ستساعد الخلايا اللاحقة في تبسيط خط أنابيب الإدخال وكذلك تصور الأداء.

أولاً نحدد بعض المتغيرات المتعلقة بالبيانات ونحدد وظيفة المعالجة المسبقة المطلوبة.

تحديد المتغيرات

تحديد وظائف ما قبل المعالجة

ثم نبني وظائف البيانات التي نحتاجها في باقي الكولاب.

# 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.

وظائف المعالجة المسبقة للبيانات لـ

أخيرًا ، نحدد دالة تقوم بتقييم النتائج في 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)`

كما ذكرنا أعلاه ، نحن نركز على المعدل الإيجابي الخاطئ. يحدد الإصدار الحالي من مؤشرات الإنصاف (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 من العثور على نموذج يقترب من تلبية القيد ويقلل من التفاوت بين المجموعات قدر الإمكان.