Google I/O bir tamamlamadır! TensorFlow oturumlarını takip edin Oturumları görüntüleyin

BERT modeline ince ayar yapma

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Not defterini indir TF Hub modeline bakın

Bu örnekte, tensorflow-models PIP paketini kullanarak bir BERT modelinin ince ayarını yapacağız.

Bu öğretici dayanmaktadır pretrained Bert modeli de mevcuttur TensorFlow Hub o başvurmak nasıl kullanılacağını görmek için, Hub Ek

Kurmak

TensorFlow Model Garden pip paketini kurun

  • tf-models-official istikrarlı Modeli Bahçe paketidir. Not o son değişiklikleri de olmayabilir tensorflow_models github repo. Son değişiklikleri dahil etmek için yükleyebilir tf-models-nightly günlük otomatik olarak oluşturulur gece Modeli Bahçe paketi olan.
  • pip, tüm modelleri ve bağımlılıkları otomatik olarak kuracaktır.
pip install -q -U tensorflow-text
pip install -q tf-models-official==2.4.0

ithalat

import os

import numpy as np
import matplotlib.pyplot as plt

import tensorflow as tf

import tensorflow_hub as hub
import tensorflow_datasets as tfds
tfds.disable_progress_bar()

from official.modeling import tf_utils
from official import nlp
from official.nlp import bert

# Load the required submodules
import official.nlp.optimization
import official.nlp.bert.bert_models
import official.nlp.bert.configs
import official.nlp.bert.run_classifier
import official.nlp.bert.tokenization
import official.nlp.data.classifier_data_lib
import official.nlp.modeling.losses
import official.nlp.modeling.models
import official.nlp.modeling.networks
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/pkg_resources/__init__.py:119: PkgResourcesDeprecationWarning: 0.18ubuntu0.18.04.1 is an invalid version and will not be supported in a future release
  PkgResourcesDeprecationWarning,

Kaynaklar

Bu dizin, bu öğreticide kullanılan yapılandırmayı, kelimeleri ve önceden eğitilmiş bir kontrol noktasını içerir:

gs_folder_bert = "gs://cloud-tpu-checkpoints/bert/v3/uncased_L-12_H-768_A-12"
tf.io.gfile.listdir(gs_folder_bert)
['bert_config.json',
 'bert_model.ckpt.data-00000-of-00001',
 'bert_model.ckpt.index',
 'vocab.txt']

Sen bir ön eğitimli Bert kodlayıcı alabilirsiniz TensorFlow Hub :

hub_url_bert = "https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/3"

Veri

Bu örnek için kullandığımız TFDS dan TUTKAL MRPC veri kümesi .

Bu veri seti, doğrudan BERT modeline beslenecek şekilde ayarlanmamıştır, dolayısıyla bu bölüm ayrıca gerekli ön işlemeyi de ele alır.

TensorFlow Veri Kümelerinden veri kümesini alın

Microsoft Research Paraphrase Corpus (Dolan & Brockett, 2005), çiftteki cümlelerin anlamsal olarak eşdeğer olup olmadığına dair insan açıklamalarıyla birlikte, çevrimiçi haber kaynaklarından otomatik olarak çıkarılan bir cümle çiftleri topluluğudur.

  • Etiket sayısı: 2.
  • Eğitim veri kümesinin boyutu: 3668.
  • Değerlendirme veri kümesinin boyutu: 408.
  • Eğitim ve değerlendirme veri setinin maksimum dizi uzunluğu: 128.
glue, info = tfds.load('glue/mrpc', with_info=True,
                       # It's small, load the whole dataset
                       batch_size=-1)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_datasets/core/dataset_builder.py:622: get_single_element (from tensorflow.python.data.experimental.ops.get_single_element) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.data.Dataset.get_single_element()`.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_datasets/core/dataset_builder.py:622: get_single_element (from tensorflow.python.data.experimental.ops.get_single_element) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.data.Dataset.get_single_element()`.
