บันทึกวันที่! Google I / O ส่งคืนวันที่ 18-20 พฤษภาคม ลงทะเบียนตอนนี้
หน้านี้ได้รับการแปลโดย Cloud Translation API
Switch to English

จัดหมวดหมู่ข้อความด้วย BERT

ดูใน TensorFlow.org เรียกใช้ใน Google Colab ดูบน GitHub ดาวน์โหลดสมุดบันทึก ดูโมเดล TF Hub

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

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

  • โหลดชุดข้อมูล IMDB
  • โหลดโมเดล BERT จาก TensorFlow Hub
  • สร้างแบบจำลองของคุณเองโดยการรวม BERT กับลักษณนาม
  • ฝึกโมเดลของคุณเองปรับแต่ง BERT อย่างละเอียดโดยเป็นส่วนหนึ่งของสิ่งนั้น
  • บันทึกโมเดลของคุณและใช้เพื่อจำแนกประโยค

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

เกี่ยวกับ BERT

BERT และสถาปัตยกรรมตัวเข้ารหัส Transformer อื่น ๆ ประสบความสำเร็จอย่างมากในงานต่างๆใน NLP (การประมวลผลภาษาธรรมชาติ) พวกเขาคำนวณการแสดงพื้นที่เวกเตอร์ของภาษาธรรมชาติที่เหมาะสำหรับใช้ในแบบจำลองการเรียนรู้เชิงลึก โมเดลตระกูล BERT ใช้สถาปัตยกรรมตัวเข้ารหัส Transformer เพื่อประมวลผลโทเค็นของข้อความอินพุตแต่ละรายการในบริบทที่สมบูรณ์ของโทเค็นทั้งหมดก่อนและหลังด้วยเหตุนี้จึงมีชื่อว่า: Bidirectional Encoder Representations จาก Transformers

โดยปกติแล้วโมเดล BERT จะได้รับการฝึกฝนมาก่อนในคลังข้อความขนาดใหญ่จากนั้นปรับแต่งสำหรับงานเฉพาะ

ติดตั้ง

# A dependency of the preprocessing for BERT inputs
pip install -q tensorflow-text

คุณจะใช้เครื่องมือเพิ่มประสิทธิภาพ AdamW จาก เทนเซอร์โฟลว์ / รุ่น

pip install -q tf-models-official
import os
import shutil

import tensorflow as tf
import tensorflow_hub as hub
import tensorflow_text as text
from official.nlp import optimization  # to create AdamW optmizer

import matplotlib.pyplot as plt

tf.get_logger().setLevel('ERROR')

การวิเคราะห์ความเชื่อมั่น

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

คุณจะใช้ ชุดข้อมูลบทวิจารณ์ภาพยนตร์ขนาดใหญ่ ที่มีข้อความบทวิจารณ์ภาพยนตร์ 50,000 บทจาก ฐานข้อมูลภาพยนตร์ทางอินเทอร์เน็ต

ดาวน์โหลดชุดข้อมูล IMDB

มาดาวน์โหลดและแยกชุดข้อมูลจากนั้นสำรวจโครงสร้างไดเร็กทอรี

url = 'https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz'

dataset = tf.keras.utils.get_file('aclImdb_v1.tar.gz', url,
                                  untar=True, cache_dir='.',
                                  cache_subdir='')

dataset_dir = os.path.join(os.path.dirname(dataset), 'aclImdb')

train_dir = os.path.join(dataset_dir, 'train')

# remove unused folders to make it easier to load the data
remove_dir = os.path.join(train_dir, 'unsup')
shutil.rmtree(remove_dir)
Downloading data from https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
84131840/84125825 [==============================] - 7s 0us/step

จากนั้นคุณจะใช้ยูทิลิตี้ text_dataset_from_directory เพื่อสร้างtf.data.Dataset มีป้ายกำกับ

ชุดข้อมูล IMDB ถูกแบ่งออกเป็นส่วนฝึกอบรมและการทดสอบแล้ว แต่ไม่มีชุดตรวจสอบความถูกต้อง มาสร้างชุดการตรวจสอบความถูกต้องโดยใช้การแบ่งข้อมูลการฝึกอบรมแบบ 80:20 โดยใช้อาร์กิวเมนต์ validation_split ด้านล่าง

AUTOTUNE = tf.data.AUTOTUNE
batch_size = 32
seed = 42

raw_train_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/train',
    batch_size=batch_size,
    validation_split=0.2,
    subset='training',
    seed=seed)

