BERT-SNGP के साथ अनिश्चितता-जागरूक गहरी भाषा सीखना

एसएनजीपी ट्यूटोरियल में, आपने सीखा कि एक गहरे अवशिष्ट नेटवर्क के शीर्ष पर एसएनजीपी मॉडल कैसे बनाया जाए ताकि इसकी अनिश्चितता को मापने की क्षमता में सुधार हो सके। इस ट्यूटोरियल में, आप एसएनजीपी को एक प्राकृतिक भाषा समझ (एनएलयू) कार्य के लिए एक गहरे बीईआरटी एन्कोडर के शीर्ष पर बनाकर लागू करेंगे ताकि आउट-ऑफ-स्कोप प्रश्नों का पता लगाने में एनएलयू मॉडल की क्षमता में सुधार हो सके।

विशेष रूप से, आप करेंगे:

  • BERT-SNGP, एक SNGP-संवर्धित BERT मॉडल बनाएँ।
  • CLINC आउट-ऑफ-स्कोप (OOS) इंटेंट डिटेक्शन डेटासेट लोड करें।
  • BERT-SNGP मॉडल को प्रशिक्षित करें।
  • अनिश्चितता अंशांकन और आउट-ऑफ-डोमेन डिटेक्शन में BERT-SNGP मॉडल के प्रदर्शन का मूल्यांकन करें।

CLINC OOS से परे, SNGP मॉडल को बड़े पैमाने के डेटासेट जैसे आरा विषाक्तता का पता लगाने , और छवि डेटासेट जैसे CIFAR-100 और ImageNet पर लागू किया गया है। एसएनजीपी और अन्य अनिश्चितता के तरीकों के बेंचमार्क परिणामों के साथ-साथ एंड-टू-एंड प्रशिक्षण/मूल्यांकन स्क्रिप्ट के साथ उच्च गुणवत्ता वाले कार्यान्वयन के लिए, आप अनिश्चितता बेसलाइन बेंचमार्क देख सकते हैं।

सेट अप

pip uninstall -y tensorflow tf-text
pip install -U tensorflow-text-nightly
pip install -U tf-nightly
pip install -U tf-models-nightly
import matplotlib.pyplot as plt

import sklearn.metrics
import sklearn.calibration

import tensorflow_hub as hub
import tensorflow_datasets as tfds

import numpy as np
import tensorflow as tf

import official.nlp.modeling.layers as layers
import official.nlp.optimization as optimization
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_addons/utils/ensure_tf_install.py:43: UserWarning: You are currently using a nightly version of TensorFlow (2.9.0-dev20220203). 
TensorFlow Addons offers no support for the nightly versions of TensorFlow. Some things might work, some other might not. 
If you encounter a bug, do not file an issue on GitHub.
  UserWarning,

इस ट्यूटोरियल को कुशलतापूर्वक चलाने के लिए GPU की आवश्यकता है। जांचें कि क्या GPU उपलब्ध है।

tf.__version__
'2.9.0-dev20220203'
gpus = tf.config.list_physical_devices('GPU')
gpus
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
assert gpus, """
  No GPU(s) found! This tutorial will take many hours to run without a GPU.

  You may hit this error if the installed tensorflow package is not
  compatible with the CUDA and CUDNN versions."""

पहले बीईआरटी ट्यूटोरियल के साथ क्लासिफाई टेक्स्ट के बाद एक मानक बीईआरटी क्लासिफायरियर लागू करें। हम क्लासिफायर के रूप में BERT-बेस एनकोडर और बिल्ट-इन ClassificationHead का उपयोग करेंगे।

मानक बीईआरटी मॉडल

PREPROCESS_HANDLE = 'https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3'
MODEL_HANDLE
= 'https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/3'

class BertClassifier(tf.keras.Model):
 
def __init__(self,
               num_classes
=150, inner_dim=768, dropout_rate=0.1,
               
**classifier_kwargs):

   
super().__init__()
   
self.classifier_kwargs = classifier_kwargs

   
# Initiate the BERT encoder components.
   
self.bert_preprocessor = hub.KerasLayer(PREPROCESS_HANDLE, name='preprocessing')
   
self.bert_hidden_layer = hub.KerasLayer(MODEL_HANDLE, trainable=True, name='bert_encoder')

   
# Defines the encoder and classification layers.
   
self.bert_encoder = self.make_bert_encoder()
   
self.classifier = self.make_classification_head(num_classes, inner_dim, dropout_rate)

 
def make_bert_encoder(self):
    text_inputs
= tf.keras.layers.Input(shape=(), dtype=tf.string, name='text')
    encoder_inputs
= self.bert_preprocessor(text_inputs)
    encoder_outputs
= self.bert_hidden_layer(encoder_inputs)
   
return tf.keras.Model(text_inputs, encoder_outputs)

 
def make_classification_head(self, num_classes, inner_dim, dropout_rate):
   
return layers.ClassificationHead(
        num_classes
=num_classes,
        inner_dim
=inner_dim,
        dropout_rate
=dropout_rate,
       
**self.classifier_kwargs)

 
def call(self, inputs, **kwargs):
    encoder_outputs