list(glue.keys())
['train', 'validation', 'test']

info nesnesi veri kümesini açıklar ve özellikleri şunlardır:

info.features
FeaturesDict({
    'idx': tf.int32,
    'label': ClassLabel(shape=(), dtype=tf.int64, num_classes=2),
    'sentence1': Text(shape=(), dtype=tf.string),
    'sentence2': Text(shape=(), dtype=tf.string),
})

İki sınıf şunlardır:

info.features['label'].names
['not_equivalent', 'equivalent']

İşte eğitim setinden bir örnek:

glue_train = glue['train']

for key, value in glue_train.items():
  print(f"{key:9s}: {value[0].numpy()}")
idx      : 1680
label    : 0
sentence1: b'The identical rovers will act as robotic geologists , searching for evidence of past water .'
sentence2: b'The rovers act as robotic geologists , moving on six wheels .'

BERT belirteci

Önceden eğitilmiş bir modelde ince ayar yapmak için eğitim sırasında kullandığınızla tam olarak aynı simgeleştirme, sözcük bilgisi ve dizin eşlemeyi kullandığınızdan emin olmanız gerekir.

Bu eğitimde kullanılan BERT belirteci saf Python ile yazılmıştır (TensorFlow operasyonlarından oluşturulmamıştır). Sen de hemen yanı modeliniz takın olamaz keras.layer size yapabileceğiniz gibi preprocessing.TextVectorization .

Aşağıdaki kod, temel model tarafından kullanılan belirteci yeniden oluşturur:

# Set up tokenizer to generate Tensorflow dataset
tokenizer = bert.tokenization.FullTokenizer(
    vocab_file=os.path.join(gs_folder_bert, "vocab.txt"),
     do_lower_case=True)

print("Vocab size:", len(tokenizer.vocab))
Vocab size: 30522

Bir cümleyi tokenize edin:

tokens = tokenizer.tokenize("Hello TensorFlow!")
print(tokens)
ids = tokenizer.convert_tokens_to_ids(tokens)
print(ids)
['hello', 'tensor', '##flow', '!']
[7592, 23435, 12314, 999]

Verileri önceden işleyin

Bölüm, veri kümesini model tarafından beklenen formatta manuel olarak ön işleme tabi tuttu.

Bu veri kümesi küçüktür, bu nedenle ön işleme, bellekte hızlı ve kolay bir şekilde yapılabilir. Daha büyük veri kümeleri için tf_models kütüphane ön işlenmesi ve veri kümesi yeniden serializing bazı araçlar içerir. Bkz Ek: Büyük bir veri kümesini yeniden kodlama detaylar için.

Cümleleri kodla

Model, iki girdi cümlesinin birlikte birleştirilmesini bekler. Bu giriş, bir başlangıç için beklenen [CLS] belirteç "Bu sınıflandırma sorun" ve her bir cümle bir sona ermelidir [SEP] "Ayırıcı" belirteç:

tokenizer.convert_tokens_to_ids(['[CLS]', '[SEP]'])
[101, 102]

Bir ekleme yaparken bütün cümleleri kodlayan başlayın [SEP] belirteci ve dağınık-tensörlerle içine ambalaj:

def encode_sentence(s):
   tokens = list(tokenizer.tokenize(s.numpy()))
   tokens.append('[SEP]')
   return tokenizer.convert_tokens_to_ids(tokens)

sentence1 = tf.ragged.constant([
    encode_sentence(s) for s in glue_train["sentence1"]])
sentence2 = tf.ragged.constant([
    encode_sentence(s) for s in glue_train["sentence2"]])
print("Sentence1 shape:", sentence1.shape.as_list())
print("Sentence2 shape:", sentence2.shape.as_list())
Sentence1 shape: [3668, None]
Sentence2 shape: [3668, None]

