ช่วยปกป้อง Great Barrier Reef กับ TensorFlow บน Kaggle เข้าร่วมท้าทาย

แก้ไขงาน GLUE โดยใช้ BERT บน TPU

ดูบน TensorFlow.org ทำงานใน Google Colab ดูบน GitHub ดาวน์โหลดโน๊ตบุ๊ค ดูรุ่น TF Hub

BERT สามารถใช้แก้ปัญหาต่างๆ ในการประมวลผลภาษาธรรมชาติได้ คุณจะได้เรียนรู้วิธีการ BERT ปรับแต่งสำหรับงานจำนวนมากจาก มาตรฐานกาว :

  1. โคล่า (คอร์ปัสของภาษาศาสตร์ยอมรับ): เป็นประโยคที่ถูกต้องตามหลักไวยากรณ์?

  2. SST-2 (Stanford ความเชื่อมั่น Treebank): งานคือการคาดการณ์ความเชื่อมั่นของประโยคที่กำหนด

  3. MRPC (Microsoft Research แปลความหมาย Corpus): ตรวจสอบว่าคู่ของประโยคที่มีความหมายเทียบเท่า

  4. QQP (Quora คำถาม Pairs2): ตรวจสอบว่าคู่ของคำถามจะเทียบเท่าความหมาย

  5. MNLI (Multi-แนวธรรมชาติภาษาอนุมาน): ให้เป็นประโยคที่สถานที่ตั้งและประโยคสมมติฐานของงานคือการคาดการณ์ว่าจะเป็นสถานที่สร้างความสมมติฐาน (entailment) ขัดแย้งกับสมมติฐาน (ขัดแย้ง) หรือไม่ (กลาง)

  6. QNLI (คำถาม-ตอบภาษาธรรมชาติอนุมาน): งานคือการตรวจสอบว่าประโยคบริบทมีคำตอบสำหรับคำถามที่

  7. RTE (ตระหนักถึงข้อความ entailment): ตรวจสอบว่าประโยค entails สมมติฐานที่กำหนดหรือไม่

  8. WNLI (Winograd ภาษาธรรมชาติอนุมาน): งานคือการคาดการณ์ถ้าประโยคที่มีคำสรรพนามแทนจะถูกยกให้โดยประโยคเดิม

บทแนะนำนี้ประกอบด้วยโค้ดแบบ end-to-end ที่สมบูรณ์เพื่อฝึกโมเดลเหล่านี้บน TPU คุณยังสามารถเรียกใช้โน้ตบุ๊กเครื่องนี้บน GPU โดยเปลี่ยนหนึ่งบรรทัด (อธิบายด้านล่าง)

ในสมุดบันทึกนี้ คุณจะ:

  • โหลดโมเดล BERT จาก TensorFlow Hub
  • เลือกงาน GLUE และดาวน์โหลดชุดข้อมูล
  • ประมวลผลข้อความล่วงหน้า
  • ปรับแต่ง BERT (ตัวอย่างมีให้สำหรับชุดข้อมูลแบบประโยคเดียวและหลายประโยค)
  • บันทึกรูปแบบการฝึกอบรมและใช้งาน

ติดตั้ง

คุณจะใช้แบบจำลองแยกต่างหากเพื่อประมวลผลข้อความล่วงหน้าก่อนที่จะใช้เพื่อปรับแต่ง BERT รุ่นนี้ขึ้นอยู่กับ tensorflow / ข้อความ ซึ่งคุณจะติดตั้งอยู่ด้านล่าง

pip install -q -U tensorflow-text

คุณจะใช้เพิ่มประสิทธิภาพ AdamW จาก tensorflow / รุ่น เพื่อ BERT ปรับแต่งซึ่งคุณจะติดตั้งได้เป็นอย่างดี

pip install -q -U tf-models-official
pip install -U tfds-nightly
import os
import tensorflow as tf
import tensorflow_hub as hub
import tensorflow_datasets as tfds
import tensorflow_text as text  # A dependency of the preprocessing model
import tensorflow_addons as tfa
from official.nlp import optimization
import numpy as np

tf.get_logger().setLevel('ERROR')
/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/requests/__init__.py:104: RequestsDependencyWarning: urllib3 (1.26.7) or chardet (2.3.0)/charset_normalizer (2.0.7) doesn't match a supported version!
  RequestsDependencyWarning)