= self.bert_encoder(inputs)
    classifier_inputs
= encoder_outputs['sequence_output']
   
return self.classifier(classifier_inputs, **kwargs)

एसएनजीपी मॉडल बनाएं

BERT-SNGP मॉडल को लागू करने के लिए, आपको केवल ClassificationHead को बिल्ट-इन GaussianProcessClassificationHead से बदलना होगा। वर्णक्रमीय सामान्यीकरण पहले से ही इस वर्गीकरण शीर्ष में पूर्व-पैक किया गया है। एसएनजीपी ट्यूटोरियल की तरह, मॉडल में एक कॉन्वर्सिस रीसेट कॉलबैक जोड़ें, इसलिए मॉडल एक ही डेटा को दो बार गिनने से बचने के लिए एक नए युग की शुरुआत में स्वचालित रूप से कॉन्वर्सिस अनुमानक को रीसेट कर देता है।

class ResetCovarianceCallback(tf.keras.callbacks.Callback):

 
def on_epoch_begin(self, epoch, logs=None):
   
"""Resets covariance matrix at the begining of the epoch."""
   
if epoch > 0:
     
self.model.classifier.reset_covariance_matrix()
class SNGPBertClassifier(BertClassifier):

 
def make_classification_head(self, num_classes, inner_dim, dropout_rate):
   
return layers.GaussianProcessClassificationHead(
        num_classes
=num_classes,
        inner_dim
=inner_dim,
        dropout_rate
=dropout_rate,
        gp_cov_momentum
=-1,
        temperature
=30.,
       
**self.classifier_kwargs)

 
def fit(self, *args, **kwargs):
   
"""Adds ResetCovarianceCallback to model callbacks."""
    kwargs
['callbacks'] = list(kwargs.get('callbacks', []))
    kwargs
['callbacks'].append(ResetCovarianceCallback())

   
return super().fit(*args, **kwargs)

CLINC OOS डेटासेट लोड करें

अब CLINC OOS इंटेंट डिटेक्शन डेटासेट लोड करें। इस डेटासेट में 150,000 उपयोगकर्ता की बोली जाने वाली क्वेरीज़ 150 से अधिक इंटेंट क्लासेस में एकत्र की गई हैं, इसमें 1000 आउट-ऑफ-डोमेन (OOD) वाक्य भी शामिल हैं जो किसी भी ज्ञात वर्ग द्वारा कवर नहीं किए गए हैं।

(clinc_train, clinc_test, clinc_test_oos), ds_info = tfds.load(
   
'clinc_oos', split=['train', 'test', 'test_oos'], with_info=True, batch_size=-1)

ट्रेन बनाएं और डेटा का परीक्षण करें।

train_examples = clinc_train['text']
train_labels
= clinc_train['intent']

# Makes the in-domain (IND) evaluation data.
ind_eval_data
= (clinc_test['text'], clinc_test['intent'])

एक OOD मूल्यांकन डेटासेट बनाएँ। इसके लिए, इन-डोमेन परीक्षण डेटा clinc_test और आउट-ऑफ़-डोमेन डेटा clinc_test_oos को संयोजित करें। हम इन-डोमेन उदाहरणों के लिए लेबल 0 और आउट-ऑफ-डोमेन उदाहरणों को लेबल 1 भी निर्दिष्ट करेंगे।

test_data_size = ds_info.splits['test'].num_examples
oos_data_size
= ds_info.splits['test_oos'].num_examples

# Combines the in-domain and out-of-domain test examples.
oos_texts
= tf.concat([clinc_test['text'], clinc_test_oos['text']], axis=0)
oos_labels
= tf.constant([0] * test_data_size + [1] * oos_data_size)

# Converts into a TF dataset.
ood_eval_dataset
= tf.data.Dataset.from_tensor_slices(
   
{"text": oos_texts, "label": oos_labels})

ट्रेन और मूल्यांकन

पहले बुनियादी प्रशिक्षण विन्यास स्थापित करें।

TRAIN_EPOCHS = 3
TRAIN_BATCH_SIZE
= 32
EVAL_BATCH_SIZE
= 256

def bert_optimizer(learning_rate, 
                   batch_size
=TRAIN_BATCH_SIZE, epochs=TRAIN_EPOCHS,
                   warmup_rate
=0.1):
 
"""Creates an AdamWeightDecay optimizer with learning rate schedule."""
  train_data_size
= ds_info.splits['train'].num_examples

  steps_per_epoch
= int(train_data_size / batch_size)
  num_train_steps
= steps_per_epoch * epochs
  num_warmup_steps
= int(warmup_rate * num_train_steps)  

 
# Creates learning schedule.
  lr_schedule
= tf.keras.optimizers.schedules.PolynomialDecay(
      initial_learning_rate
=learning_rate,
      decay_steps
=num_train_steps,
      end_learning_rate
=0.0)  

 
return optimization.AdamWeightDecay(
      learning_rate
=lr_schedule,
      weight_decay_rate
=0.01,
      epsilon
=1e-6,
      exclude_from_weight_decay
=['LayerNorm', 'layer_norm', 'bias'])