Şimdi öne eklemek [CLS] belirteci ve tek oluşturmak üzere düzensiz tansörlerine bağlamak input_word_ids her örnek için tensörü. RaggedTensor.to_tensor() en uzun sekansına sıfır pedleri.

cls = [tokenizer.convert_tokens_to_ids(['[CLS]'])]*sentence1.shape[0]
input_word_ids = tf.concat([cls, sentence1, sentence2], axis=-1)
_ = plt.pcolormesh(input_word_ids.to_tensor())

png

Maske ve giriş tipi

Model iki ek girdi beklemektedir:

  • giriş maskesi
  • giriş türü

Maske, modelin içerik ve dolgu arasında net bir şekilde ayrım yapmasını sağlar. Maske ile aynı şekle sahip input_word_ids ve içerdiği 1 hiçbir yerinde input_word_ids doldurma değil.

input_mask = tf.ones_like(input_word_ids).to_tensor()

plt.pcolormesh(input_mask)
<matplotlib.collections.QuadMesh at 0x7fa22c0ecc50>

png

"Giriş tipi" de aynı şekle sahiptir, ancak dolu olmayan bölge içinde, bir içeren 0 ya da 1 belirteci bir parçası olan cümle göstermektedir.

type_cls = tf.zeros_like(cls)
type_s1 = tf.zeros_like(sentence1)
type_s2 = tf.ones_like(sentence2)
input_type_ids = tf.concat([type_cls, type_s1, type_s2], axis=-1).to_tensor()

plt.pcolormesh(input_type_ids)
<matplotlib.collections.QuadMesh at 0x7fa1cc682490>

png

Hepsini bir araya getirmek

Tek bir işlevi yukarıdaki metin ayrıştırma kodu toplamak ve her bölme için geçerlidir glue/mrpc veri seti.

def encode_sentence(s, tokenizer):
   tokens = list(tokenizer.tokenize(s))
   tokens.append('[SEP]')
   return tokenizer.convert_tokens_to_ids(tokens)

def bert_encode(glue_dict, tokenizer):
  num_examples = len(glue_dict["sentence1"])

  sentence1 = tf.ragged.constant([
      encode_sentence(s, tokenizer)
      for s in np.array(glue_dict["sentence1"])])
  sentence2 = tf.ragged.constant([
      encode_sentence(s, tokenizer)
       for s in np.array(glue_dict["sentence2"])])

  cls = [tokenizer.convert_tokens_to_ids(['[CLS]'])]*sentence1.shape[0]
  input_word_ids = tf.concat([cls, sentence1, sentence2], axis=-1)

  input_mask = tf.ones_like(input_word_ids).to_tensor()

  type_cls = tf.zeros_like(cls)
  type_s1 = tf.zeros_like(sentence1)
  type_s2 = tf.ones_like(sentence2)
  input_type_ids = tf.concat(
      [type_cls, type_s1, type_s2], axis=-1).to_tensor()

  inputs = {
      'input_word_ids': input_word_ids.to_tensor(),
      'input_mask': input_mask,
      'input_type_ids': input_type_ids}

  return inputs
glue_train = bert_encode(glue['train'], tokenizer)
glue_train_labels = glue['train']['label']

glue_validation = bert_encode(glue['validation'], tokenizer)
glue_validation_labels = glue['validation']['label']

glue_test = bert_encode(glue['test'], tokenizer)
glue_test_labels  = glue['test']['label']

Verilerin her bir alt kümesi, bir özellik sözlüğüne ve bir etiket kümesine dönüştürülmüştür. Giriş sözlüğündeki her özellik aynı şekle sahiptir ve etiket sayısı aşağıdakilerle eşleşmelidir:

for key, value in glue_train.items():
  print(f'{key:15s} shape: {value.shape}')

print(f'glue_train_labels shape: {glue_train_labels.shape}')
input_word_ids  shape: (3668, 103)
input_mask      shape: (3668, 103)
input_type_ids  shape: (3668, 103)
glue_train_labels shape: (3668,)