ถัดไป กำหนดค่า TFHub ให้อ่านจุดตรวจสอบโดยตรงจากที่เก็บข้อมูล Cloud Storage ของ TFHub แนะนำให้ใช้เฉพาะเมื่อใช้งานรุ่น TFHub บน TPU

หากไม่มีการตั้งค่านี้ TFHub จะดาวน์โหลดไฟล์บีบอัดและแยกจุดตรวจในเครื่อง ความพยายามที่จะโหลดจากไฟล์ในเครื่องเหล่านี้จะล้มเหลวโดยมีข้อผิดพลาดดังต่อไปนี้:

InvalidArgumentError: Unimplemented: File system scheme '[local]' not implemented

เพราะนี่คือ TPU สามารถอ่านได้อย่างเดียวโดยตรงจากบุ้งกี๋ Cloud Storage

os.environ["TFHUB_MODEL_LOAD_FORMAT"]="UNCOMPRESSED"

เชื่อมต่อกับคนงาน TPU

รหัสต่อไปนี้เชื่อมต่อกับผู้ปฏิบัติงาน TPU และเปลี่ยนอุปกรณ์เริ่มต้นของ TensorFlow เป็นอุปกรณ์ CPU บนตัวปฏิบัติงาน TPU นอกจากนี้ยังกำหนดกลยุทธ์การกระจาย TPU ที่คุณจะใช้เพื่อแจกจ่ายการฝึกโมเดลไปยังแกน TPU 8 ตัวที่แยกจากกันซึ่งมีอยู่ในพนักงาน TPU รายนี้ ดู TensorFlow ของ TPU คู่มือ สำหรับข้อมูลเพิ่มเติม

import os

if os.environ['COLAB_TPU_ADDR']:
  cluster_resolver = tf.distribute.cluster_resolver.TPUClusterResolver(tpu='')
  tf.config.experimental_connect_to_cluster(cluster_resolver)
  tf.tpu.experimental.initialize_tpu_system(cluster_resolver)
  strategy = tf.distribute.TPUStrategy(cluster_resolver)
  print('Using TPU')
elif tf.config.list_physical_devices('GPU'):
  strategy = tf.distribute.MirroredStrategy()
  print('Using GPU')
else:
  raise ValueError('Running on CPU is not recommended.')
Using TPU

กำลังโหลดโมเดลจาก TensorFlow Hub

ที่นี่คุณสามารถเลือกรุ่น BERT ที่คุณจะโหลดจาก TensorFlow Hub และปรับแต่งได้ มี BERT ให้เลือกหลายรุ่น

  • BERT-Base , uncased และ อีกเจ็ดรุ่น ที่มีน้ำหนักการฝึกอบรมที่ออกโดยผู้เขียน BERT เดิม
  • BERTs ขนาดเล็ก มีสถาปัตยกรรมทั่วไปเหมือนกัน แต่น้อยลงและ / หรือเล็กบล็อกหม้อแปลงไฟฟ้าซึ่งจะช่วยให้คุณสำรวจความสมดุลระหว่างความเร็ว, ขนาดและคุณภาพ
  • ALBERT : สี่ขนาดที่แตกต่างกัน "A Lite BERT" ที่ช่วยลดขนาดของรูปแบบ ( แต่ไม่ใช่เวลาในการคำนวณ) โดยการแบ่งปันพารามิเตอร์ระหว่างชั้น
  • ผู้เชี่ยวชาญ BERT : แปดรูปแบบที่ทุกคนมีสถาปัตยกรรม BERT ฐาน แต่เสนอทางเลือกระหว่างโดเมนก่อนการฝึกอบรมที่แตกต่างกันในการจัดขึ้นอย่างใกล้ชิดกับงานเป้าหมาย
  • Electra มีสถาปัตยกรรมเดียวกับเบิร์ต (ในสามขนาดที่แตกต่างกัน) แต่ได้รับก่อนการฝึกอบรมเป็น discriminator ในการตั้งค่าที่คล้ายกำเนิดขัดแย้งเครือข่าย (GAN)
  • BERT กับ Talking Heads-เรียนและรั้วรอบขอบชิด Gelu [ ฐาน , ขนาดใหญ่ ] มีสองการปรับปรุงหลักของสถาปัตยกรรมหม้อแปลง

