Trang này được dịch bởi Cloud Translation API.
Switch to English

Tinh chỉnh một mô hình Bert

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải về máy tính xách tay

Trong ví dụ này, chúng tôi sẽ làm việc thông qua tinh chỉnh một mô hình Bert sử dụng gói PIP tensorflow-mô hình.

Mô hình Bert pretrained hướng dẫn này được dựa trên cũng có sẵn trên TensorFlow Hub , để xem làm thế nào để sử dụng nó đề cập đến Hub Phụ lục

Thiết lập

Cài đặt gói pip TensorFlow Model Garden

  • tf-models-nightly là gói Model Garden đêm tạo ra hàng ngày tự động.
  • pip sẽ cài đặt tất cả các mô hình và phụ thuộc tự động.
pip install -q tf-nightly
pip install -q tf-models-nightly

nhập khẩu

 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.6/site-packages/tensorflow_addons/utils/ensure_tf_install.py:44: UserWarning: You are currently using a nightly version of TensorFlow (2.3.0-dev20200623). 
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,

Tài nguyên

Thư mục này chứa các cấu hình, từ vựng, và một trạm kiểm soát trước khi đào tạo được sử dụng trong hướng dẫn này:

 gs_folder_bert = "gs://cloud-tpu-checkpoints/bert/keras_bert/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']

Bạn có thể có được một Bert encoder pre-đào tạo từ TensorFlow Hub ở đây:

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

Dữ liệu

Trong ví dụ này chúng tôi sử dụng các dữ liệu KEO MRPC từ TFDS .

Bộ dữ liệu này không được thiết lập để nó có thể được đưa trực tiếp vào mô hình Bert, vì vậy phần này cũng xử lý việc tiền xử lý cần thiết.

Lấy dữ liệu từ TensorFlow Datasets

Microsoft Research diễn giải Corpus (Dolan & Brockett, 2005) là một corpus các cặp câu tự động chiết xuất từ ​​các nguồn tin tức trên mạng, với các chú thích con người cho dù các câu trong cặp là ngữ nghĩa tương đương.

  • Số nhãn: 2.
  • Kích thước của tập dữ liệu huấn luyện: 3668.
  • Kích thước của tập dữ liệu đánh giá: 408.
  • chiều dài chuỗi tối đa đào tạo và đánh giá số liệu: 128.
 glue, info = tfds.load('glue/mrpc', with_info=True,
                       # It's small, load the whole dataset
                       batch_size=-1)
 
Downloading and preparing dataset glue/mrpc/1.0.0 (download: 1.43 MiB, generated: Unknown size, total: 1.43 MiB) to /home/kbuilder/tensorflow_datasets/glue/mrpc/1.0.0...

/usr/lib/python3/dist-packages/urllib3/connectionpool.py:860: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
/usr/lib/python3/dist-packages/urllib3/connectionpool.py:860: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
/usr/lib/python3/dist-packages/urllib3/connectionpool.py:860: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)

Shuffling and writing examples to /home/kbuilder/tensorflow_datasets/glue/mrpc/1.0.0.incomplete1RTRDK/glue-train.tfrecord
Shuffling and writing examples to /home/kbuilder/tensorflow_datasets/glue/mrpc/1.0.0.incomplete1RTRDK/glue-validation.tfrecord
Shuffling and writing examples to /home/kbuilder/tensorflow_datasets/glue/mrpc/1.0.0.incomplete1RTRDK/glue-test.tfrecord
Dataset glue downloaded and prepared to /home/kbuilder/tensorflow_datasets/glue/mrpc/1.0.0. Subsequent calls will reuse this data.

 list(glue.keys())
 
['test', 'train', 'validation']

Các info đối tượng mô tả các tập dữ liệu và tính năng của nó:

 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),
})

Hai lớp học là:

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

Dưới đây là một ví dụ từ tập huấn luyện:

 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 .'