model

Modeli oluşturun

İlk adım, önceden eğitilmiş model için yapılandırmayı indirmektir.

import json

bert_config_file = os.path.join(gs_folder_bert, "bert_config.json")
config_dict = json.loads(tf.io.gfile.GFile(bert_config_file).read())

bert_config = bert.configs.BertConfig.from_dict(config_dict)

config_dict
{'attention_probs_dropout_prob': 0.1,
 'hidden_act': 'gelu',
 'hidden_dropout_prob': 0.1,
 'hidden_size': 768,
 'initializer_range': 0.02,
 'intermediate_size': 3072,
 'max_position_embeddings': 512,
 'num_attention_heads': 12,
 'num_hidden_layers': 12,
 'type_vocab_size': 2,
 'vocab_size': 30522}

config çekirdek çıktılarını tahmin etmek için bir Keras modeli Bert Modeli, tanımlar num_classes maksimum sekans uzunluğu olan girişlerden max_seq_length .

Bu işlev hem kodlayıcıyı hem de sınıflandırıcıyı döndürür.

bert_classifier, bert_encoder = bert.bert_models.classifier_model(
    bert_config, num_labels=2)

Sınıflandırıcının üç girişi ve bir çıkışı vardır:

tf.keras.utils.plot_model(bert_classifier, show_shapes=True, dpi=48)

png

Eğitim setinden 10 örneklik bir test verisi üzerinde çalıştırın. Çıktı, iki sınıfın logitleridir:

glue_batch = {key: val[:10] for key, val in glue_train.items()}

bert_classifier(
    glue_batch, training=True
).numpy()
array([[ 0.10071337,  0.05758326],
       [ 0.05382514,  0.30056837],
       [ 0.00795104,  0.1443476 ],
       [ 0.03538848, -0.04541291],
       [ 0.0905486 ,  0.3010756 ],
       [-0.09503749,  0.26234314],
       [-0.00378452,  0.19791688],
       [-0.09037939,  0.2433937 ],
       [-0.03041902,  0.07568075],
       [ 0.30516896,  0.08384045]], dtype=float32)

TransformerEncoder sınıflandırıcı merkezinde üzerindedir bert_encoder .

Kodlayıcı incelenmesi, biz, yığın bkz Transformer tabakaları aynı üç girişlerine bağlı:

tf.keras.utils.plot_model(bert_encoder, show_shapes=True, dpi=48)

png

Enkoder ağırlıklarını geri yükleyin

Oluşturulduğunda kodlayıcı rastgele başlatılır. Kontrol noktasından kodlayıcının ağırlıklarını geri yükleyin:

checkpoint = tf.train.Checkpoint(encoder=bert_encoder)
checkpoint.read(
    os.path.join(gs_folder_bert, 'bert_model.ckpt')).assert_consumed()
<tensorflow.python.training.tracking.util.CheckpointLoadStatus at 0x7fa18848bb50>

Optimize ediciyi ayarlayın

Bert ağırlık çürüme (diğer adıyla "ile Adem optimize edici benimser AdamW "). Ayrıca, önce 0'dan ısınan ve ardından 0'a düşen bir öğrenme oranı çizelgesi kullanır.

# Set up epochs and steps
epochs = 3
batch_size = 32
eval_batch_size = 32

train_data_size = len(glue_train_labels)
steps_per_epoch = int(train_data_size / batch_size)
num_train_steps = steps_per_epoch * epochs
warmup_steps = int(epochs * train_data_size * 0.1 / batch_size)

# creates an optimizer with learning rate schedule
optimizer = nlp.optimization.create_optimizer(
    2e-5, num_train_steps=num_train_steps, num_warmup_steps=warmup_steps)

Bu döner bir AdamWeightDecay öğrenme hızı çizelgesi seti ile optimize edici:

type(optimizer)
official.nlp.optimization.AdamWeightDecay

