مطالعه موردی اصلاح مدل

در این دفترچه، ما یک طبقه‌بندی متن را آموزش می‌دهیم تا محتوای نوشتاری را که می‌تواند سمی یا مضر در نظر گرفته شود، شناسایی کرده و از MinDiff برای رفع برخی نگرانی‌های مربوط به عدالت استفاده می‌کنیم. در گردش کار خود، ما موارد زیر را انجام خواهیم داد:

  1. عملکرد مدل پایه ما را در مورد متن حاوی ارجاع به گروه های حساس ارزیابی کنید.
  2. با تمرین با MinDiff عملکرد را در هر گروهی که عملکرد ضعیفی دارند، بهبود بخشید.
  3. عملکرد مدل جدید را بر اساس معیار انتخابی ما ارزیابی کنید.

هدف ما نشان دادن استفاده از تکنیک MinDiff با گردش کار بسیار کم است، نه ارائه یک رویکرد اصولی برای عدالت در یادگیری ماشین. به این ترتیب، ارزیابی ما فقط بر یک مقوله حساس و یک معیار واحد متمرکز خواهد بود. ما همچنین به کاستی‌های بالقوه در مجموعه داده‌ها رسیدگی نمی‌کنیم و تنظیمات خود را تنظیم نمی‌کنیم. در یک محیط تولید، شما می خواهید به هر یک از اینها با دقت نزدیک شوید. برای کسب اطلاعات بیشتر در مورد ارزیابی برای عدالت، و این راهنمای .

برپایی

ما با نصب Fairness Indicators و TensorFlow Model Remediation شروع می کنیم.

نصب می کند

تمام اجزای لازم از جمله MinDiff و Fairness Indicators را برای ارزیابی وارد کنید.

واردات

ما از یک تابع ابزار برای دانلود داده های از پیش پردازش شده و آماده سازی برچسب ها برای مطابقت با شکل خروجی مدل استفاده می کنیم. این تابع همچنین داده ها را به عنوان TFRecords بارگیری می کند تا ارزیابی بعدی را سریعتر انجام دهد. از طرف دیگر، می‌توانید Pandas DataFrame را با هر تابع تبدیل ابزار موجود به TFRecords تبدیل کنید.

# We use a helper utility to preprocessed data for convenience and speed.
data_train, data_validate, validate_tfrecord_file, labels_train, labels_validate = min_diff_keras_utils.download_and_process_civil_comments_data()
Downloading data from https://storage.googleapis.com/civil_comments_dataset/train_df_processed.csv
345702400/345699197 [==============================] - 8s 0us/step
Downloading data from https://storage.googleapis.com/civil_comments_dataset/validate_df_processed.csv
229974016/229970098 [==============================] - 5s 0us/step
Downloading data from https://storage.googleapis.com/civil_comments_dataset/validate_tf_processed.tfrecord
324943872/324941336 [==============================] - 9s 0us/step

ما چند ثابت مفید تعریف می کنیم. ما در بر مدل در آموزش خواهد 'comment_text' ویژگی، با برچسب هدف ما به عنوان 'toxicity' . توجه داشته باشید که اندازه دسته در اینجا به صورت دلخواه انتخاب می شود، اما در یک محیط تولید باید آن را برای بهترین عملکرد تنظیم کنید.

TEXT_FEATURE = 'comment_text'
LABEL = 'toxicity'
BATCH_SIZE = 512

دانه های تصادفی را تنظیم کنید. (توجه داشته باشید که این به طور کامل نتایج را تثبیت نمی کند.)

دانه

مدل پایه را تعریف و آموزش دهید

برای کاهش زمان اجرا، به طور پیش فرض از یک مدل از پیش آموزش دیده استفاده می کنیم. این یک مدل متوالی Keras ساده با لایه‌های جاسازی و پیچش اولیه است که یک پیش‌بینی سمیت را ارائه می‌دهد. اگر ترجیح می دهید، می توانید این را تغییر دهید و از ابتدا با استفاده از تابع ابزار ما برای ایجاد مدل آموزش دهید. (توجه داشته باشید که از آنجایی که محیط شما احتمالاً با محیط ما متفاوت است، باید آستانه تنظیم و ارزیابی را سفارشی کنید.)