class_names = raw_train_ds.class_names
train_ds = raw_train_ds.cache().prefetch(buffer_size=AUTOTUNE)

val_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/train',
    batch_size=batch_size,
    validation_split=0.2,
    subset='validation',
    seed=seed)

val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

test_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/test',
    batch_size=batch_size)

test_ds = test_ds.cache().prefetch(buffer_size=AUTOTUNE)
Found 25000 files belonging to 2 classes.
Using 20000 files for training.
Found 25000 files belonging to 2 classes.
Using 5000 files for validation.
Found 25000 files belonging to 2 classes.

ลองมาดูบทวิจารณ์เล็ก ๆ น้อย ๆ

for text_batch, label_batch in train_ds.take(1):
  for i in range(3):
    print(f'Review: {text_batch.numpy()[i]}')
    label = label_batch.numpy()[i]
    print(f'Label : {label} ({class_names[label]})')
Review: b'"Pandemonium" is a horror movie spoof that comes off more stupid than funny. Believe me when I tell you, I love comedies. Especially comedy spoofs. "Airplane", "The Naked Gun" trilogy, "Blazing Saddles", "High Anxiety", and "Spaceballs" are some of my favorite comedies that spoof a particular genre. "Pandemonium" is not up there with those films. Most of the scenes in this movie had me sitting there in stunned silence because the movie wasn\'t all that funny. There are a few laughs in the film, but when you watch a comedy, you expect to laugh a lot more than a few times and that\'s all this film has going for it. Geez, "Scream" had more laughs than this film and that was more of a horror film. How bizarre is that?<br /><br />*1/2 (out of four)'
Label : 0 (neg)
Review: b"David Mamet is a very interesting and a very un-equal director. His first movie 'House of Games' was the one I liked best, and it set a series of films with characters whose perspective of life changes as they get into complicated situations, and so does the perspective of the viewer.<br /><br />So is 'Homicide' which from the title tries to set the mind of the viewer to the usual crime drama. The principal characters are two cops, one Jewish and one Irish who deal with a racially charged area. The murder of an old Jewish shop owner who proves to be an ancient veteran of the Israeli Independence war triggers the Jewish identity in the mind and heart of the Jewish detective.<br /><br />This is were the flaws of the film are the more obvious. The process of awakening is theatrical and hard to believe, the group of Jewish militants is operatic, and the way the detective eventually walks to the final violent confrontation is pathetic. The end of the film itself is Mamet-like smart, but disappoints from a human emotional perspective.<br /><br />Joe Mantegna and William Macy give strong performances, but the flaws of the story are too evident to be easily compensated."
Label : 0 (neg)
Review: b'Great documentary about the lives of NY firefighters during the worst terrorist attack of all time.. That reason alone is why this should be a must see collectors item.. What shocked me was not only the attacks, but the"High Fat Diet" and physical appearance of some of these firefighters. I think a lot of Doctors would agree with me that,in the physical shape they were in, some of these firefighters would NOT of made it to the 79th floor carrying over 60 lbs of gear. Having said that i now have a greater respect for firefighters and i realize becoming a firefighter is a life altering job. The French have a history of making great documentary\'s and that is what this is, a Great Documentary.....'
Label : 1 (pos)

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

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

  • BERT-Base , Uncased และ อีกเจ็ดรุ่น พร้อมน้ำหนักที่ได้รับการฝึกฝนโดยผู้เขียน BERT ดั้งเดิม
  • BERT ขนาดเล็ก มีสถาปัตยกรรมทั่วไปเหมือนกัน แต่บล็อก Transformer น้อยกว่าและ / หรือเล็กกว่าซึ่งช่วยให้คุณสำรวจการแลกเปลี่ยนระหว่างความเร็วขนาดและคุณภาพ
  • ALBERT : "A Lite BERT" สี่ขนาดที่แตกต่างกันซึ่งจะลดขนาดโมเดล (แต่ไม่ใช่เวลาในการคำนวณ) โดยการแชร์พารามิเตอร์ระหว่างเลเยอร์
  • BERT Experts : แปดรุ่นที่ทั้งหมดมีสถาปัตยกรรมพื้นฐานของ BERT แต่มีตัวเลือกระหว่างโดเมนก่อนการฝึกอบรมที่แตกต่างกันเพื่อให้สอดคล้องกับงานเป้าหมายมากขึ้น
  • Electra มีสถาปัตยกรรมแบบเดียวกับ BERT (มีสามขนาดที่แตกต่างกัน) แต่ได้รับการฝึกอบรมล่วงหน้าในฐานะผู้เลือกปฏิบัติในการตั้งค่าที่คล้ายกับ Generative Adversarial Network (GAN)
  • BERT with Talking-Heads Attention และ Gated GELU [ base , large ] มีการปรับปรุงสองประการสำหรับแกนหลักของสถาปัตยกรรม Transformer