Optimize edici ve 's zamanlama özelleştirmek için nasıl bir örnek görmek için bkz Doktoru zamanlama apendiksi .

Modeli eğit

Metrik doğruluktur ve kayıp olarak seyrek kategorik çapraz entropi kullanıyoruz.

metrics = [tf.keras.metrics.SparseCategoricalAccuracy('accuracy', dtype=tf.float32)]
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

bert_classifier.compile(
    optimizer=optimizer,
    loss=loss,
    metrics=metrics)

bert_classifier.fit(
      glue_train, glue_train_labels,
      validation_data=(glue_validation, glue_validation_labels),
      batch_size=32,
      epochs=epochs)
Epoch 1/3
115/115 [==============================] - 37s 220ms/step - loss: 0.5972 - accuracy: 0.7034 - val_loss: 0.4941 - val_accuracy: 0.7794
Epoch 2/3
115/115 [==============================] - 24s 211ms/step - loss: 0.4228 - accuracy: 0.8171 - val_loss: 0.4503 - val_accuracy: 0.8137
Epoch 3/3
115/115 [==============================] - 24s 211ms/step - loss: 0.2852 - accuracy: 0.8956 - val_loss: 0.4061 - val_accuracy: 0.8162
<keras.callbacks.History at 0x7fa1884d0b50>

Şimdi çalıştığını görmek için ince ayarlı modeli özel bir örnek üzerinde çalıştırın.

Bazı cümle çiftlerini kodlayarak başlayın:

my_examples = bert_encode(
    glue_dict = {
        'sentence1':[
            'The rain in Spain falls mainly on the plain.',
            'Look I fine tuned BERT.'],
        'sentence2':[
            'It mostly rains on the flat lands of Spain.',
            'Is it working? This does not match.']
    },
    tokenizer=tokenizer)

Model sınıfı bildirmelidir 1 Birinci örnekte ve sınıf için "eşleşme" 0 saniye "hayır-maç":

result = bert_classifier(my_examples, training=False)

result = tf.argmax(result).numpy()
result
array([1, 0])
np.array(info.features['label'].names)[result]
array(['equivalent', 'not_equivalent'], dtype='<U14')

modeli kaydet

Genellikle bir modeli eğitim hedefi şey için kullanıyorum o modeli verebilir ve sonra emin çalıştığını olmasını sağlamaktır.

export_dir='./saved_model'
tf.saved_model.save(bert_classifier, export_dir=export_dir)
2021-11-12 13:12:55.273917: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
WARNING:absl:Found untraced functions such as self_attention_layer_call_fn, self_attention_layer_call_and_return_conditional_losses, dropout_layer_call_fn, dropout_layer_call_and_return_conditional_losses, self_attention_layer_norm_layer_call_fn while saving (showing 5 of 900). These functions will not be directly callable after loading.
INFO:tensorflow:Assets written to: ./saved_model/assets
INFO:tensorflow:Assets written to: ./saved_model/assets
reloaded = tf.saved_model.load(export_dir)
reloaded_result = reloaded([my_examples['input_word_ids'],
                            my_examples['input_mask'],
                            my_examples['input_type_ids']], training=False)

original_result = bert_classifier(my_examples, training=False)

# The results are (nearly) identical:
print(original_result.numpy())
print()
print(reloaded_result.numpy())
[[-1.0493996   1.3163755 ]
 [ 0.674296   -0.87380654]]

[[-1.0493993  1.3163751]
 [ 0.6742962 -0.873807 ]]

ek

Büyük bir veri kümesini yeniden kodlama

Bu öğretici, netlik için veri kümesini bellekte yeniden kodladınız.

Bunun nedeni sadece mümkündü glue/mrpc çok küçük bir veri kümesi olduğunu. Daha büyük veri kümeleri ile ilgilenmek için tf_models kütüphanesinde işleme ve verimli eğitim için bir veri kümesi yeniden kodlamak için kullanılan bazı araçlar içerir.

