ترجمت واجهة Cloud Translation API‏ هذه الصفحة.
Switch to English

نموذج بيرت صقل

عرض على TensorFlow.org تشغيل في جوجل Colab عرض المصدر على جيثب تحميل دفتر

في هذا المثال، سوف نعمل من خلال صقل نموذج بيرت باستخدام حزمة PIP نماذج tensorflow.

نموذج بيرت pretrained ويستند هذا البرنامج التعليمي على متاح في أيضا TensorFlow محور ، لمعرفة كيفية استخدامها الرجوع إلى محور الملحق

اقامة

تثبيت حزمة نقطة TensorFlow نموذج حديقة

  • tf-models-nightly هو حزمة نموذج حديقة ليلا إنشاؤها يوميا تلقائيا.
  • ونقطة تثبيت كافة النماذج والتبعيات تلقائيا.
pip install -q tf-nightly
pip install -q tf-models-nightly

واردات

 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,

مصادر

يحتوي هذا الدليل على التكوين، والمفردات، ونقطة تفتيش تابعة للمدربين قبل المستخدمة في هذا البرنامج التعليمي:

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

يمكنك الحصول على المدربين قبل بيرت التشفير من TensorFlow المحور هنا:

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

البيانات

في هذا المثال استخدمنا بيانات GLUE MRPC من TFDS .

لم يتم تعيين هذه البينات يصل بحيث يمكن تغذية مباشرة في نموذج بيرت، بحيث يعالج هذا القسم أيضا تجهيزها اللازم.

الحصول على بيانات من TensorFlow مجموعات البيانات

في مايكروسوفت للبحوث الصياغه كوربوس (دولان وBrockett، 2005) هو جسم من أزواج الجملة المستخرجة تلقائيا من مصادر الأخبار على شبكة الإنترنت، مع شروح الإنسان عن ما إذا كان الجمل في الزوج تعادل غويا.

  • عدد التسميات: 2.
  • حجم بيانات التدريب: 3668.
  • حجم بيانات التقييم: 408.
  • الحد الأقصى لطول سلسلة من التدريب وتقييم مجموعة البيانات: 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']

و info يصف كائن مجموعة البيانات وانها الميزات:

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

فئتين هي:

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

هنا هو مثال واحد من مجموعة التدريب:

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

وtokenizer بيرت

لضبط نموذجا المدربين قبل تحتاج للتأكد من أن كنت تستخدم بالضبط نفس tokenization، والمفردات، ورسم مؤشر وأنت تستخدم أثناء التدريب.

وtokenizer بيرت المستخدمة في هذا البرنامج التعليمي هو مكتوب في بيثون النقي (انها ليست مبنية من التقاط TensorFlow). لذلك لا يمكن إلا أن تركبه في نموذج ك keras.layer مثل يمكنك مع preprocessing.TextVectorization .

التعليمة البرمجية التالية يعيد بناء وtokenizer التي تم استخدامها من قبل نموذج قاعدة:

 # 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 الجملة:

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

المعالجة المسبقة البيانات

قسم preprocessed يدويا مجموعة البيانات في شكل المتوقعة من هذا النموذج.

هذه البينات صغير، لذلك يمكن أن يتم تجهيزها بسرعة وسهولة في الذاكرة. لمجموعات البيانات الكبيرة و tf_models تتضمن مكتبة بعض الأدوات لتجهيزها وإعادة تسلسل واحد البيانات. انظر الملحق: إعادة ترميز بيانات كبيرة للحصول على التفاصيل.

ترميز الجمل

ويتوقع نموذج جملتين المدخلات على أن تكون متصلا معا. ومن المتوقع أن تبدأ مع هذه المدخلات [CLS] "هذه هي مشكلة تصنيف" رمزية، ويجب أن تنتهي كل جملة مع [SEP] "فاصل" رمز:

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

تبدأ من خلال ترميز كل الجمل في حين إلحاق [SEP] رمز، وتعبئتها في-التنسورات خشنة:

 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]

الآن أرفقت [CLS] رمز، وسلسلة من التنسورات خشنة لتشكيل واحد input_word_ids موتر لكل المثال. RaggedTensor.to_tensor() صفر منصات لأطول تسلسل.

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

بي إن جي

قناع وإدخال نوع

ويتوقع نموذج اثنين من المدخلات إضافية:

  • قناع الإدخال
  • نوع الإدخال

قناع يسمح النموذج ليفرق نظيفة بين المحتوى والحشو. قناع لديه نفس شكل input_word_ids ، ويحتوي على 1 في أي مكان input_word_ids لا الحشو.

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

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

بي إن جي

"نوع إدخال" أيضا لديه نفس الشكل، ولكن داخل المنطقة غير مبطن، ويحتوي على 0 أو 1 يشير إلى الذي حكم الرمز المميز هو جزء من.

 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>

بي إن جي

ضعها سوية

جمع ما سبق توزيع التعليمات البرمجية النصية إلى وظيفة واحدة، وتطبيقه على كل انقسام glue/mrpc البيانات.

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

وقد تم تحويل كل مجموعة فرعية من البيانات إلى القاموس من الميزات، ومجموعة من العلامات. كل ميزة في القاموس المدخلات له نفس الشكل، ويجب أن يتطابق مع عدد من العلامات:

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

الموديل

بناء نموذج

وتتمثل الخطوة الأولى لتحميل التكوين لنموذج المدربين قبل.

 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 يحدد جوهر بيرت النموذجي، الذي هو نموذج للتنبؤ Keras مخرجات num_classes من المدخلات مع أقصى تسلسل طول max_seq_length .