ดูเอกสารแบบจำลองที่ลิงก์ด้านบนสำหรับรายละเอียดเพิ่มเติม

ในบทช่วยสอนนี้ คุณจะเริ่มด้วย BERT-base คุณสามารถใช้รุ่นที่ใหญ่กว่าและใหม่กว่าเพื่อความแม่นยำที่สูงขึ้น หรือใช้รุ่นที่เล็กกว่าเพื่อการฝึกฝนที่เร็วขึ้น หากต้องการเปลี่ยนโมเดล คุณต้องเปลี่ยนโค้ดเพียงบรรทัดเดียว (แสดงด้านล่าง) ความแตกต่างทั้งหมดถูกห่อหุ้มไว้ใน SavedModel ที่คุณจะดาวน์โหลดจาก TensorFlow Hub

เลือกรุ่น BERT เพื่อปรับแต่ง

BERT model selected           : https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/3
Preprocessing model auto-selected: https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3

ประมวลผลข้อความล่วงหน้า

ใน ข้อความประเภทกับ BERT Colab รุ่น preprocessing จะใช้ฝังโดยตรงด้วยการเข้ารหัส BERT

บทช่วยสอนนี้สาธิตวิธีทำการประมวลผลล่วงหน้าซึ่งเป็นส่วนหนึ่งของไปป์ไลน์อินพุตสำหรับการฝึกอบรม โดยใช้ Dataset.map จากนั้นผสานเข้ากับโมเดลที่ส่งออกเพื่อการอนุมาน ด้วยวิธีนี้ ทั้งการฝึกและการอนุมานสามารถทำงานได้จากอินพุตข้อความดิบ แม้ว่า TPU เองจะต้องการอินพุตที่เป็นตัวเลข

ต้องการ TPU กันก็สามารถช่วยให้ประสิทธิภาพการทำงานที่ได้ทำ preprocessing ถ่ายทอดสดในท่อป้อนข้อมูล (คุณสามารถเรียนรู้เพิ่มเติมใน คู่มือการปฏิบัติงาน tf.data )

บทช่วยสอนนี้ยังสาธิตวิธีสร้างแบบจำลองหลายอินพุต และวิธีปรับความยาวลำดับของอินพุตเป็น BERT

มาสาธิตโมเดลก่อนการประมวลผลกัน

bert_preprocess = hub.load(tfhub_handle_preprocess)
tok = bert_preprocess.tokenize(tf.constant(['Hello TensorFlow!']))
print(tok)
<tf.RaggedTensor [[[7592], [23435, 12314], [999]]]>

แต่ละรุ่น preprocessing นอกจากนี้ยังมีวิธีการ .bert_pack_inputs(tensors, seq_length) ซึ่งจะนำรายชื่อของสัญญาณ (เช่น tok ด้านบน) และความยาวลำดับอาร์กิวเมนต์ ซึ่งบรรจุอินพุตเพื่อสร้างพจนานุกรมของเทนเซอร์ในรูปแบบที่โมเดล BERT คาดไว้

text_preprocessed = bert_preprocess.bert_pack_inputs([tok, tok], tf.constant(20))

print('Shape Word Ids : ', text_preprocessed['input_word_ids'].shape)
print('Word Ids       : ', text_preprocessed['input_word_ids'][0, :16])
print('Shape Mask     : ', text_preprocessed['input_mask'].shape)
print('Input Mask     : ', text_preprocessed['input_mask'][0, :16])
print('Shape Type Ids : ', text_preprocessed['input_type_ids'].shape)
print('Type Ids       : ', text_preprocessed['input_type_ids'][0, :16])
Shape Word Ids :  (1, 20)
Word Ids       :  tf.Tensor(
[  101  7592 23435 12314   999   102  7592 23435 12314   999   102     0
     0     0     0     0], shape=(16,), dtype=int32)
Shape Mask     :  (1, 20)
Input Mask     :  tf.Tensor([1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0], shape=(16,), dtype=int32)
Shape Type Ids :  (1, 20)
Type Ids       :  tf.Tensor([0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0], shape=(16,), dtype=int32)