İlk adım, veri kümesinin hangi özelliklerinin dönüştürülmesi gerektiğini açıklamaktır:

processor = nlp.data.classifier_data_lib.TfdsProcessor(
    tfds_params="dataset=glue/mrpc,text_key=sentence1,text_b_key=sentence2",
    process_text_fn=bert.tokenization.convert_to_unicode)

Ardından, yeni TFRecord dosyaları oluşturmak için dönüşümü uygulayın.

# Set up output of training and evaluation Tensorflow dataset
train_data_output_path="./mrpc_train.tf_record"
eval_data_output_path="./mrpc_eval.tf_record"

max_seq_length = 128
batch_size = 32
eval_batch_size = 32

# Generate and save training data into a tf record file
input_meta_data = (
    nlp.data.classifier_data_lib.generate_tf_record_from_data_file(
      processor=processor,
      data_dir=None,  # It is `None` because data is from tfds, not local dir.
      tokenizer=tokenizer,
      train_data_output_path=train_data_output_path,
      eval_data_output_path=eval_data_output_path,
      max_seq_length=max_seq_length))

Nihayet oluşturmak tf.data olanlar TFRecord dosyalarından giriş boru hatlarını:

training_dataset = bert.run_classifier.get_dataset_fn(
    train_data_output_path,
    max_seq_length,
    batch_size,
    is_training=True)()

evaluation_dataset = bert.run_classifier.get_dataset_fn(
    eval_data_output_path,
    max_seq_length,
    eval_batch_size,
    is_training=False)()

Elde edilen tf.data.Datasets dönüş (features, labels) çifti, beklendiği gibi keras.Model.fit :

training_dataset.element_spec
({'input_word_ids': TensorSpec(shape=(32, 128), dtype=tf.int32, name=None),
  'input_mask': TensorSpec(shape=(32, 128), dtype=tf.int32, name=None),
  'input_type_ids': TensorSpec(shape=(32, 128), dtype=tf.int32, name=None)},
 TensorSpec(shape=(32,), dtype=tf.int32, name=None))

Eğitim ve değerlendirme için tf.data.Dataset oluşturun

Veri yüklemesini değiştirmeniz gerekirse, başlamanıza yardımcı olacak bazı kodlar burada:

def create_classifier_dataset(file_path, seq_length, batch_size, is_training):
  """Creates input dataset from (tf)records files for train/eval."""
  dataset = tf.data.TFRecordDataset(file_path)
  if is_training:
    dataset = dataset.shuffle(100)
    dataset = dataset.repeat()

  def decode_record(record):
    name_to_features = {
      'input_ids': tf.io.FixedLenFeature([seq_length], tf.int64),
      'input_mask': tf.io.FixedLenFeature([seq_length], tf.int64),
      'segment_ids': tf.io.FixedLenFeature([seq_length], tf.int64),
      'label_ids': tf.io.FixedLenFeature([], tf.int64),
    }
    return tf.io.parse_single_example(record, name_to_features)

  def _select_data_from_record(record):
    x = {
        'input_word_ids': record['input_ids'],
        'input_mask': record['input_mask'],
        'input_type_ids': record['segment_ids']
    }
    y = record['label_ids']
    return (x, y)

  dataset = dataset.map(decode_record,
                        num_parallel_calls=tf.data.AUTOTUNE)
  dataset = dataset.map(
      _select_data_from_record,
      num_parallel_calls=tf.data.AUTOTUNE)
  dataset = dataset.batch(batch_size, drop_remainder=is_training)
  dataset = dataset.prefetch(tf.data.AUTOTUNE)
  return dataset
# Set up batch sizes
batch_size = 32
eval_batch_size = 32

# Return Tensorflow dataset
training_dataset = create_classifier_dataset(
    train_data_output_path,
    input_meta_data['max_seq_length'],
    batch_size,
    is_training=True)