use_pretrained_model = True

if use_pretrained_model:
  URL = 'https://storage.googleapis.com/civil_comments_model/baseline_model.zip'
  BASE_PATH = tempfile.mkdtemp()
  ZIP_PATH = os.path.join(BASE_PATH, 'baseline_model.zip')
  MODEL_PATH = os.path.join(BASE_PATH, 'tmp/baseline_model')

  r = requests.get(URL, allow_redirects=True)
  open(ZIP_PATH, 'wb').write(r.content)

  with zipfile.ZipFile(ZIP_PATH, 'r') as zip_ref:
    zip_ref.extractall(BASE_PATH)
  baseline_model = tf.keras.models.load_model(
      MODEL_PATH, custom_objects={'KerasLayer' : hub.KerasLayer})
else:
  optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
  loss = tf.keras.losses.BinaryCrossentropy()

  baseline_model = min_diff_keras_utils.create_keras_sequential_model()

  baseline_model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])

  baseline_model.fit(x=data_train[TEXT_FEATURE],
                     y=labels_train,
                     batch_size=BATCH_SIZE,
                     epochs=20)

ما مدل به منظور ارزیابی با استفاده از صرفه جویی در شاخص عدالت .

base_dir = tempfile.mkdtemp(prefix='saved_models')
baseline_model_location = os.path.join(base_dir, 'model_export_baseline')
baseline_model.save(baseline_model_location, save_format='tf')
INFO:tensorflow:Assets written to: /tmp/saved_models867b8d74/model_export_baseline/assets
INFO:tensorflow:Assets written to: /tmp/saved_models867b8d74/model_export_baseline/assets

در مرحله بعد، Fairness Indicators را اجرا می کنیم. به عنوان یک یادآوری، ما فقط رفتن را به انجام ارزیابی قطعه قطعه برای نظر یک دسته، گروه های مذهبی ارجاع. در یک محیط تولید، توصیه می‌کنیم یک رویکرد متفکرانه برای تعیین اینکه کدام دسته‌ها و معیارها باید ارزیابی شوند، اتخاذ کنید.

برای محاسبه عملکرد مدل، تابع ابزار چند انتخاب راحت برای متریک ها، برش ها و آستانه های طبقه بندی کننده انجام می دهد.

# We use a helper utility to hide the evaluation logic for readability.
base_dir = tempfile.mkdtemp(prefix='eval')
eval_dir = os.path.join(base_dir, 'tfma_eval_result')
eval_result = fi_util.get_eval_results(
    baseline_model_location, eval_dir, validate_tfrecord_file)