Các tokenizer Bert

Để tinh chỉnh một mô hình pre-đào tạo bạn cần phải chắc chắn rằng bạn đang sử dụng chính xác tokenization cùng, từ vựng, và lập bản đồ chỉ số như bạn sử dụng trong đào tạo.

Các tokenizer Bert sử dụng trong hướng dẫn này được viết bằng tinh khiết Python (Nó không được xây dựng ra khỏi ops TensorFlow). Vì vậy, bạn không thể chỉ cần cắm nó vào mô hình của bạn như một keras.layer như bạn có thể với preprocessing.TextVectorization .

Các mã sau xây dựng lại tokenizer đã được sử dụng bởi các mô hình cơ sở:

 # 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

Tokenize một câu:

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

Preprocess dữ liệu

Phần tay xử lý trước các bộ dữ liệu sang định dạng mong đợi của mô hình.

Bộ dữ liệu này là nhỏ, vì vậy tiền xử lý có thể được thực hiện một cách nhanh chóng và dễ dàng trong bộ nhớ. Đối với các tập dữ liệu càng lớn thì tf_models thư viện bao gồm một số công cụ để tiền xử lý và tái serializing một tập dữ liệu. Xem Phụ lục: Re-mã hóa một tập dữ liệu lớn để biết chi tiết.

Mã hóa các câu

Mô hình này hy vọng hai đầu vào câu của nó được nối với nhau. Đầu vào này được dự kiến sẽ bắt đầu với một [CLS] "Đây là một vấn đề phân loại" token, và mỗi câu nên kết thúc với một [SEP] "tách" mã thông báo:

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

Bắt đầu bằng cách mã hóa tất cả các câu trong khi phụ thêm một [SEP] token, và đóng gói chúng thành Ragged-tensors:

 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]

Bây giờ thêm vào trước một [CLS] token, và nối các tensors rách rưới để tạo thành một đơn input_word_ids tensor cho mỗi ví dụ. RaggedTensor.to_tensor() zero miếng đệm để chuỗi dài nhất.

 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

Mask và input type

Mô hình này hy vọng hai đầu vào bổ sung:

  • Mặt nạ đầu vào
  • Loại đầu vào

Mặt nạ cho phép các mô hình để phân biệt sạch giữa nội dung và padding. Mặt nạ có hình dạng giống như input_word_ids , và chứa một 1 bất cứ nơi nào input_word_ids không đệm.

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

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

png

"Loại đầu vào" cũng có hình dạng tương tự, nhưng bên trong khu vực phi độn, chứa 0 hoặc 1 chỉ ra câu nào token là một phần của.

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

png

Đặt nó tất cả cùng nhau

Thu thập các mã văn bản phân tích cú pháp trên vào một chức năng duy nhất, và áp dụng nó vào từng phần của glue/mrpc tập dữ liệu.

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

Mỗi tập hợp các dữ liệu đã được chuyển đổi sang một cuốn từ điển các tính năng, và một bộ các nhãn. Mỗi tính năng có trong từ điển đầu vào có hình dạng tương tự, và số lượng nhãn phải phù hợp:

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

Ngươi mâu

Xây dựng mô hình

Bước đầu tiên là để tải cấu hình cho mô hình pre-đào tạo.

 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}

Các config xác định cốt lõi Bert Model, mà là một mô hình Keras để dự đoán kết quả của num_classes từ đầu vào với chiều dài chuỗi tối đa max_seq_length .

Hàm này trả về cả hai bộ mã hóa và phân loại.

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

Phân loại có ba đầu vào và một đầu ra:

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

png

Chạy nó trên một lô kiểm tra dữ liệu 10 ví dụ từ tập huấn luyện. Kết quả là logits cho hai lớp:

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

bert_classifier(
    glue_batch, training=True
).numpy()
 