evaluation_dataset = create_classifier_dataset(
    eval_data_output_path,
    input_meta_data['max_seq_length'],
    eval_batch_size,
    is_training=False)
training_dataset.element_spec
({'input_word_ids': TensorSpec(shape=(32, 128), dtype=tf.int64, name=None),
  'input_mask': TensorSpec(shape=(32, 128), dtype=tf.int64, name=None),
  'input_type_ids': TensorSpec(shape=(32, 128), dtype=tf.int64, name=None)},
 TensorSpec(shape=(32,), dtype=tf.int64, name=None))

TFHub'da TFModels BERT

Sen alabilirsiniz Bert modeli gelen raftan TFHub . Üstüne bir sınıflandırma baş eklemek için zor olmaz hub.KerasLayer

# Note: 350MB download.
import tensorflow_hub as hub

hub_encoder = hub.KerasLayer(f"https://tfhub.dev/tensorflow/{hub_model_name}/3",
                             trainable=True)

print(f"The Hub encoder has {len(hub_encoder.trainable_variables)} trainable variables")
The Hub encoder has 199 trainable variables

Bir grup veri üzerinde test edin:

result = hub_encoder(
    inputs=dict(
        input_word_ids=glue_train['input_word_ids'][:10],
        input_mask=glue_train['input_mask'][:10],
        input_type_ids=glue_train['input_type_ids'][:10],),
    training=False,
)

print("Pooled output shape:", result['pooled_output'].shape)
print("Sequence output shape:", result['sequence_output'].shape)
Pooled output shape: (10, 768)
Sequence output shape: (10, 103, 768)

Bu noktada, kendiniz bir sınıflandırma başlığı eklemek basit olacaktır.

bert_models.classifier_model fonksiyonu da TensorFlow Hub'dan kodlayıcı üzerine bir sınıflandırıcı inşa edebilirsiniz:

hub_classifier = nlp.modeling.models.BertClassifier(
    bert_encoder,
    num_classes=2,
    dropout_rate=0.1,
    initializer=tf.keras.initializers.TruncatedNormal(
        stddev=0.02))

Bu modeli TFHub'dan yüklemenin bir dezavantajı, dahili keras katmanlarının yapısının geri yüklenmemesidir. Bu nedenle, modeli incelemek veya değiştirmek daha zordur. BertEncoder modeli artık tek bir tabakadır:

tf.keras.utils.plot_model(hub_classifier, show_shapes=True, dpi=64)

png

try:
  tf.keras.utils.plot_model(hub_encoder, show_shapes=True, dpi=64)
  assert False
except Exception as e:
  print(f"{type(e).__name__}: {e}")
AttributeError: 'KerasLayer' object has no attribute 'layers'

Düşük seviyeli model oluşturma

Eğer modelin inşasıyla ilgili bir fazla kontrole ihtiyaç olduğunu belirterek 's değerinde classifier_model işlevi daha önce kullanılan gerçekten üzerinde sadece ince bir sarıcı nlp.modeling.networks.BertEncoder ve nlp.modeling.models.BertClassifier sınıfları. Mimariyi değiştirmeye başlarsanız, önceden eğitilmiş kontrol noktasını yeniden yüklemenin doğru veya mümkün olmayabileceğini, bu nedenle sıfırdan yeniden eğitim almanız gerekeceğini unutmayın.

Kodlayıcıyı oluşturun:

bert_encoder_config = config_dict.copy()

# You need to rename a few fields to make this work:
bert_encoder_config['attention_dropout_rate'] = bert_encoder_config.pop('attention_probs_dropout_prob')
bert_encoder_config['activation'] = tf_utils.get_activation(bert_encoder_config.pop('hidden_act'))
bert_encoder_config['dropout_rate'] = bert_encoder_config.pop('hidden_dropout_prob')
bert_encoder_config['initializer'] = tf.keras.initializers.TruncatedNormal(
          stddev=bert_encoder_config.pop('initializer_range'))