นี่คือรายละเอียดบางส่วนที่ควรคำนึงถึง:

  • input_mask หน้ากากช่วยให้รูปแบบที่แตกต่างหมดจดระหว่างเนื้อหาและช่องว่างที่ หน้ากากมีรูปร่างเช่นเดียวกับ input_word_ids และมี 1 ทุกที่ input_word_ids ไม่ได้รอง
  • input_type_ids มีรูปร่างเช่นเดียวกับ input_mask แต่ภายในภูมิภาคที่ไม่ใช่เบาะมี 0 หรือ 1 ระบุว่าประโยคโทเค็นเป็นส่วนหนึ่งของ

ถัดไป คุณจะต้องสร้างโมเดลการประมวลผลล่วงหน้าที่สรุปตรรกะทั้งหมดนี้ โมเดลของคุณจะรับสตริงเป็นอินพุต และส่งคืนอ็อบเจ็กต์ที่จัดรูปแบบอย่างเหมาะสมซึ่งสามารถส่งผ่านไปยัง BERT ได้

โมเดล BERT แต่ละรุ่นมีรูปแบบการประมวลผลล่วงหน้าเฉพาะ ตรวจสอบให้แน่ใจว่าได้ใช้แบบจำลองที่เหมาะสมที่อธิบายไว้ในเอกสารประกอบแบบจำลองของ BERT

def make_bert_preprocess_model(sentence_features, seq_length=128):
  """Returns Model mapping string features to BERT inputs.

  Args:
    sentence_features: a list with the names of string-valued features.
    seq_length: an integer that defines the sequence length of BERT inputs.

  Returns:
    A Keras Model that can be called on a list or dict of string Tensors
    (with the order or names, resp., given by sentence_features) and
    returns a dict of tensors for input to BERT.
  """

  input_segments = [
      tf.keras.layers.Input(shape=(), dtype=tf.string, name=ft)
      for ft in sentence_features]

  # Tokenize the text to word pieces.
  bert_preprocess = hub.load(tfhub_handle_preprocess)
  tokenizer = hub.KerasLayer(bert_preprocess.tokenize, name='tokenizer')
  segments = [tokenizer(s) for s in input_segments]

  # Optional: Trim segments in a smart way to fit seq_length.
  # Simple cases (like this example) can skip this step and let
  # the next step apply a default truncation to approximately equal lengths.
  truncated_segments = segments

  # Pack inputs. The details (start/end token ids, dict of output tensors)
  # are model-dependent, so this gets loaded from the SavedModel.
  packer = hub.KerasLayer(bert_preprocess.bert_pack_inputs,
                          arguments=dict(seq_length=seq_length),
                          name='packer')
  model_inputs = packer(truncated_segments)
  return tf.keras.Model(input_segments, model_inputs)

มาสาธิตโมเดลก่อนการประมวลผลกัน คุณจะสร้างการทดสอบด้วยการป้อนสองประโยค (input1 และ input2) เอาท์พุทคือสิ่งที่รุ่น BERT จะคาดหวังเป็น input: input_word_ids , input_masks และ input_type_ids

test_preprocess_model = make_bert_preprocess_model(['my_input1', 'my_input2'])
test_text = [np.array(['some random test sentence']),
             np.array(['another sentence'])]
text_preprocessed = test_preprocess_model(test_text)

print('Keys           : ', list(text_preprocessed.keys()))
print('Shape Word Ids : ', text_preprocessed['input_word_ids'].shape)
print('Word Ids       : ', text_preprocessed['input_word_ids'][0, :16])
print('Shape Mask     : ', text_preprocessed['input_mask'].shape)
print('Input Mask     : ', text_preprocessed['input_mask'][0, :16])
print('Shape Type Ids : ', text_preprocessed['input_type_ids'].shape)
print('Type Ids       : ', text_preprocessed['input_type_ids'][0, :16])
Keys           :  ['input_word_ids', 'input_mask', 'input_type_ids']
Shape Word Ids :  (1, 128)
Word Ids       :  tf.Tensor(
[ 101 2070 6721 3231 6251  102 2178 6251  102    0    0    0    0    0
    0    0], shape=(16,), dtype=int32)
Shape Mask     :  (1, 128)
Input Mask     :  tf.Tensor([1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0], shape=(16,), dtype=int32)
Shape Type Ids :  (1, 128)
Type Ids       :  tf.Tensor([0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0], shape=(16,), dtype=int32)

