مشاهده در TensorFlow.org | در Google Colab اجرا شود | در GitHub مشاهده کنید | دانلود دفترچه یادداشت | مدل TF Hub را ببینید |
در آموزش SNGP ، یاد گرفتید که چگونه مدل SNGP را بر روی یک شبکه باقیمانده عمیق بسازید تا توانایی آن را در تعیین کمیت عدم قطعیت آن بهبود بخشد. در این آموزش، SNGP را با ساختن آن بر روی یک رمزگذار BERT عمیق برای بهبود توانایی مدل NLU عمیق در تشخیص پرس و جوهای خارج از محدوده، برای یک کار درک زبان طبیعی (NLU) اعمال خواهید کرد.
به طور خاص، شما:
- BERT-SNGP، یک مدل BERT افزوده شده با SNGP را بسازید.
- مجموعه داده تشخیص هدف CLINC خارج از محدوده (OOS) را بارگیری کنید.
- مدل BERT-SNGP را آموزش دهید.
- عملکرد مدل BERT-SNGP در کالیبراسیون عدم قطعیت و تشخیص خارج از دامنه را ارزیابی کنید.
فراتر از CLINC OOS، مدل SNGP برای مجموعه داده های مقیاس بزرگ مانند تشخیص سمیت Jigsaw و مجموعه داده های تصویر مانند CIFAR-100 و ImageNet اعمال شده است. برای نتایج معیار SNGP و سایر روشهای عدم قطعیت، و همچنین اجرای با کیفیت بالا با اسکریپتهای آموزشی/ارزیابی سرتاسر، میتوانید معیار Uncertainty Baselines را بررسی کنید.
برپایی
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 را به دنبال متن طبقهبندی با آموزش BERT پیادهسازی کنید. ما از رمزگذار BERT-base و ClassificationHead
داخلی به عنوان طبقهبندی کننده استفاده خواهیم کرد.
مدل استاندارد BERT
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)
ساخت مدل SNGP
برای پیاده سازی یک مدل BERT-SNGP، فقط باید ClassificationHead
را با GaussianProcessClassificationHead
داخلی جایگزین کنید. نرمال سازی طیفی از قبل در این سر طبقه بندی بسته بندی شده است. مانند آموزش SNGP ، یک بازخوانی مجدد کوواریانس به مدل اضافه کنید، بنابراین مدل به طور خودکار تخمینگر کوواریانس را در ابتدای یک دوره جدید بازنشانی میکند تا از دوبار شمارش دادههای مشابه جلوگیری شود.
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 را بارگیری کنید. این مجموعه داده شامل 15000 پرسش گفتاری کاربر است که بیش از 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 را به عنوان \(1 - p(x)\)محاسبه می کند، که در آن \(p(x)=softmax(logit(x))\) احتمال پیش بینی است.
sngp_probs, ood_labels = oos_predict(sngp_model, ood_eval_dataset)
ood_probs = 1 - sngp_probs
حال ارزیابی کنید که نمره عدم قطعیت مدل ood_probs
چقدر خوب برچسب خارج از دامنه را پیش بینی می کند. ابتدا ناحیه تحت منحنی فراخوان دقیق (AUPRC) را برای احتمال OOD در مقابل دقت تشخیص OOD محاسبه کنید.
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
این با عملکرد SNGP گزارش شده در معیار CLINC OOS تحت خطوط پایه عدم قطعیت مطابقت دارد.
سپس، کیفیت مدل را در کالیبراسیون عدم قطعیت بررسی کنید، یعنی اینکه آیا احتمال پیشبینی مدل با دقت پیشبینی آن مطابقت دارد یا خیر. یک مدل خوب کالیبره شده قابل اعتماد در نظر گرفته می شود، زیرا، برای مثال، احتمال پیش بینی آن \(p(x)=0.8\) به این معنی است که مدل در 80٪ مواقع درست است.
prob_true, prob_pred = sklearn.calibration.calibration_curve(
ood_labels, ood_probs, n_bins=10, strategy='quantile')
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()
منابع و مطالعه بیشتر
- برای مطالعه دقیق پیاده سازی SNGP از ابتدا به آموزش SNGP مراجعه کنید.
- برای اجرای مدل SNGP (و بسیاری از روشهای عدم قطعیت دیگر) در طیف گستردهای از مجموعه دادههای معیار (مانند CIFAR ، ImageNet ، تشخیص سمیت Jigsaw ، و غیره) به خطوط پایه عدم قطعیت مراجعه کنید.
- برای درک عمیقتر روش SNGP، مقاله برآورد عدم قطعیت ساده و اصولی با یادگیری عمیق قطعی از طریق آگاهی از راه دور را بررسی کنید.