bert_encoder_config['max_sequence_length'] = bert_encoder_config.pop('max_position_embeddings')
bert_encoder_config['num_layers'] = bert_encoder_config.pop('num_hidden_layers')

bert_encoder_config
{'hidden_size': 768,
 'intermediate_size': 3072,
 'num_attention_heads': 12,
 'type_vocab_size': 2,
 'vocab_size': 30522,
 'attention_dropout_rate': 0.1,
 'activation': <function official.modeling.activations.gelu.gelu(x)>,
 'dropout_rate': 0.1,
 'initializer': <keras.initializers.initializers_v2.TruncatedNormal at 0x7f9d1011da50>,
 'max_sequence_length': 512,
 'num_layers': 12}
manual_encoder = nlp.modeling.networks.BertEncoder(**bert_encoder_config)

Ağırlıkları geri yükleyin:

checkpoint = tf.train.Checkpoint(encoder=manual_encoder)
checkpoint.read(
    os.path.join(gs_folder_bert, 'bert_model.ckpt')).assert_consumed()
<tensorflow.python.training.tracking.util.CheckpointLoadStatus at 0x7f9d10142d50>

Testi çalıştırın:

result = manual_encoder(my_examples, training=True)

print("Sequence output shape:", result[0].shape)
print("Pooled output shape:", result[1].shape)
Sequence output shape: (2, 23, 768)
Pooled output shape: (2, 768)

Bir sınıflandırıcıya sarın:

manual_classifier = nlp.modeling.models.BertClassifier(
        bert_encoder,
        num_classes=2,
        dropout_rate=bert_encoder_config['dropout_rate'],
        initializer=bert_encoder_config['initializer'])
manual_classifier(my_examples, training=True).numpy()
array([[-0.23401603, -0.3458405 ],
       [ 0.2552695 , -0.28906718]], dtype=float32)

Optimize ediciler ve zamanlamalar

Modeli eğitmek için kullanılan iyileştirici kullanılarak oluşturuldu nlp.optimization.create_optimizer fonksiyonu:

optimizer = nlp.optimization.create_optimizer(
    2e-5, num_train_steps=num_train_steps, num_warmup_steps=warmup_steps)

Bu üst düzey sarmalayıcı, öğrenme hızı çizelgelerini ve optimize ediciyi ayarlar.

Burada kullanılan temel öğrenme oranı çizelgesi, eğitim çalışması boyunca sıfıra doğrusal bir düşüştür:

epochs = 3
batch_size = 32
eval_batch_size = 32

train_data_size = len(glue_train_labels)
steps_per_epoch = int(train_data_size / batch_size)
num_train_steps = steps_per_epoch * epochs
decay_schedule = tf.keras.optimizers.schedules.PolynomialDecay(
      initial_learning_rate=2e-5,
      decay_steps=num_train_steps,
      end_learning_rate=0)

plt.plot([decay_schedule(n) for n in range(num_train_steps)])
[<matplotlib.lines.Line2D at 0x7f9d11235d90>]

png

Bu da bir sarılır WarmUp doğrusal Eğitimin ilk% 10 üzerinde hedef değere öğrenme hızını arttırdığını zamanlamaya:

warmup_steps = num_train_steps * 0.1

warmup_schedule = nlp.optimization.WarmUp(
        initial_learning_rate=2e-5,
        decay_schedule_fn=decay_schedule,
        warmup_steps=warmup_steps)

# The warmup overshoots, because it warms up to the `initial_learning_rate`
# following the original implementation. You can set
# `initial_learning_rate=decay_schedule(warmup_steps)` if you don't like the
# overshoot.
plt.plot([warmup_schedule(n) for n in range(num_train_steps)])
[<matplotlib.lines.Line2D at 0x7f9d109551d0>]

png

Sonra oluşturmak nlp.optimization.AdamWeightDecay Bert modeli için yapılandırılmış olduğunu çizelgesi kullanılarak:

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