هذه الدالة تقوم بإرجاع كل من التشفير والمصنف.

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

المصنف ثلاثة مدخلات والمخرجات واحد:

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

بي إن جي

تشغيله على دفعة اختبار البيانات 10 أمثلة من مجموعة التدريب. الإخراج هو logits لفئتين:

 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)

و TransformerEncoder في وسط المصنف سبق هو bert_encoder .

يتفقد التشفير، ونحن نرى المكدس من Transformer طبقات متصلة نفس تلك ثلاثة مداخل:

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

بي إن جي

استعادة الأوزان التشفير

عندما بنيت تتم تهيئة التشفير عشوائيا. استعادة الأوزان التشفير من نقطة التفتيش:

 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>

إعداد محسن

بيرت يتبنى محسن آدم مع الوزن الاضمحلال (ويعرف أيضا باسم " AdamW "). ويعمل أيضا جدول زمني معدل التعلم التي أولا ارتفاع درجة حرارة تصل من 0 ثم يضمحل إلى 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)
 

هذا إلى ظهور AdamWeightDecay محسن مع مجموعة جدول معدل التعلم:

 type(optimizer)
 
official.nlp.optimization.AdamWeightDecay

لمشاهدة مثال لكيفية تخصيص محسن والجدول الزمني انها، راجع محسن جدول الملحق .

تدريب نموذج

متري هو الدقة ونستخدم القاطع متفرق عبر الكون كما الخسارة.

 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>

الآن تشغيل نموذج صقلها على سبيل المثال مخصص لنرى أن يعمل.

تبدأ من خلال ترميز بعض أزواج الجملة:

 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)
 

نموذج يجب أن التقرير الطبقة 1 "مباراة" لأول مثال والدرجة 0 "عدم تطابق" للمرة الثانية:

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

حفظ نموذج

غالبا ما يكون الهدف من تدريب النموذج هو لاستخدامها لشيء، لذلك تصدير نموذج ومن ثم استعادته للتأكد من أنه يعمل.

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

الملحق

إعادة ترميز بيانات كبيرة

هذا البرنامج التعليمي يجب إعادة ترميز مجموعة البيانات في الذاكرة، لوضوح.

وكان هذا ممكنا فقط لأن glue/mrpc هو مجموعة بيانات صغيرة جدا. للتعامل مع قواعد البيانات الكبيرة tf_models مكتبة تضم بعض الأدوات لمعالجة وإعادة ترميز مجموعة بيانات للتدريب الفعال.

وتتمثل الخطوة الأولى لوصف أي ميزات مجموعة البيانات يجب أن تتحول:

 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)
 

ثم تطبيق التحول لإنشاء ملفات TFRecord جديدة.

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

وأخيرا إنشاء tf.data أنابيب المدخلات من تلك الملفات 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)()

 

الناتج tf.data.Datasets عودة (features, labels) أزواج، كما هو متوقع من قبل 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))

إنشاء tf.data.Dataset للتدريب والتقييم

إذا كنت بحاجة إلى تعديل تحميل البيانات هنا هي بعض رمز للحصول على انك بدأته:

 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 بيرت على TFHub

يمكنك الحصول على نموذج بيرت من على الرف من TFHub . فإنه لن يكون من الصعب لإضافة رأس التصنيف على رأس هذه 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

اختبار تشغيلها على مجموعة من البيانات:

 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)

عند هذه النقطة سيكون بسيطة لإضافة رأس تصنيف نفسك.

و bert_models.classifier_model وظيفة يمكن أيضا بناء المصنف على التشفير من TensorFlow المحور:

 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)
 

الجانب السلبي واحدة لتحميل هذا النموذج من TFHub هو أن هيكل keras الداخلية طبقات لا يتم استعادة. لذلك فمن أكثر صعوبة للتفتيش أو تعديل هذا النموذج. و TransformerEncoder النموذج هو الآن طبقة واحدة:

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

بي إن جي

 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'

بناء نموذج مستوى منخفض

إذا كنت في حاجة الى المزيد من السيطرة على بناء نموذج ومن الجدير بالذكر أن classifier_model وظيفة استخدمت في وقت سابق هو في الحقيقة مجرد غلاف رقيق على nlp.modeling.networks.TransformerEncoder و nlp.modeling.models.BertClassifier الطبقات. فقط تذكر أنه إذا كنت بدء تعديل الهيكل قد لا تكون صحيحة أو من الممكن تحميل حاجز المدربين قبل ذلك ستحتاج إلى إعادة تدريب من الصفر.

بناء التشفير:

 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)
 

استعادة الأوزان:

 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>

اختبار تشغيلها:

 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)

التفاف عليه في المصنف:

 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)

أبتيميزر والجداول الزمنية

تم إنشاء محسن تستخدم لتدريب نموذج باستخدام nlp.optimization.create_optimizer وظيفة:

 optimizer = nlp.optimization.create_optimizer(
    2e-5, num_train_steps=num_train_steps, num_warmup_steps=warmup_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
 
 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>]

بي إن جي

هذا، بدوره ملفوفة في WarmUp الجدول الذي خطيا يزيد من معدل التعلم إلى القيمة المستهدفة خلال أول 10٪ من التدريب:

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

بي إن جي

ثم خلق nlp.optimization.AdamWeightDecay باستخدام هذا الجدول الزمني، وتهيئتها لنموذج بيرت:

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