يوم مجتمع ML هو 9 نوفمبر! الانضمام إلينا للحصول على التحديثات من TensorFlow، JAX، وأكثر معرفة المزيد

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

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

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

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

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

التركيب

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

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

تثبيت Pip

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

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

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

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

تمكين التنفيذ الحثيث وإصدارات الطباعة

Eager execution enabled by default.
TensorFlow 2.4.1
TFMA 0.29.0
TFDS 4.2.0
FI 0.29.0

مجموعة بيانات CelebA

CelebA عبارة عن مجموعة بيانات لسمات الوجه واسعة النطاق تحتوي على أكثر من 200000 صورة من صور المشاهير ، ولكل منها 40 تعليقًا توضيحيًا للسمات (مثل نوع الشعر وإكسسوارات الموضة وميزات الوجه وما إلى ذلك) و 5 مواقع بارزة (مواقع العيون والفم والأنف) لمزيد من التفاصيل الق نظرة على الصحيفة . بإذن من المالكين ، قمنا بتخزين مجموعة البيانات هذه على Google Cloud Storage والوصول إليها في الغالب عبر مجموعات بيانات tfds ( tfds ) .

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

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

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

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

نحدد أيضًا وظيفة لضبط البذور لضمان نتائج قابلة للتكرار. لاحظ أن هذا colab يُقصد به أن يكون أداة تعليمية ولا يتمتع باستقرار خط أنابيب إنتاج مضبوط بدقة. قد يؤدي الجري دون وضع بذرة إلى نتائج متنوعة.

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 [==============================] - 17s 11ms/step - loss: 0.6219 - accuracy: 0.7189
Epoch 2/5
1000/1000 [==============================] - 10s 10ms/step - loss: 0.4061 - accuracy: 0.8187
Epoch 3/5
1000/1000 [==============================] - 10s 10ms/step - loss: 0.3649 - accuracy: 0.8391
Epoch 4/5
1000/1000 [==============================] - 16s 16ms/step - loss: 0.3427 - accuracy: 0.8485
Epoch 5/5
1000/1000 [==============================] - 10s 10ms/step - loss: 0.3390 - accuracy: 0.8482
<tensorflow.python.keras.callbacks.History at 0x7f47c01a8550>

يجب أن يؤدي تقييم النموذج على بيانات الاختبار إلى درجة دقة نهائية تزيد قليلاً عن 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 [==============================] - 40s 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')
INFO:tensorflow:Assets written to: /tmp/saved_modelseqklzviu/model_export_unconstrained/assets
INFO:tensorflow:Assets written to: /tmp/saved_modelseqklzviu/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: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.6/site-packages/tensorflow_model_analysis/writers/metrics_plots_and_validations_writer.py:113: 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.6/site-packages/tensorflow_model_analysis/writers/metrics_plots_and_validations_writer.py:113: 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': 'Overall', 'slice': 'Overall', 'metrics': {'example_cou…

كما تظهر النتائج أعلاه ، نرى فجوة غير متناسبة بين فئتي "الشباب" و "ليست صغيرة" .

هذا هو المكان الذي يمكن أن تساعد فيه TFCO من خلال تقييد المعدل الإيجابي الخاطئ ليكون ضمن معيار أكثر قبولًا.

إعداد نموذج مقيد

كما هو موثق في مكتبة TFCO ، هناك العديد من المساعدين الذين سيجعلون من السهل تقييد المشكلة:

  1. tfco.rate_context() - هذا هو ما سيُستخدم في بناء قيد لكل فئة عمرية.
  2. tfco.RateMinimizationProblem() - سيكون تعبير المعدل المطلوب تصغيره هنا هو المعدل الإيجابي الخاطئ الخاضع 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_modelsrnjadh_e/model_export_constrained/assets
INFO:tensorflow:Assets written to: /tmp/saved_modelsrnjadh_e/model_export_constrained/assets

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