WARNING:absl:Tensorflow version (2.5.0) found. Note that TFMA support for TF 2.0 is currently in beta
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.7/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.7/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)`

رندر نتایج ارزیابی

widget_view.render_fairness_indicator(eval_result)
FairnessIndicatorViewer(slicingMetrics=[{'sliceValue': 'Overall', 'slice': 'Overall', 'metrics': {'accuracy': …

بیایید به نتایج ارزیابی نگاه کنیم. نرخ مثبت کاذب متریک (FPR) را با آستانه 0.450 انتخاب کنید. می‌توانیم ببینیم که این مدل برای برخی از گروه‌های مذهبی به خوبی برخی دیگر عمل نمی‌کند و FPR بسیار بالاتری را نشان می‌دهد. به فواصل اطمینان گسترده در برخی از گروه ها توجه کنید زیرا آنها نمونه های بسیار کمی دارند. این امر باعث می شود که با قاطعیت بتوان گفت که تفاوت قابل توجهی در عملکرد این برش ها وجود دارد. ممکن است بخواهیم مثال های بیشتری برای پرداختن به این موضوع جمع آوری کنیم. با این حال، می‌توانیم سعی کنیم MinDiff را برای دو گروهی که مطمئن هستیم عملکرد ضعیفی دارند، اعمال کنیم.

ما انتخاب کرده‌ایم که روی FPR تمرکز کنیم، زیرا FPR بالاتر به این معنی است که نظراتی که به این گروه‌های هویتی ارجاع می‌دهند، بیشتر از سایر نظرات به اشتباه به عنوان سمی علامت‌گذاری می‌شوند. این می تواند منجر به پیامدهای ناعادلانه برای کاربرانی شود که در گفتگو در مورد مذهب شرکت می کنند، اما توجه داشته باشید که تفاوت در سایر معیارها می تواند منجر به انواع دیگر آسیب شود.

تعریف و آموزش مدل MinDiff

اکنون، ما سعی خواهیم کرد FPR را برای گروه های مذهبی که عملکرد ضعیفی دارند، بهبود بخشیم. ما تلاش می کنیم به انجام این کار با استفاده از MinDiff ، یک تکنیک اصلاح است که به دنبال تعادل نرخ خطا در برش داده های خود را مجازات نابرابری در عملکرد در طول آموزش. هنگامی که ما MinDiff را اعمال می کنیم، عملکرد مدل ممکن است در قسمت های دیگر کمی کاهش یابد. به این ترتیب، اهداف ما با MinDiff این خواهد بود:

  • بهبود عملکرد برای گروه هایی که عملکرد ضعیفی دارند
  • تخریب محدود برای گروه های دیگر و عملکرد کلی

داده های خود را آماده کنید

برای استفاده از MinDiff، دو تقسیم داده اضافی ایجاد می کنیم:

  • تقسیمی برای نمونه‌های غیرسمی که به گروه‌های اقلیت ارجاع می‌دهند: در مورد ما، این شامل نظراتی با ارجاع به شرایط هویتی ما است که عملکرد ضعیفی دارند. ما برخی از گروه‌ها را درج نمی‌کنیم زیرا نمونه‌های بسیار کمی وجود دارد، که منجر به عدم قطعیت بالاتر با دامنه‌های بازه اطمینان وسیع می‌شود.
  • تقسیمی برای نمونه های غیر سمی که به گروه اکثریت ارجاع می دهند.

مهم است که نمونه‌های کافی متعلق به طبقات ضعیف داشته باشید. بر اساس معماری مدل، توزیع داده ها و پیکربندی MinDiff، مقدار داده مورد نیاز می تواند به طور قابل توجهی متفاوت باشد. در برنامه های گذشته، ما شاهد عملکرد خوب MinDiff با 5000 نمونه در هر تقسیم داده بودیم.

در مورد ما، گروه های موجود در تقسیمات اقلیت دارای مقادیر نمونه 9688 و 3906 هستند. به عدم تعادل کلاس در مجموعه داده توجه کنید. در عمل، این می تواند باعث نگرانی شود، اما ما به دنبال پرداختن به آنها در این دفترچه نخواهیم بود زیرا قصد ما فقط نشان دادن MinDiff است.

ما فقط نمونه‌های منفی را برای این گروه‌ها انتخاب می‌کنیم تا MinDiff بتواند این نمونه‌ها را درست بهینه کند. ممکن است نظر می رسد متضاد به حک کردن مجموعه از نمونه حقیقت زمین منفی اگر ما در حال در درجه اول با نابرابری در میزان مثبت کاذب نگران، اما به یاد داشته باشید که یک پیش بینی مثبت کاذب یک مثال حقیقت زمین منفی است که به اشتباه به عنوان مثبت طبقه بندی شده است، این است که موضوع در حال تلاش برای رسیدگی است.

ایجاد MinDiff DataFrames

# Create masks for the sensitive and nonsensitive groups
minority_mask = data_train.religion.apply(
    lambda x: any(religion in x for religion in ('jewish', 'muslim')))
majority_mask = data_train.religion.apply(lambda x: x == "['christian']")

# Select nontoxic examples, so MinDiff will be able to reduce sensitive FP rate.
true_negative_mask = data_train['toxicity'] == 0

data_train_main = copy.copy(data_train)
data_train_sensitive = data_train[minority_mask & true_negative_mask]
data_train_nonsensitive = data_train[majority_mask & true_negative_mask]

همچنین برای ورودی MinDiff باید Pandas DataFrames خود را به Tensorflow Datasets تبدیل کنیم. توجه داشته باشید که برخلاف Keras model API برای Pandas DataFrames، استفاده از Datasets به این معنی است که ما باید ویژگی ها و برچسب های ورودی مدل را با هم در یک مجموعه داده ارائه کنیم. در اینجا ما شما را به 'comment_text' به عنوان یک ویژگی ورودی و تغییر شکل برچسب برای مطابقت با خروجی مورد انتظار مدل است.

ما مجموعه داده را در این مرحله نیز دسته بندی می کنیم، زیرا MinDiff به مجموعه داده های دسته بندی شده نیاز دارد. توجه داشته باشید که ما انتخاب اندازه دسته را به همان روشی که برای مدل پایه تنظیم شده تنظیم می کنیم، با در نظر گرفتن سرعت آموزش و ملاحظات سخت افزاری در حالی که با عملکرد مدل تعادل برقرار می کنیم. در اینجا ما اندازه دسته‌ای یکسان را برای هر سه مجموعه داده انتخاب کرده‌ایم، اما این یک الزام نیست، اگرچه تمرین خوبی است که دو اندازه دسته MinDiff معادل باشند.

مجموعه داده های MinDiff را ایجاد کنید

# Convert the pandas DataFrames to Datasets.
dataset_train_main = tf.data.Dataset.from_tensor_slices(
    (data_train_main['comment_text'].values, 
     data_train_main.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)
dataset_train_sensitive = tf.data.Dataset.from_tensor_slices(
    (data_train_sensitive['comment_text'].values, 
     data_train_sensitive.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)
dataset_train_nonsensitive = tf.data.Dataset.from_tensor_slices(
    (data_train_nonsensitive['comment_text'].values, 
     data_train_nonsensitive.pop(LABEL).values.reshape(-1,1) * 1.0)).batch(BATCH_SIZE)

آموزش و ارزیابی مدل

برای آموزش با MinDiff، به سادگی مدل اصلی را و قرار دادن آن در یک MinDiffModel با متناظر loss و loss_weight . ما با استفاده از 1.5 به عنوان پیش فرض loss_weight ، اما این یک پارامتر است که باید برای مورد استفاده شما تنظیم می شود، از آن بر اساس مدل و کالا مورد نیاز شما بستگی دارد. می‌توانید با تغییر مقدار آزمایش کنید تا ببینید چگونه بر مدل تأثیر می‌گذارد، توجه داشته باشید که افزایش آن عملکرد گروه‌های اقلیت و اکثریت را به هم نزدیک‌تر می‌کند، اما ممکن است با مبادلات واضح‌تری همراه باشد.

سپس مدل را به طور معمول (با استفاده از اتلاف غیر MinDiff معمولی) کامپایل می کنیم و برای آموزش مناسب می شویم.

آموزش MinDiffModel

use_pretrained_model = True

base_dir = tempfile.mkdtemp(prefix='saved_models')
min_diff_model_location = os.path.join(base_dir, 'model_export_min_diff')

if use_pretrained_model:
  BASE_MIN_DIFF_PATH = tempfile.mkdtemp()
  MIN_DIFF_URL = 'https://storage.googleapis.com/civil_comments_model/min_diff_model.zip'
  ZIP_PATH = os.path.join(BASE_PATH, 'min_diff_model.zip')
  MIN_DIFF_MODEL_PATH = os.path.join(BASE_MIN_DIFF_PATH, 'tmp/min_diff_model')
  DIRPATH = '/tmp/min_diff_model'

  r = requests.get(MIN_DIFF_URL, allow_redirects=True)
  open(ZIP_PATH, 'wb').write(r.content)

  with zipfile.ZipFile(ZIP_PATH, 'r') as zip_ref:
    zip_ref.extractall(BASE_MIN_DIFF_PATH)
  min_diff_model = tf.keras.models.load_model(
      MIN_DIFF_MODEL_PATH, custom_objects={'KerasLayer' : hub.KerasLayer})

  min_diff_model.save(min_diff_model_location, save_format='tf')

else:
  min_diff_weight = 1.5

  # Create the dataset that will be passed to the MinDiffModel during training.
  dataset = md.keras.utils.input_utils.pack_min_diff_data(
      dataset_train_main, dataset_train_sensitive, dataset_train_nonsensitive)

  # Create the original model.
  original_model = min_diff_keras_utils.create_keras_sequential_model()

  # Wrap the original model in a MinDiffModel, passing in one of the MinDiff
  # losses and using the set loss_weight.
  min_diff_loss = md.losses.MMDLoss()
  min_diff_model = md.keras.MinDiffModel(original_model,
                                         min_diff_loss,
                                         min_diff_weight)

  # Compile the model normally after wrapping the original model.  Note that
  # this means we use the baseline's model's loss here.
  optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
  loss = tf.keras.losses.BinaryCrossentropy()
  min_diff_model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])

  min_diff_model.fit(dataset, epochs=20)

  min_diff_model.save_original_model(min_diff_model_location, save_format='tf')
INFO:tensorflow:Assets written to: /tmp/saved_modelsb3zkcos_/model_export_min_diff/assets
INFO:tensorflow:Assets written to: /tmp/saved_modelsb3zkcos_/model_export_min_diff/assets

در مرحله بعد نتایج را ارزیابی می کنیم.

min_diff_eval_subdir = os.path.join(base_dir, 'tfma_eval_result')
min_diff_eval_result = fi_util.get_eval_results(
    min_diff_model_location,
    min_diff_eval_subdir,
    validate_tfrecord_file,
    slice_selection='religion')
WARNING:absl:Tensorflow version (2.5.0) found. Note that TFMA support for TF 2.0 is currently in beta

برای اطمینان از اینکه یک مدل جدید را به درستی ارزیابی می کنیم، باید یک آستانه را به همان روشی که مدل پایه انتخاب می کنیم، انتخاب کنیم. در یک محیط تولید، این به معنای اطمینان از مطابقت معیارهای ارزیابی استانداردهای راه اندازی است. در مورد ما، آستانه ای را انتخاب می کنیم که منجر به یک FPR کلی مشابه با مدل پایه می شود. این آستانه ممکن است با آستانه ای که برای مدل پایه انتخاب کرده اید متفاوت باشد. نرخ مثبت کاذب را با آستانه 0.400 انتخاب کنید. (توجه داشته باشید که زیرگروه‌هایی که نمونه‌هایی با مقدار بسیار کم دارند، فواصل اطمینان بسیار وسیعی دارند و نتایج قابل پیش‌بینی ندارند.)

widget_view.render_fairness_indicator(min_diff_eval_result)
FairnessIndicatorViewer(slicingMetrics=[{'sliceValue': 'Overall', 'slice': 'Overall', 'metrics': {'accuracy': …

با مرور این نتایج، ممکن است متوجه شوید که FPR برای گروه های هدف ما بهبود یافته است. فاصله بین گروهی که کمترین عملکرد را داشتند و گروه اکثریت از 0.024 به 0.006 بهبود یافته است. با توجه به پیشرفت هایی که مشاهده کرده ایم و ادامه عملکرد قوی برای گروه اکثریت، هر دو هدف خود را برآورده کرده ایم. بسته به محصول، ممکن است بهبودهای بیشتری لازم باشد، اما این رویکرد مدل ما را یک قدم به عملکرد عادلانه برای همه کاربران نزدیک‌تر کرده است.