มาดูโครงสร้างของโมเดลกัน โดยให้ความสนใจกับอินพุตทั้งสองที่คุณเพิ่งกำหนด

tf.keras.utils.plot_model(test_preprocess_model, show_shapes=True, show_dtype=True)
('You must install pydot (`pip install pydot`) and install graphviz (see instructions at https://graphviz.gitlab.io/download/) ', 'for plot_model/model_to_dot to work.')

เพื่อนำไปใช้ประมวลผลเบื้องต้นในปัจจัยการผลิตทั้งหมดจากชุดข้อมูลที่คุณจะใช้ map ฟังก์ชั่นจากชุดข้อมูล ผลที่ได้คือที่เก็บไว้ชั่วคราวแล้วสำหรับ ผลการดำเนินงาน

AUTOTUNE = tf.data.AUTOTUNE


def load_dataset_from_tfds(in_memory_ds, info, split, batch_size,
                           bert_preprocess_model):
  is_training = split.startswith('train')
  dataset = tf.data.Dataset.from_tensor_slices(in_memory_ds[split])
  num_examples = info.splits[split].num_examples

  if is_training:
    dataset = dataset.shuffle(num_examples)
    dataset = dataset.repeat()
  dataset = dataset.batch(batch_size)
  dataset = dataset.map(lambda ex: (bert_preprocess_model(ex), ex['label']))
  dataset = dataset.cache().prefetch(buffer_size=AUTOTUNE)
  return dataset, num_examples

กำหนดรุ่นของคุณ

ตอนนี้คุณพร้อมที่จะกำหนดแบบจำลองของคุณสำหรับการจำแนกคู่ประโยคหรือประโยคโดยป้อนอินพุตที่ประมวลผลล่วงหน้าผ่านตัวเข้ารหัส BERT และวางตัวแยกประเภทเชิงเส้นไว้ด้านบน

def build_classifier_model(num_classes):

  class Classifier(tf.keras.Model):
    def __init__(self, num_classes):
      super(Classifier, self).__init__(name="prediction")
      self.encoder = hub.KerasLayer(tfhub_handle_encoder, trainable=True)
      self.dropout = tf.keras.layers.Dropout(0.1)
      self.dense = tf.keras.layers.Dense(num_classes)

    def call(self, preprocessed_text):
      encoder_outputs = self.encoder(preprocessed_text)
      pooled_output = encoder_outputs["pooled_output"]
      x = self.dropout(pooled_output)
      x = self.dense(x)
      return x

  model = Classifier(num_classes)
  return model

มาลองเรียกใช้โมเดลกับอินพุตที่ประมวลผลล่วงหน้า

test_classifier_model = build_classifier_model(2)
bert_raw_result = test_classifier_model(text_preprocessed)
print(tf.sigmoid(bert_raw_result))
tf.Tensor([[0.29329836 0.44367802]], shape=(1, 2), dtype=float32)

เลือกงานจาก GLUE

คุณจะใช้ TensorFlow ชุดข้อมูลจาก กาว ชุดมาตรฐาน

Colab ให้คุณดาวน์โหลดชุดข้อมูลขนาดเล็กเหล่านี้ไปยังระบบไฟล์ในเครื่อง และโค้ดด้านล่างอ่านทั้งหมดลงในหน่วยความจำ เนื่องจากโฮสต์ของผู้ปฏิบัติงาน TPU ที่แยกจากกันไม่สามารถเข้าถึงระบบไฟล์ในเครื่องของรันไทม์ colab

สำหรับชุดข้อมูลขนาดใหญ่ที่คุณจะต้องสร้างของคุณเอง ข้อมูล Google Cloud Storage ถังและมีคนงาน TPU อ่านข้อมูลจากที่นั่น คุณสามารถเรียนรู้เพิ่มเติมใน คู่มือ TPU

ขอแนะนำให้เริ่มต้นด้วยชุดข้อมูล CoLa (สำหรับประโยคเดียว) หรือ MRPC (สำหรับหลายประโยค) เนื่องจากชุดข้อมูลเหล่านี้มีขนาดเล็กและไม่ใช้เวลาในการปรับแต่งนาน

Using glue/cola from TFDS
This dataset has 10657 examples
Number of classes: 2
Features ['sentence']
Splits ['train', 'validation', 'test']
Here are some sample rows from glue/cola dataset
['unacceptable', 'acceptable']