เอกสารประกอบแบบจำลองบน TensorFlow Hub มีรายละเอียดเพิ่มเติมและการอ้างอิงถึงงานวิจัย ตามลิงค์ด้านบนหรือคลิกที่ tfhub.dev URL ที่พิมพ์หลังจากการเรียกใช้เซลล์ถัดไป

ข้อเสนอแนะคือให้เริ่มต้นด้วย Small BERT (ที่มีพารามิเตอร์น้อยกว่า) เนื่องจากสามารถปรับแต่งได้เร็วกว่า หากคุณชอบโมเดลขนาดเล็ก แต่มีความแม่นยำสูง ALBERT อาจเป็นตัวเลือกถัดไปของคุณ หากคุณต้องการความแม่นยำที่ดียิ่งขึ้นให้เลือกขนาด BERT แบบคลาสสิกหรือการปรับแต่งล่าสุดเช่น Electra, Talking Heads หรือ BERT Expert

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

คุณจะเห็นในโค้ดด้านล่างว่าการสลับ tfhub.dev URL ก็เพียงพอแล้วที่จะลองใช้โมเดลเหล่านี้เนื่องจากความแตกต่างทั้งหมดระหว่างนั้นถูกห่อหุ้มไว้ใน SavedModels จาก TF Hub

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

BERT model selected           : https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-4_H-512_A-8/1
Preprocess model auto-selected: https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3

แบบจำลองก่อนการประมวลผล

อินพุตข้อความจำเป็นต้องเปลี่ยนเป็นรหัสโทเค็นตัวเลขและจัดเรียงเป็น Tensors หลายตัวก่อนที่จะป้อนไปยัง BERT TensorFlow Hub มีโมเดลก่อนการประมวลผลที่ตรงกันสำหรับ BERT แต่ละรุ่นที่กล่าวถึงข้างต้นซึ่งดำเนินการแปลงนี้โดยใช้ TF ops จากไลบรารี TF.text ไม่จำเป็นต้องรันโค้ด Python แท้นอกโมเดล TensorFlow ของคุณเพื่อประมวลผลข้อความล่วงหน้า

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

bert_preprocess_model = hub.KerasLayer(tfhub_handle_preprocess)

ลองใช้โมเดลก่อนการประมวลผลกับข้อความและดูผลลัพธ์:

text_test = ['this is such an amazing movie!']
text_preprocessed = bert_preprocess_model(text_test)

print(f'Keys       : {list(text_preprocessed.keys())}')
print(f'Shape      : {text_preprocessed["input_word_ids"].shape}')
print(f'Word Ids   : {text_preprocessed["input_word_ids"][0, :12]}')
print(f'Input Mask : {text_preprocessed["input_mask"][0, :12]}')
print(f'Type Ids   : {text_preprocessed["input_type_ids"][0, :12]}')
Keys       : ['input_type_ids', 'input_mask', 'input_word_ids']
Shape      : (1, 128)
Word Ids   : [ 101 2023 2003 2107 2019 6429 3185  999  102    0    0    0]
Input Mask : [1 1 1 1 1 1 1 1 1 0 0 0]
Type Ids   : [0 0 0 0 0 0 0 0 0 0 0 0]

อย่างที่คุณเห็นตอนนี้คุณมี 3 เอาต์พุตจากการประมวลผลล่วงหน้าที่โมเดล BERT จะใช้ ( input_words_id , input_mask และ input_type_ids )

ประเด็นสำคัญอื่น ๆ :

  • อินพุตถูกตัดให้เหลือ 128 โทเค็น จำนวนโทเค็นสามารถปรับแต่งได้และคุณสามารถดูรายละเอียดเพิ่มเติมเกี่ยวกับงาน แก้ปัญหากาวโดยใช้ BERT บนโคแล็บ TPU
  • input_type_ids มีเพียงค่าเดียว (0) เนื่องจากเป็นอินพุตประโยคเดียว สำหรับการป้อนหลายประโยคมันจะมีหนึ่งหมายเลขสำหรับแต่ละอินพุต