array([[ 0.05488977, -0.26042116],
       [ 0.11358108, -0.09727937],
       [ 0.14350253, -0.2465629 ],
       [ 0.2775127 , -0.09028438],
       [ 0.3606584 , -0.17138724],
       [ 0.3287397 , -0.14672714],
       [ 0.18621178, -0.13080403],
       [ 0.21898738,  0.10716071],
       [ 0.18413854, -0.13491377],
       [ 0.20307963, -0.05396855]], dtype=float32)

Các TransformerEncoder ở trung tâm của phân loại trên bert_encoder .

Kiểm tra việc mã hóa, chúng ta thấy stack của Transformer lớp kết nối với những người cùng ba đầu vào:

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

png

Khôi phục các trọng encoder

Khi xây dựng bộ mã hóa được khởi tạo một cách ngẫu nhiên. Khôi phục trọng lượng của bộ mã hóa từ các trạm kiểm soát:

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

Thiết lập tối ưu hóa

Bert thông qua tôi ưu hoa Adam với phân rã trọng lượng (hay còn gọi là " AdamW "). Nó cũng sử dụng một lịch trình tỷ lệ học mà trước hết là ấm lên từ 0 và sau đó phân rã đến 0.

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

Này trả một AdamWeightDecay tối ưu hóa với các thiết lập lịch trình tỷ lệ học:

 type(optimizer)
 
official.nlp.optimization.AdamWeightDecay

Để xem một ví dụ về cách tùy chỉnh tối ưu hóa và tiến độ của nó, xem lịch trình phụ lục Optimizer .

Đào tạo mô hình

Các số liệu là chính xác và chúng tôi sử dụng thưa thớt phân loại cross-entropy như mất mát.

 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 [==============================] - 25s 218ms/step - loss: 0.7047 - accuracy: 0.6101 - val_loss: 0.5219 - val_accuracy: 0.7181
Epoch 2/3
115/115 [==============================] - 24s 210ms/step - loss: 0.5068 - accuracy: 0.7560 - val_loss: 0.5047 - val_accuracy: 0.7794
Epoch 3/3
115/115 [==============================] - 24s 209ms/step - loss: 0.3812 - accuracy: 0.8332 - val_loss: 0.4839 - val_accuracy: 0.8137

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

Bây giờ chạy mô hình tinh chỉnh trên một ví dụ tùy chỉnh để thấy rằng nó hoạt động.

Bắt đầu bằng cách mã hóa một số cặp câu:

 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)
 

Mô hình này nên báo cáo lớp 1 "trận đấu" cho ví dụ đầu tiên và lớp 0 "không phù hợp" cho phần thứ hai:

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

Lưu mô hình

Thường thì các mục tiêu đào tạo một mô hình là để sử dụng nó cho một cái gì đó, vì vậy xuất khẩu mô hình và sau đó khôi phục nó để chắc chắn rằng nó hoạt động.

 export_dir='./saved_model'
tf.saved_model.save(bert_classifier, export_dir=export_dir)
 
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Model.state_updates (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Model.state_updates (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Layer.updates (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Layer.updates (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.

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.1238481   0.92107666]
 [ 0.35722053 -0.4061358 ]]

[[-1.1238478   0.9210764 ]
 [ 0.35722044 -0.40613574]]

ruột thừa

Re-mã hóa một tập dữ liệu lớn

Hướng dẫn này bạn tái mã hóa các tập dữ liệu trong bộ nhớ, cho rõ ràng.

Đây là chỉ có thể vì glue/mrpc là một tập dữ liệu rất nhỏ. Để đối phó với các tập dữ liệu lớn hơn tf_models thư viện bao gồm một số công cụ để xử lý và tái mã hóa một tập dữ liệu huấn luyện hiệu quả.

Bước đầu tiên là để mô tả những tính năng của bộ dữ liệu nên được chuyển đổi:

 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)
 

Sau đó, áp dụng việc chuyển đổi để tạo ra các file TFRecord mới.

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

Cuối cùng tạo tf.data đường ống đầu vào từ các tập tin TFRecord:

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

 

Kết quả tf.data.Datasets trở lại (features, labels) cặp, như mong đợi bởi 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))

