BERT modelinin ince ayarı

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

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

Bu öğreticinin temel aldığı önceden eğitilmiş BERT modeli, TensorFlow Hub'da da mevcuttur, nasıl kullanılacağını görmek için Hub Ekine bakın

Kurulum

TensorFlow Model Garden pip paketini kurun

  • tf-models-official kararlı Model Bahçe paketidir. tensorflow_models github tensorflow_models en son değişiklikleri içermeyebileceğini unutmayın. En son değişiklikleri dahil etmek için her gün otomatik olarak oluşturulan gecelik Model Garden paketi olan tf-models-nightly kurabilirsiniz.
  • pip tüm modelleri ve bağımlılıkları otomatik olarak kuracaktır.
pip install -q tf-models-official==2.4.0

İthalat

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

Kaynaklar

Bu dizin, bu eğiticide 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']

TensorFlow Hub'dan önceden eğitilmiş bir BERT kodlayıcı alabilirsiniz :

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

Veri

Bu örnek için TFDS'den GLUE MRPC veri setini kullandık .

Bu veri kümesi doğrudan BERT modeline beslenebilecek şekilde ayarlanmamıştır, bu nedenle bu bölüm gerekli ön işlemleri de ele alır.

Veri kümesini TensorFlow Veri Kümelerinden 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 alınan bir cümle çiftleri bütünüdür.

  • Etiket sayısı: 2.
  • Eğitim veri kümesinin boyutu: 3668.
  • Değerlendirme veri kümesinin boyutu: 408.
  • Eğitim ve değerlendirme veri kümesinin maksimum sıra uzunluğu: 128.
glue, info = tfds.load('glue/mrpc', with_info=True,
                       # It's small, load the whole dataset
                       batch_size=-1)
list(glue.keys())
['test', 'train', 'validation']

info nesnesi, veri kümesini ve özelliklerini açıklar:

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:

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 jetonlaştırıcı

Önceden eğitilmiş bir modelin ince ayarını yapmak için, eğitim sırasında kullandığınızla tamamen aynı jetonlama, kelime haznesi ve dizin eşleştirmeyi kullandığınızdan emin olmanız gerekir.

Bu eğitimde kullanılan BERT belirteç oluşturucu saf Python ile yazılmıştır (TensorFlow işlemlerinden oluşturulmamıştır). Yani, preprocessing.TextVectorization keras.layer gibi modelinize keras.layer olarak keras.layer .

Aşağıdaki kod, temel model tarafından kullanılan jetonlaştırıcıyı 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ümle şifreleyin:

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 modelin beklediği biçime manuel olarak önceden işledi.

Bu veri kümesi küçüktür, bu nedenle ön işlem hızlı ve kolay bir şekilde bellekte yapılabilir. Daha büyük veri kümeleri için tf_models kitaplığı, bir veri kümesini önceden tf_models ve yeniden serileştirmek için bazı araçlar içerir. Ayrıntılar için Ek: Büyük bir veri kümesini yeniden kodlama bölümüne bakın.

Cümleleri kodlayın

Model, iki girdi cümlesinin bir araya getirilmesini bekler. Bu girdinin bir [CLS] "Bu bir sınıflandırma problemidir" belirteciyle başlaması beklenir ve her cümlenin bir [SEP] "Ayırıcı" simgesiyle bitmesi gerekir:

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

Bir [SEP] belirteci eklerken tüm cümleleri kodlayarak ve bunları düzensiz tensörler halinde paketleyerek başlayın:

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 bir [CLS] belirtecinin başına ekleyin ve her örnek için tek bir input_word_ids tensörü oluşturmak için düzensiz tensörleri birleştirin. RaggedTensor.to_tensor() sıfır pedlerinden en uzun diziye kadar.

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ş türü

Model iki ek girdi beklemektedir:

  • Giriş maskesi
  • Giriş türü

Maske, modelin içerik ve dolguyu net bir şekilde ayırt etmesini sağlar. Maske, input_word_ids aynı şekle sahiptir ve input_word_ids doldurmadığı her yerde bir 1 içerir.

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

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

png

"Girdi tipi" de aynı şekle sahiptir, ancak doldurulmamış bölgenin içinde, jetonun hangi cümlenin bir parçası olduğunu belirten bir 0 veya bir 1 içerir.

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 0x7fe3400d82b0>

png

Hepsini bir araya getirmek

Yukarıdaki metin ayrıştırma kodunu tek bir işlevde toplayın ve her glue/mrpc veri kümesine uygulayın.

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 özellikler 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ı 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 , maksimum sıra uzunluğu max_seq_length olan girdilerden num_classes çıktılarını tahmin etmek için bir num_classes modeli olan çekirdek BERT Modelini tanımlar.

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 örnek veri test grubu üzerinde çalıştırın. Çıktı, iki sınıf için günlüklerdir:

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

bert_classifier(
    glue_batch, training=True
).numpy()
array([[-0.3999117 ,  0.19228943],
       [-0.48039404,  0.49550664],
       [-0.4205317 ,  0.4514861 ],
       [-0.46268317,  0.24971014],
       [-0.24856849,  0.29781285],
       [-0.20492092,  0.33435237],
       [-0.16171221,  0.12575442],
       [-0.17115599,  0.40965632],
       [-0.23386969,  0.41947454],
       [-0.5728958 ,  0.40995434]], dtype=float32)

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