sample row 1
b'It is this hat that it is certain that he was wearing.'
label: 1 (acceptable)

sample row 2
b'Her efficient looking up of the answer pleased the boss.'
label: 1 (acceptable)

sample row 3
b'Both the workers will wear carnations.'
label: 1 (acceptable)

sample row 4
b'John enjoyed drawing trees for his syntax homework.'
label: 1 (acceptable)

sample row 5
b'We consider Leslie rather foolish, and Lou a complete idiot.'
label: 1 (acceptable)

ชุดข้อมูลยังกำหนดประเภทของปัญหา (การจำแนกหรือการถดถอย) และฟังก์ชันการสูญเสียที่เหมาะสมสำหรับการฝึกอบรม

def get_configuration(glue_task):

  loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

  if glue_task == 'glue/cola':
    metrics = tfa.metrics.MatthewsCorrelationCoefficient(num_classes=2)
  else:
    metrics = tf.keras.metrics.SparseCategoricalAccuracy(
        'accuracy', dtype=tf.float32)

  return metrics, loss

ฝึกโมเดลของคุณ

สุดท้าย คุณสามารถฝึกโมเดล end-to-end บนชุดข้อมูลที่คุณเลือกได้

การกระจาย

เรียกคืนรหัสการตั้งค่าที่ด้านบน ซึ่งเชื่อมต่อรันไทม์ของ colab กับผู้ปฏิบัติงาน TPU ที่มีอุปกรณ์ TPU หลายเครื่อง ในการเผยแพร่การฝึกอบรม คุณจะต้องสร้างและรวบรวมโมเดล Keras หลักของคุณภายในขอบเขตของกลยุทธ์การกระจาย TPU (โปรดดูรายละเอียด ที่กระจายการฝึกอบรมกับ Keras .)

ในทางกลับกัน การประมวลผลล่วงหน้าทำงานบน CPU ของโฮสต์ผู้ปฏิบัติงาน ไม่ใช่ TPU ดังนั้นโมเดล Keras สำหรับการประมวลผลล่วงหน้ารวมถึงชุดข้อมูลการฝึกอบรมและการตรวจสอบความถูกต้องที่แมปด้วยจะถูกสร้างขึ้นนอกขอบเขตกลยุทธ์การแจกจ่าย เรียกร้องให้ Model.fit() จะดูแลการจัดจำหน่ายผ่านในชุดข้อมูลที่จำลองรูปแบบ

เครื่องมือเพิ่มประสิทธิภาพ

ปรับจูนต่อไปเพิ่มประสิทธิภาพการตั้งค่าจาก BERT ก่อนการฝึกอบรม (ในขณะที่ ข้อความประเภทกับ BERT ): จะใช้เพิ่มประสิทธิภาพ AdamW กับการสลายตัวเชิงเส้นของอัตราการเรียนรู้ความคิดเริ่มต้นนำหน้าด้วยขั้นตอนการอุ่นเครื่องเชิงเส้นในช่วงแรก 10% ของขั้นตอนการฝึกอบรม ( num_warmup_steps ) ตามรายงานของ BERT อัตราการเรียนรู้เริ่มต้นจะน้อยกว่าสำหรับการปรับแต่งอย่างละเอียด (ดีที่สุดของ 5e-5, 3e-5, 2e-5)

epochs = 3
batch_size = 32
init_lr = 2e-5

print(f'Fine tuning {tfhub_handle_encoder} model')
bert_preprocess_model = make_bert_preprocess_model(sentence_features)

with strategy.scope():

  # metric have to be created inside the strategy scope
  metrics, loss = get_configuration(tfds_name)

  train_dataset, train_data_size = load_dataset_from_tfds(
      in_memory_ds, tfds_info, train_split, batch_size, bert_preprocess_model)
  steps_per_epoch = train_data_size // batch_size
  num_train_steps = steps_per_epoch * epochs
  num_warmup_steps = num_train_steps // 10

  validation_dataset, validation_data_size = load_dataset_from_tfds(
      in_memory_ds, tfds_info, validation_split, batch_size,
      bert_preprocess_model)
  validation_steps = validation_data_size // batch_size

  classifier_model = build_classifier_model(num_classes)

  optimizer = optimization.create_optimizer(
      init_lr=init_lr,
      num_train_steps=num_train_steps,
      num_warmup_steps=num_warmup_steps,
      optimizer_type='adamw')

  classifier_model.compile(optimizer=optimizer, loss=loss, metrics=[metrics])

  classifier_model.fit(
      x=train_dataset,
      validation_data=validation_dataset,
      steps_per_epoch=steps_per_epoch,
      epochs=epochs,
      validation_steps=validation_steps)