Tạo tf.data.Dataset cho đào tạo và đánh giá

Nếu bạn cần phải sửa đổi tải dữ liệu ở đây là một số mã để giúp bạn bắt đầu:

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

TFModels Bert trên TFHub

Bạn có thể nhận được các mô hình Bert khỏi kệ từ TFHub . Sẽ không khó để thêm một cái đầu phân loại trên đầu trang này hub.KerasLayer

 # Note: 350MB download.
import tensorflow_hub as hub
hub_encoder = hub.KerasLayer(hub_url_bert, trainable=True)

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

Test chạy nó trên một loạt số liệu:

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

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

Tại thời điểm này nó sẽ là đơn giản để thêm một cái đầu phân loại chính mình.

Các bert_models.classifier_model chức năng cũng có thể xây dựng một bộ phân loại vào encoder từ TensorFlow Hub:

 hub_classifier, hub_encoder = bert.bert_models.classifier_model(
    # Caution: Most of `bert_config` is ignored if you pass a hub url.
    bert_config=bert_config, hub_module_url=hub_url_bert, num_labels=2)
 

Một trong những nhược điểm để tải mô hình này từ TFHub là cấu trúc của keras nội bộ lớp không được khôi phục. Vì vậy, nó khó khăn hơn để kiểm tra hoặc sửa đổi các mô hình. Các TransformerEncoder mô hình bây giờ là một lớp duy nhất:

 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'

xây dựng mô hình cấp thấp

Nếu bạn cần một kiểm soát tốt hơn việc xây dựng các mô hình của nó đáng chú ý là các classifier_model chức năng sử dụng trước đó thực sự chỉ là một wrapper mỏng trên nlp.modeling.networks.TransformerEncodernlp.modeling.models.BertClassifier lớp. Chỉ cần nhớ rằng nếu bạn bắt đầu thay đổi kiến ​​trúc nó có thể không chính xác hoặc có thể để lại các trạm kiểm soát trước khi được đào tạo, do đó bạn sẽ cần phải đào tạo lại từ đầu.

Xây dựng bộ mã hóa:

 transformer_config = config_dict.copy()

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

transformer_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 0x7f81145cb3c8>,
 'max_sequence_length': 512,
 'num_layers': 12}
 manual_encoder = nlp.modeling.networks.TransformerEncoder(**transformer_config)
 

Khôi phục các trọng:

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

Test chạy 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)

Bọc nó trong một phân loại:

 manual_classifier = nlp.modeling.models.BertClassifier(
        bert_encoder,
        num_classes=2,
        dropout_rate=transformer_config['dropout_rate'],
        initializer=tf.keras.initializers.TruncatedNormal(
          stddev=bert_config.initializer_range))
 
 manual_classifier(my_examples, training=True).numpy()
 
array([[-0.22512403,  0.07213479],
       [-0.21233292,  0.1311737 ]], dtype=float32)

Optimizers và lịch trình

Tôi ưu hoa dùng để huấn luyện các mô hình được tạo ra bằng cách sử dụng nlp.optimization.create_optimizer chức năng:

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

Đó là mức cao wrapper bộ lên lịch trình tỷ lệ học tập và tôi ưu hoa.

Lịch trình tỷ lệ học cơ sở sử dụng ở đây là một phân rã tuyến tính để zero về lâu đào tạo:

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

png

Này, đến lượt nó được bọc trong một WarmUp lịch trình tuyến tính làm tăng tỷ lệ học với giá trị mục tiêu trong 10% đầu tiên đào tạo:

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

png

Sau đó tạo ra các nlp.optimization.AdamWeightDecay sử dụng mà đúng tiến độ, cấu hình cho mô hình Bert:

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