เนื่องจากตัวประมวลผลข้อความนี้เป็นแบบจำลอง TensorFlow จึงสามารถรวมไว้ในโมเดลของคุณได้โดยตรง

โดยใช้แบบจำลอง BERT

ก่อนที่จะใส่ BERT ลงในโมเดลของคุณเรามาดูผลลัพธ์ของมันกันก่อน คุณจะโหลดจาก TF Hub และดูค่าที่ส่งคืน

bert_model = hub.KerasLayer(tfhub_handle_encoder)
bert_results = bert_model(text_preprocessed)

print(f'Loaded BERT: {tfhub_handle_encoder}')
print(f'Pooled Outputs Shape:{bert_results["pooled_output"].shape}')
print(f'Pooled Outputs Values:{bert_results["pooled_output"][0, :12]}')
print(f'Sequence Outputs Shape:{bert_results["sequence_output"].shape}')
print(f'Sequence Outputs Values:{bert_results["sequence_output"][0, :12]}')
Loaded BERT: https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-4_H-512_A-8/1
Pooled Outputs Shape:(1, 512)
Pooled Outputs Values:[ 0.76262873  0.9928097  -0.18611881  0.36673862  0.15233737  0.6550447
  0.9681153  -0.9486272   0.00216161 -0.9877732   0.06842697 -0.9763058 ]
Sequence Outputs Shape:(1, 128, 512)
Sequence Outputs Values:[[-0.28946346  0.34321272  0.33231515 ...  0.21300808  0.71020764
  -0.05771098]
 [-0.28742087  0.31980985 -0.23018607 ...  0.58455014 -0.21329728
   0.72692114]
 [-0.6615697   0.6887685  -0.87432986 ...  0.10877222 -0.2617324
   0.4785539 ]
 ...
 [-0.22561133 -0.2892562  -0.07064445 ...  0.47565985  0.83277136
   0.40025374]
 [-0.29824236 -0.27473187 -0.05450562 ...  0.48849723  1.0955356
   0.1816333 ]
 [-0.4437813   0.00930756  0.07223685 ...  0.17290069  1.1833248
   0.07897997]]

แบบจำลอง BERT ส่งคืนแผนที่พร้อมคีย์สำคัญ 3 คีย์: pooled_output , sequence_output , encoder_outputs

  • pooled_output เพื่อแสดงลำดับอินพุตแต่ละลำดับโดยรวม รูปร่างคือ [batch_size, H] คุณอาจคิดว่านี่เป็นการฝังสำหรับบทวิจารณ์ภาพยนตร์ทั้งหมด
  • sequence_output แทนโทเค็นอินพุตแต่ละรายการในบริบท รูปร่างคือ [batch_size, seq_length, H] คุณสามารถคิดว่านี่เป็นการฝังตามบริบทสำหรับโทเค็นทุกรายการในบทวิจารณ์ภาพยนตร์
  • encoder_outputs เป็นการกระตุ้นระดับกลางของบล็อก L Transformer outputs["encoder_outputs"][i] คือ Tensor ของรูปร่าง [batch_size, seq_length, 1024] พร้อมเอาต์พุตของบล็อก i-th Transformer สำหรับ 0 <= i < L ค่าสุดท้ายของรายการมีค่าเท่ากับ sequence_output

สำหรับการปรับแต่งอย่างละเอียดคุณจะใช้อาร์เรย์ pooled_output

กำหนดรูปแบบของคุณ

คุณจะสร้างโมเดลที่ได้รับการปรับแต่งอย่างง่ายโดยใช้โมเดลก่อนการประมวลผลโมเดล BERT ที่เลือกหนึ่ง Dense และเลเยอร์ Dropout

def build_classifier_model():
  text_input = tf.keras.layers.Input(shape=(), dtype=tf.string, name='text')
  preprocessing_layer = hub.KerasLayer(tfhub_handle_preprocess, name='preprocessing')
  encoder_inputs = preprocessing_layer(text_input)
  encoder = hub.KerasLayer(tfhub_handle_encoder, trainable=True, name='BERT_encoder')
  outputs = encoder(encoder_inputs)
  net = outputs['pooled_output']
  net = tf.keras.layers.Dropout(0.1)(net)
  net = tf.keras.layers.Dense(1, activation=None, name='classifier')(net)
  return tf.keras.Model(text_input, net)

