Model İyileştirme Vaka Çalışması

Bu not defterinde, toksik veya zararlı olarak kabul edilebilecek yazılı içeriği belirlemek için bir metin sınıflandırıcı eğiteceğiz ve bazı adalet endişelerini gidermek için MinDiff uygulayacağız. İş akışımızda şunları yapacağız:

  1. Temel modelimizin, hassas gruplara referanslar içeren metin üzerindeki performansını değerlendirin.
  2. MinDiff ile antrenman yaparak düşük performans gösteren gruplarda performansı artırın.
  3. Yeni modelin performansını seçtiğimiz metriğe göre değerlendirin.

Amacımız, makine öğreniminde adilliğe ilkeli bir yaklaşım ortaya koymak değil, MinDiff tekniğinin kullanımını çok minimal bir iş akışıyla göstermektir. Bu nedenle, değerlendirmemiz yalnızca bir hassas kategoriye ve tek bir metriğe odaklanacaktır. Ayrıca veri setindeki olası eksiklikleri ele almıyor veya konfigürasyonlarımızı ayarlamıyoruz. Bir üretim ortamında, bunların her birine titizlikle yaklaşmak istersiniz. Adalet için değerlendirilmesi konusunda daha fazla bilgi için bkz bu kılavuzu .

Kurmak

Adalet Göstergelerini ve TensorFlow Model İyileştirmesini yükleyerek başlıyoruz.

Yüklemeler

Değerlendirme için MinDiff ve Adalet Göstergeleri dahil tüm gerekli bileşenleri içe aktarın.

ithalat

Önceden işlenmiş verileri indirmek ve etiketleri modelin çıktı şekline uyacak şekilde hazırlamak için bir yardımcı fonksiyon kullanıyoruz. İşlev ayrıca daha sonraki değerlendirmeyi daha hızlı hale getirmek için verileri TFRecords olarak indirir. Alternatif olarak, mevcut herhangi bir yardımcı program dönüştürme işleviyle Pandas DataFrame'i TFRecords'a dönüştürebilirsiniz.

# 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

Birkaç faydalı sabit tanımladık. Biz üzerine modelini eğitecek 'comment_text' olarak hedefimiz etiket ile, özellik 'toxicity' . Buradaki parti boyutunun isteğe bağlı olarak seçildiğini, ancak bir üretim ayarında en iyi performans için ayarlamanız gerektiğini unutmayın.

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

Rastgele tohumlar ayarlayın. (Bunun sonuçları tam olarak stabilize etmediğini unutmayın.)

tohumlar

Temel modeli tanımlayın ve eğitin

Çalışma süresini azaltmak için varsayılan olarak önceden eğitilmiş bir model kullanıyoruz. Bir toksisite tahmini veren, ilk gömme ve evrişim katmanlarına sahip basit bir Keras sıralı modelidir. İsterseniz, bunu değiştirebilir ve modeli oluşturmak için yardımcı işlevimizi kullanarak sıfırdan eğitebilirsiniz. (Ortamınız muhtemelen bizimkinden farklı olduğundan, ayarlama ve değerlendirme eşiklerini özelleştirmeniz gerekeceğini unutmayın.)

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)

Biz kullanarak değerlendirmek için bir model kaydetmek Adil Göstergeleri .

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

Ardından Adalet Göstergelerini çalıştırıyoruz. Bir hatırlatma olarak, biz sadece bir kategoriyi, dini gruplar başvuran yorumlar için dilimlenmiş değerlendirmesini gerçekleştirmek için gidiyoruz. Bir üretim ortamında, hangi kategorilerin ve metriklerin değerlendirileceğini belirlemek için dikkatli bir yaklaşım benimsemenizi öneririz.

Model performansını hesaplamak için, yardımcı program işlevi metrikler, dilimler ve sınıflandırıcı eşikleri için birkaç uygun seçim yapar.

# 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)`

Render Değerlendirme Sonuçları

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

Değerlendirme sonuçlarına bakalım. 0,450 eşiğiyle metrik yanlış pozitif oranı (FPR) seçmeyi deneyin. Modelin bazı dini gruplar için diğerleri kadar iyi performans göstermediğini ve çok daha yüksek bir FPR gösterdiğini görebiliriz. Çok az örneğe sahip oldukları için bazı gruplardaki geniş güven aralıklarına dikkat edin. Bu, bu dilimler için performansta önemli bir fark olduğunu kesin olarak söylemeyi zorlaştırıyor. Bu sorunu çözmek için daha fazla örnek toplamak isteyebiliriz. Ancak, düşük performans gösterdiğinden emin olduğumuz iki grup için MinDiff'i uygulamaya çalışabiliriz.

FPR'ye odaklanmayı seçtik, çünkü daha yüksek bir FPR, bu kimlik gruplarına atıfta bulunan yorumların diğer yorumlardan daha yanlış bir şekilde toksik olarak işaretlenmesi anlamına gelir. Bu, din hakkında diyalog kuran kullanıcılar için adaletsiz sonuçlara yol açabilir, ancak diğer ölçütlerdeki farklılıkların başka tür zararlara yol açabileceğini unutmayın.

MinDiff Modelini Tanımlayın ve Eğitin

Şimdi, düşük performans gösteren dini gruplar için FPR'yi iyileştirmeye çalışacağız. Biz kullanarak bunu deneriz MinDiff , eğitim sırasında performansta farklılıkları cezalandırarak verilerinizin dilimleri boyunca hata oranlarını dengelemek için çalışan bir düzeltme tekniği. MinDiff uyguladığımızda, model performansı diğer dilimlerde biraz düşebilir. Bu nedenle, MinDiff ile hedeflerimiz şunlar olacaktır:

  • Düşük performans gösteren gruplar için iyileştirilmiş performans
  • Diğer gruplar ve genel performans için sınırlı bozulma