Kodlayıcıyı incelerken, Transformer katmanlarının aynı üç girişe bağlı olduğunu görüyoruz:

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

png

Kodlayıcı ağırlıklarını geri yükleyin

Kodlayıcı inşa edildiğinde rastgele başlatılır. Kodlayıcının ağırlıklarını kontrol noktasından 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 0x7fe2e00765f8>

Optimize ediciyi kurun

BERT, ağırlık azalmalı Adam optimizer'ı (" AdamW " olarak da bilinir) benimser . 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, öğrenme hızı çizelgesi ayarlı bir AdamWeightDecay iyileştirici döndürür:

type(optimizer)
official.nlp.optimization.AdamWeightDecay

Optimize edicinin ve takviminin nasıl özelleştirileceğine ilişkin bir örnek görmek için, Optimizer çizelgesi ekine bakın .

Modeli eğitin

Ölçü doğruluktur ve kayıp olarak seyrek kategorik çapraz entropiyi kullanırız.

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 [==============================] - 38s 229ms/step - loss: 0.6175 - accuracy: 0.6844 - val_loss: 0.4610 - val_accuracy: 0.7892
Epoch 2/3
115/115 [==============================] - 25s 215ms/step - loss: 0.4207 - accuracy: 0.8125 - val_loss: 0.3859 - val_accuracy: 0.8211
Epoch 3/3
115/115 [==============================] - 25s 215ms/step - loss: 0.2990 - accuracy: 0.8867 - val_loss: 0.3759 - val_accuracy: 0.8407

<tensorflow.python.keras.callbacks.History at 0x7fe2e03ba0f0>

Şimdi, çalıştığını görmek için özel bir örnek üzerinde ince ayarlı modeli ç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, ilk örnek için sınıf 1 "eşleşme" ve ikincisi için sınıf 0 "eşleşme yok" raporlamalıdır:

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 kaydedin

Genellikle bir modeli eğitmenin amacı onu bir şey için kullanmaktır , bu nedenle modeli dışa aktarın ve çalıştığından emin olmak için geri yükleyin.

export_dir='./saved_model'
tf.saved_model.save(bert_classifier, export_dir=export_dir)
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.
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.5500499   1.4857253 ]
 [ 0.72138155 -0.6029598 ]]

[[-1.5500501   1.4857253 ]
 [ 0.72138053 -0.6029588 ]]

Ek

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

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

Bu yalnızca glue/mrpc çok küçük bir veri kümesi olduğu için mümkündü. Daha büyük veri kümeleriyle başa çıkmak için tf_models kitaplığı, verimli eğitim için bir veri kümesini işlemek ve yeniden kodlamak için bazı araçlar içerir.

İlk adım, veri kümesinin hangi özelliklerinin dönüştürülmesi gerektiğini tanımlamaktı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))

Son olarak, bu TFRecord dosyalarından tf.data girdi ardışık tf.data oluşturun:

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

Ortaya çıkan tf.data.Datasets , keras.Model.fit tarafından beklendiği gibi (features, labels) çiftlerini 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ız için bazı kodlar aşağıdadır:

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.experimental.AUTOTUNE)
  dataset = dataset.map(
      _select_data_from_record,
      num_parallel_calls=tf.data.experimental.AUTOTUNE)
  dataset = dataset.batch(batch_size, drop_remainder=is_training)
  dataset = dataset.prefetch(tf.data.experimental.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

BERT modelini TFHub'dan raftan alabilirsiniz . Bu merkezin üzerine bir sınıflandırma başlığı eklemek zor 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 işlevi, TensorFlow Hub'dan kodlayıcı üzerine bir sınıflandırıcı da oluşturabilir:

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üklenmemiş olmasıdır. Bu nedenle modeli incelemek veya değiştirmek daha zordur. BertEncoder modeli artık tek bir katmandı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

Modelin inşası üzerinde daha fazla kontrole ihtiyacınız varsa, daha önce kullanılan classifier_model işlevinin gerçekten nlp.modeling.networks.BertEncoder ve nlp.modeling.models.BertClassifier sınıfları üzerinde ince bir sarmalayıcı olduğunu nlp.modeling.networks.BertEncoder nlp.modeling.models.BertClassifier . 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ğitmeniz 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': <tensorflow.python.keras.initializers.initializers_v2.TruncatedNormal at 0x7fe203c32d68>,
 '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 0x7fe20392a198>

Test et çalıştır:

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.1309041 , -0.20986415],
       [-0.09952673,  0.05040173]], dtype=float32)

Optimize ediciler ve programlar

Modeli eğitmek için kullanılan optimize edici, nlp.optimization.create_optimizer işlevi kullanılarak oluşturulmuştur:

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

Bu yüksek seviyeli 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ğru doğrusal bir azalmadı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 0x7fe203c1ac50>]

png

Bu da, eğitimin ilk% 10'unda öğrenme oranını doğrusal olarak hedef değere WarmUp bir WarmUp programına sarılır:

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 0x7fe20397bfd0>]

png

Ardından, BERT modeli için yapılandırılan bu zamanlamayı kullanarak nlp.optimization.AdamWeightDecay oluşturun:

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