Fine tuning https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/3 model
/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/keras/engine/functional.py:585: UserWarning: Input dict contained keys ['idx', 'label'] which did not match any model input. They will be ignored by the model.
  [n for n in tensors.keys() if n not in ref_input_names])
Epoch 1/3
/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/framework/indexed_slices.py:449: UserWarning: Converting sparse IndexedSlices(IndexedSlices(indices=Tensor("AdamWeightDecay/gradients/StatefulPartitionedCall:1", shape=(None,), dtype=int32), values=Tensor("clip_by_global_norm/clip_by_global_norm/_0:0", dtype=float32), dense_shape=Tensor("AdamWeightDecay/gradients/StatefulPartitionedCall:2", shape=(None,), dtype=int32))) to a dense Tensor of unknown shape. This may consume a large amount of memory.
  "shape. This may consume a large amount of memory." % value)
267/267 [==============================] - 86s 81ms/step - loss: 0.6092 - MatthewsCorrelationCoefficient: 0.0000e+00 - val_loss: 0.4846 - val_MatthewsCorrelationCoefficient: 0.0000e+00
Epoch 2/3
267/267 [==============================] - 14s 53ms/step - loss: 0.3774 - MatthewsCorrelationCoefficient: 0.0000e+00 - val_loss: 0.5322 - val_MatthewsCorrelationCoefficient: 0.0000e+00
Epoch 3/3
267/267 [==============================] - 14s 53ms/step - loss: 0.2623 - MatthewsCorrelationCoefficient: 0.0000e+00 - val_loss: 0.6469 - val_MatthewsCorrelationCoefficient: 0.0000e+00

ส่งออกเพื่อการอนุมาน

คุณจะสร้างแบบจำลองขั้นสุดท้ายที่มีส่วนประมวลผลล่วงหน้าและ BERT ที่ปรับแต่งแล้วที่เราเพิ่งสร้างขึ้น

ณ เวลาอนุมาน การประมวลผลล่วงหน้าจะต้องเป็นส่วนหนึ่งของโมเดล (เนื่องจากไม่มีคิวอินพุตแยกต่างหากอีกต่อไปสำหรับข้อมูลการฝึกที่ทำ) การประมวลผลล่วงหน้าไม่ได้เป็นเพียงการคำนวณเท่านั้น มีทรัพยากรของตัวเอง (ตารางคำศัพท์) ที่ต้องแนบกับ Keras Model ที่บันทึกไว้สำหรับการส่งออก การชุมนุมครั้งสุดท้ายนี้คือสิ่งที่จะรอด

คุณกำลังจะบันทึกรูปแบบบน Colab และต่อมาคุณสามารถดาวน์โหลดเพื่อเก็บไว้สำหรับอนาคต (ดู -> สารบัญ -> ไฟล์)

main_save_path = './my_models'
bert_type = tfhub_handle_encoder.split('/')[-2]
saved_model_name = f'{tfds_name.replace("/", "_")}_{bert_type}'

saved_model_path = os.path.join(main_save_path, saved_model_name)

preprocess_inputs = bert_preprocess_model.inputs
bert_encoder_inputs = bert_preprocess_model(preprocess_inputs)
bert_outputs = classifier_model(bert_encoder_inputs)
model_for_export = tf.keras.Model(preprocess_inputs, bert_outputs)

print('Saving', saved_model_path)

# Save everything on the Colab host (even the variables from TPU memory)
save_options = tf.saved_model.SaveOptions(experimental_io_device='/job:localhost')
model_for_export.save(saved_model_path, include_optimizer=False,
                      options=save_options)
Saving ./my_models/glue_cola_bert_en_uncased_L-12_H-768_A-12
WARNING:absl:Found untraced functions such as restored_function_body, restored_function_body, restored_function_body, restored_function_body, restored_function_body while saving (showing 5 of 910). These functions will not be directly callable after loading.

ทดสอบโมเดล