Verilerinizi hazırlayın

MinDiff'i kullanmak için iki ek veri bölümü oluşturuyoruz:

  • Azınlık gruplarına atıfta bulunan toksik olmayan örnekler için bir ayrım: Bizim durumumuzda bu, düşük performans gösteren kimlik terimlerimize atıfta bulunan yorumları içerecektir. Bazı grupları dahil etmiyoruz çünkü çok az örnek var ve bu da geniş güven aralığı aralıklarıyla daha yüksek belirsizliğe yol açıyor.
  • Çoğunluk grubuna atıfta bulunan toksik olmayan örnekler için bir ayrım.

Düşük performans gösteren sınıflara ait yeterli örneğe sahip olmak önemlidir. Model mimarinize, veri dağıtımınıza ve MinDiff yapılandırmanıza bağlı olarak, gereken veri miktarı önemli ölçüde değişebilir. Geçmiş uygulamalarda, MinDiff'in her veri bölümünde 5.000 örnekle iyi çalıştığını gördük.

Bizim durumumuzda azınlık bölüşümlerindeki grupların örnek miktarları 9,688 ve 3,906'dır. Veri kümesindeki sınıf dengesizliklerine dikkat edin; pratikte, bu endişe kaynağı olabilir, ancak niyetimiz sadece MinDiff'i göstermek olduğundan, bu defterde bunlara değinmeye çalışmayacağız.

Bu gruplar için yalnızca olumsuz örnekleri seçiyoruz, böylece MinDiff bu örnekleri doğru bir şekilde elde etmeyi optimize edebilir. Biz öncelikle yanlış pozitif oranındaki eşitsizlikler ile ilgili eğer zemin gerçeği negatif örneklerin setleri ayırırlar ama yanlış pozitif öngörü sorunu biz hangi yanlış pozitifliği olarak sınıflandırıldığı bir zemin gerçeği negatif örnek olduğunu hatırlamak mantığa aykırı gibi görünebilir hitap etmeye çalışıyoruz.

MinDiff Veri Çerçeveleri Oluşturun

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

Ayrıca Pandas DataFrame'lerimizi MinDiff girişi için Tensorflow Veri Kümelerine dönüştürmemiz gerekiyor. Pandas DataFrames için Keras model API'sinden farklı olarak, Veri Kümeleri kullanmanın, modelin giriş özelliklerini ve etiketlerini tek bir Veri Kümesinde birlikte sağlamamız gerektiği anlamına geldiğini unutmayın. Burada verdiğimiz 'comment_text' bir giriş özelliği olarak ve modelin beklenen çıkışını maç için etiket yeniden şekillendirmek.

MinDiff toplu Veri Kümeleri gerektirdiğinden, Veri Kümesini bu aşamada da topluyoruz. Model performansı ile dengelerken eğitim hızı ve donanım hususlarını hesaba katarak, parti boyutu seçimini temel model için ayarlandığı şekilde ayarladığımızı unutmayın. Burada, üç veri kümesinin tümü için aynı parti boyutunu seçtik, ancak bu bir gereklilik değildir, ancak iki MinDiff toplu boyutunun eşdeğer olması iyi bir uygulamadır.

MinDiff Veri Kümeleri Oluşturun

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

Modeli eğitin ve değerlendirin

MinDiff ile yetiştirmek için, sadece orijinal modeli alıp karşılık gelen bir MinDiffModel alanına kaydırmak loss ve loss_weight . Biz varsayılan olarak 1.5 kullanıyorsanız loss_weight , ancak modeliniz ve ürün şartlarına bağlı olduğundan bu, sizin kullanım durumu için ayarlanmış gereken bir parametredir. Modeli nasıl etkilediğini görmek için değeri değiştirmeyi deneyebilir, artırmanın azınlık ve çoğunluk gruplarının performansını birbirine yaklaştırdığını ancak daha belirgin ödünleşimlerle gelebileceğini unutmayın.

Daha sonra modeli normal olarak derleriz (normal MinDiff olmayan kaybı kullanarak) ve eğitime uygun hale getiririz.

Tren 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

Sonra sonuçları değerlendiririz.

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

Yeni bir modeli doğru bir şekilde değerlendirdiğimizden emin olmak için, temel modelde yaptığımız gibi bir eşik seçmemiz gerekir. Bir üretim ortamında bu, değerlendirme metriklerinin lansman standartlarını karşılamasını sağlamak anlamına gelir. Bizim durumumuzda, temel modele benzer bir genel FPR ile sonuçlanan eşiği seçeceğiz. Bu eşik, temel model için seçtiğinizden farklı olabilir. 0.400 eşiği ile yanlış pozitif oranı seçmeyi deneyin. (Çok düşük miktarda örnek içeren alt grupların çok geniş güven aralığı aralıklarına sahip olduğuna ve tahmin edilebilir sonuçlara sahip olmadığına dikkat edin.)

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

Bu sonuçları gözden geçirerek, hedef gruplarımız için FPR'lerin iyileştiğini fark edebilirsiniz. En düşük performans gösteren grubumuz ile çoğunluk grubu arasındaki fark .024'ten .006'ya yükseldi. Gözlemlediğimiz iyileştirmeler ve çoğunluk grubu için devam eden güçlü performans göz önüne alındığında, her iki hedefimize de ulaştık. Ürüne bağlı olarak daha fazla iyileştirme gerekli olabilir, ancak bu yaklaşım modelimizi tüm kullanıcılar için eşit performans göstermeye bir adım daha yaklaştırdı.