ตรวจสอบว่าโมเดลทำงานด้วยเอาต์พุตของโมเดลก่อนการประมวลผล

classifier_model = build_classifier_model()
bert_raw_result = classifier_model(tf.constant(text_test))
print(tf.sigmoid(bert_raw_result))
tf.Tensor([[0.5588537]], shape=(1, 1), dtype=float32)

ผลลัพธ์ไม่มีความหมายแน่นอนเพราะโมเดลยังไม่ได้รับการฝึกฝน

มาดูโครงสร้างของแบบจำลองกัน

tf.keras.utils.plot_model(classifier_model)

png

การฝึกอบรมแบบจำลอง

ตอนนี้คุณมีชิ้นส่วนทั้งหมดในการฝึกโมเดลรวมถึงโมดูลการประมวลผลก่อนการประมวลผลตัวเข้ารหัส BERT ข้อมูลและตัวแยกประเภท

ฟังก์ชั่นการสูญเสีย

เนื่องจากปัญหานี้เป็นปัญหาการจำแนกไบนารีและโมเดลแสดงความน่าจะเป็น (เลเยอร์หน่วยเดียว) คุณจะใช้การสูญเสียฟังก์ชันการสูญเสีย losses.BinaryCrossentropy

loss = tf.keras.losses.BinaryCrossentropy(from_logits=True)
metrics = tf.metrics.BinaryAccuracy()

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

สำหรับการปรับแต่งอย่างละเอียดลองใช้เครื่องมือเพิ่มประสิทธิภาพเดียวกับที่ BERT ได้รับการฝึกฝนมาก่อนนั่นคือ "ช่วงเวลาที่ปรับเปลี่ยนได้" (Adam) เครื่องมือเพิ่มประสิทธิภาพนี้ช่วยลดการสูญเสียการคาดการณ์และทำการทำให้เป็นมาตรฐานโดยการลดน้ำหนัก (ไม่ใช้ช่วงเวลา) ซึ่งเรียกอีกอย่างว่า AdamW

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

epochs = 5
steps_per_epoch = tf.data.experimental.cardinality(train_ds).numpy()
num_train_steps = steps_per_epoch * epochs
num_warmup_steps = int(0.1*num_train_steps)

init_lr = 3e-5
optimizer = optimization.create_optimizer(init_lr=init_lr,
                                          num_train_steps=num_train_steps,
                                          num_warmup_steps=num_warmup_steps,
                                          optimizer_type='adamw')

กำลังโหลดแบบจำลอง BERT และการฝึกอบรม

การใช้ classifier_model คุณสร้างไว้ก่อนหน้านี้คุณสามารถคอมไพล์โมเดลด้วยการสูญเสียเมตริกและเครื่องมือเพิ่มประสิทธิภาพ

classifier_model.compile(optimizer=optimizer,
                         loss=loss,
                         metrics=metrics)
print(f'Training model with {tfhub_handle_encoder}')
history = classifier_model.fit(x=train_ds,
                               validation_data=val_ds,
                               epochs=epochs)
Training model with https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-4_H-512_A-8/1
Epoch 1/5
625/625 [==============================] - 93s 140ms/step - loss: 0.5837 - binary_accuracy: 0.6626 - val_loss: 0.4231 - val_binary_accuracy: 0.8318
Epoch 2/5
625/625 [==============================] - 88s 140ms/step - loss: 0.3558 - binary_accuracy: 0.8365 - val_loss: 0.3813 - val_binary_accuracy: 0.8438
Epoch 3/5
625/625 [==============================] - 88s 141ms/step - loss: 0.2748 - binary_accuracy: 0.8825 - val_loss: 0.3932 - val_binary_accuracy: 0.8470
Epoch 4/5
625/625 [==============================] - 88s 141ms/step - loss: 0.2029 - binary_accuracy: 0.9200 - val_loss: 0.4420 - val_binary_accuracy: 0.8532
Epoch 5/5
625/625 [==============================] - 87s 139ms/step - loss: 0.1607 - binary_accuracy: 0.9403 - val_loss: 0.4783 - val_binary_accuracy: 0.8504

ประเมินแบบจำลอง

มาดูกันว่าแบบจำลองมีประสิทธิภาพอย่างไร ค่าสองค่าจะถูกส่งกลับ การสูญเสีย (ตัวเลขที่แสดงถึงข้อผิดพลาดค่าที่ต่ำกว่าจะดีกว่า) และความแม่นยำ