ขั้นตอนสุดท้ายคือการทดสอบผลลัพธ์ของแบบจำลองที่ส่งออกของคุณ

เพื่อทำการเปรียบเทียบ ให้โหลดแบบจำลองใหม่และทดสอบโดยใช้อินพุตบางส่วนจากการแยกการทดสอบจากชุดข้อมูล

with tf.device('/job:localhost'):
  reloaded_model = tf.saved_model.load(saved_model_path)

วิธียูทิลิตี้

ทดสอบ

with tf.device('/job:localhost'):
  test_dataset = tf.data.Dataset.from_tensor_slices(in_memory_ds[test_split])
  for test_row in test_dataset.shuffle(1000).map(prepare).take(5):
    if len(sentence_features) == 1:
      result = reloaded_model(test_row[0])
    else:
      result = reloaded_model(list(test_row))

    print_bert_results(test_row, result, tfds_name)
sentence: [b'An old woman languished in the forest.']
This sentence is acceptable
BERT raw results: tf.Tensor([-1.7032353  3.3714833], shape=(2,), dtype=float32)

sentence: [b"I went to the movies and didn't pick up the shirts."]
This sentence is acceptable
BERT raw results: tf.Tensor([-0.73970896  1.0806316 ], shape=(2,), dtype=float32)

sentence: [b"Every essay that she's written and which I've read is on that pile."]
This sentence is acceptable
BERT raw results: tf.Tensor([-0.7034159  0.6236454], shape=(2,), dtype=float32)

sentence: [b'Either Bill ate the peaches, or Harry.']
This sentence is unacceptable
BERT raw results: tf.Tensor([ 0.05972151 -0.08620442], shape=(2,), dtype=float32)

sentence: [b'I ran into the baker from whom I bought these bagels.']
This sentence is acceptable
BERT raw results: tf.Tensor([-1.6862067  3.285925 ], shape=(2,), dtype=float32)

หากคุณต้องการที่จะใช้รูปแบบของคุณบน TF การแสดง , จำไว้ว่ามันจะเรียก SavedModel ของคุณผ่านทางหนึ่งของลายเซ็นชื่อของมัน สังเกตว่าอินพุตมีความแตกต่างเล็กน้อย ใน Python คุณสามารถทดสอบได้ดังนี้:

with tf.device('/job:localhost'):
  serving_model = reloaded_model.signatures['serving_default']
  for test_row in test_dataset.shuffle(1000).map(prepare_serving).take(5):
    result = serving_model(**test_row)
    # The 'prediction' key is the classifier's defined model name.
    print_bert_results(list(test_row.values()), result['prediction'], tfds_name)
sentence: b'Everyone attended more than two seminars.'
This sentence is acceptable
BERT raw results: tf.Tensor([-1.5594155  2.862155 ], shape=(2,), dtype=float32)

sentence: b'Most columnists claim that a senior White House official has been briefing them.'
This sentence is acceptable
BERT raw results: tf.Tensor([-1.6298996  3.3155093], shape=(2,), dtype=float32)

sentence: b"That my father, he's lived here all his life is well known to those cops."
This sentence is acceptable
BERT raw results: tf.Tensor([-1.2048947  1.8589772], shape=(2,), dtype=float32)

sentence: b'Ourselves like us.'
This sentence is acceptable
BERT raw results: tf.Tensor([-1.2723312  2.0494034], shape=(2,), dtype=float32)

sentence: b'John is clever.'
This sentence is acceptable
BERT raw results: tf.Tensor([-1.6516167  3.3147635], shape=(2,), dtype=float32)

คุณทำได้! โมเดลที่บันทึกไว้ของคุณสามารถใช้สำหรับการแสดงผลหรือการอนุมานอย่างง่ายในกระบวนการ โดยมี api ที่ง่ายกว่าซึ่งมีโค้ดน้อยกว่าและดูแลรักษาง่ายกว่า

ขั้นตอนถัดไป

เมื่อคุณได้ลองใช้รุ่น BERT พื้นฐานแล้ว คุณสามารถลองใช้รุ่นอื่นเพื่อให้ได้ความแม่นยำมากขึ้นหรืออาจใช้กับรุ่นขนาดเล็กกว่าก็ได้

คุณยังสามารถลองใช้ชุดข้อมูลอื่นๆ ได้อีกด้วย