optimizer = bert_optimizer(learning_rate=1e-4)
loss
= tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
metrics
= tf.metrics.SparseCategoricalAccuracy()
fit_configs = dict(batch_size=TRAIN_BATCH_SIZE,
                   epochs
=TRAIN_EPOCHS,
                   validation_batch_size
=EVAL_BATCH_SIZE,
                   validation_data
=ind_eval_data)
sngp_model = SNGPBertClassifier()
sngp_model
.compile(optimizer=optimizer, loss=loss, metrics=metrics)
sngp_model
.fit(train_examples, train_labels, **fit_configs)
Epoch 1/3
469/469 [==============================] - 219s 427ms/step - loss: 1.0725 - sparse_categorical_accuracy: 0.7870 - val_loss: 0.4358 - val_sparse_categorical_accuracy: 0.9380
Epoch 2/3
469/469 [==============================] - 198s 422ms/step - loss: 0.0885 - sparse_categorical_accuracy: 0.9797 - val_loss: 0.2424 - val_sparse_categorical_accuracy: 0.9518
Epoch 3/3
469/469 [==============================] - 199s 424ms/step - loss: 0.0259 - sparse_categorical_accuracy: 0.9951 - val_loss: 0.1927 - val_sparse_categorical_accuracy: 0.9642
<keras.callbacks.History at 0x7fe24c0a7090>

OOD प्रदर्शन का मूल्यांकन करें

मूल्यांकन करें कि मॉडल कितनी अच्छी तरह अपरिचित आउट-ऑफ-डोमेन प्रश्नों का पता लगा सकता है। कठोर मूल्यांकन के लिए, पहले निर्मित OOD मूल्यांकन डेटासेट ood_eval_dataset का उपयोग करें।

def oos_predict(model, ood_eval_dataset, **model_kwargs):
  oos_labels
= []
  oos_probs
= []

  ood_eval_dataset
= ood_eval_dataset.batch(EVAL_BATCH_SIZE)
 
for oos_batch in ood_eval_dataset:
    oos_text_batch
= oos_batch["text"]
    oos_label_batch
= oos_batch["label"]

    pred_logits
= model(oos_text_batch, **model_kwargs)
    pred_probs_all
= tf.nn.softmax(pred_logits, axis=-1)
    pred_probs
= tf.reduce_max(pred_probs_all, axis=-1)

    oos_labels
.append(oos_label_batch)
    oos_probs
.append(pred_probs)

  oos_probs
= tf.concat(oos_probs, axis=0)
  oos_labels
= tf.concat(oos_labels, axis=0)

 
return oos_probs, oos_labels

OOD संभावनाओं की गणना 1p(x)रूप में करता है, जहां p(x)=softmax(logit(x)) भविष्य कहनेवाला संभावना है।

sngp_probs, ood_labels = oos_predict(sngp_model, ood_eval_dataset)
ood_probs = 1 - sngp_probs

अब मूल्यांकन करें कि मॉडल का अनिश्चितता स्कोर ood_probs आउट-ऑफ़-डोमेन लेबल की कितनी अच्छी तरह भविष्यवाणी करता है। पहले OOD प्रायिकता बनाम OOD डिटेक्शन सटीकता के लिए सटीक-रिकॉल कर्व (AUPRC) के तहत क्षेत्र की गणना करें।

precision, recall, _ = sklearn.metrics.precision_recall_curve(ood_labels, ood_probs)
auprc = sklearn.metrics.auc(recall, precision)
print(f'SNGP AUPRC: {auprc:.4f}')
SNGP AUPRC: 0.9039

यह अनिश्चितता बेसलाइन के तहत CLINC OOS बेंचमार्क पर रिपोर्ट किए गए SNGP प्रदर्शन से मेल खाता है।

इसके बाद, अनिश्चितता अंशांकन में मॉडल की गुणवत्ता की जांच करें, अर्थात, क्या मॉडल की भविष्य कहनेवाला संभावना इसकी भविष्य कहनेवाला सटीकता से मेल खाती है। एक अच्छी तरह से कैलिब्रेटेड मॉडल को भरोसेमंद माना जाता है, उदाहरण के लिए, इसकी भविष्य कहनेवाला संभावना p(x)=0.8 का मतलब है कि मॉडल 80% समय सही है।

prob_true, prob_pred = sklearn.calibration.calibration_curve(
    ood_labels
, ood_probs, n_bins=10, strategy='quantile')
34 एल10एन-प्लेसहोल्डर
plt.plot(prob_pred, prob_true)

plt
.plot([0., 1.], [0., 1.], c='k', linestyle="--")
plt
.xlabel('Predictive Probability')
plt
.ylabel('Predictive Accuracy')
plt
.title('Calibration Plots, SNGP')

plt
.show()

पीएनजी

संसाधन और आगे पढ़ना