loss, accuracy = classifier_model.evaluate(test_ds)

print(f'Loss: {loss}')
print(f'Accuracy: {accuracy}')
782/782 [==============================] - 63s 80ms/step - loss: 0.4651 - binary_accuracy: 0.8541
Loss: 0.4651116132736206
Accuracy: 0.8541200160980225

พล็อตความถูกต้องและการสูญเสียเมื่อเวลาผ่านไป

ขึ้นอยู่กับวัตถุ History ส่งคืนโดย model.fit() คุณสามารถวางแผนการสูญเสียการฝึกอบรมและการตรวจสอบความถูกต้องเพื่อเปรียบเทียบรวมทั้งการฝึกอบรมและความถูกต้องของการตรวจสอบความถูกต้อง:

history_dict = history.history
print(history_dict.keys())

acc = history_dict['binary_accuracy']
val_acc = history_dict['val_binary_accuracy']
loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs = range(1, len(acc) + 1)
fig = plt.figure(figsize=(10, 6))
fig.tight_layout()

plt.subplot(2, 1, 1)
# "bo" is for "blue dot"
plt.plot(epochs, loss, 'r', label='Training loss')
# b is for "solid blue line"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
# plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.subplot(2, 1, 2)
plt.plot(epochs, acc, 'r', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')
dict_keys(['loss', 'binary_accuracy', 'val_loss', 'val_binary_accuracy'])
<matplotlib.legend.Legend at 0x7f884cfea160>

png

ในพล็อตนี้เส้นสีแดงแสดงถึงการสูญเสียและความแม่นยำในการฝึกและเส้นสีน้ำเงินคือการสูญเสียการตรวจสอบความถูกต้องและความแม่นยำ

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

ตอนนี้คุณแค่บันทึกโมเดลที่ปรับแต่งแล้วของคุณเพื่อใช้ในภายหลัง

dataset_name = 'imdb'
saved_model_path = './{}_bert'.format(dataset_name.replace('/', '_'))

classifier_model.save(saved_model_path, include_optimizer=False)
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 310). These functions will not be directly callable after loading.
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 310). These functions will not be directly callable after loading.

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

reloaded_model = tf.saved_model.load(saved_model_path)

ที่นี่คุณสามารถทดสอบโมเดลของคุณกับประโยคใดก็ได้ที่คุณต้องการเพียงเพิ่มตัวแปรตัวอย่างด้านล่าง

def print_my_examples(inputs, results):
  result_for_printing = \
    [f'input: {inputs[i]:<30} : score: {results[i][0]:.6f}'
                         for i in range(len(inputs))]
  print(*result_for_printing, sep='\n')
  print()


examples = [
    'this is such an amazing movie!',  # this is the same sentence tried earlier
    'The movie was great!',
    'The movie was meh.',
    'The movie was okish.',
    'The movie was terrible...'
]

reloaded_results = tf.sigmoid(reloaded_model(tf.constant(examples)))
original_results = tf.sigmoid(classifier_model(tf.constant(examples)))

print('Results from the saved model:')
print_my_examples(examples, reloaded_results)
print('Results from the model in memory:')
print_my_examples(examples, original_results)
Results from the saved model:
input: this is such an amazing movie! : score: 0.999509
input: The movie was great!           : score: 0.994210
input: The movie was meh.             : score: 0.892940
input: The movie was okish.           : score: 0.021850
input: The movie was terrible...      : score: 0.001355

Results from the model in memory:
input: this is such an amazing movie! : score: 0.999509
input: The movie was great!           : score: 0.994210
input: The movie was meh.             : score: 0.892940
input: The movie was okish.           : score: 0.021850
input: The movie was terrible...      : score: 0.001355

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

serving_results = reloaded_model \
            .signatures['serving_default'](tf.constant(examples))

serving_results = tf.sigmoid(serving_results['classifier'])

print_my_examples(examples, serving_results)
input: this is such an amazing movie! : score: 0.999509
input: The movie was great!           : score: 0.994210
input: The movie was meh.             : score: 0.892940
input: The movie was okish.           : score: 0.021850
input: The movie was terrible...      : score: 0.001355

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

ในขั้นตอนต่อไปคุณสามารถลอง แก้งาน GLUE โดยใช้ BERT ในบทช่วยสอน TPU ซึ่งทำงานบน TPU และแสดงวิธีทำงานกับอินพุตหลายรายการ