सहायता Kaggle पर TensorFlow साथ ग्रेट बैरियर रीफ की रक्षा चैलेंज में शामिल हों

BERT मॉडल को फ़ाइन-ट्यूनिंग

TensorFlow.org पर देखें GitHub पर स्रोत देखें नोटबुक डाउनलोड करें टीएफ हब मॉडल देखें

इस उदाहरण में, हम टेंसरफ़्लो-मॉडल PIP पैकेज का उपयोग करके BERT मॉडल को फ़ाइन-ट्यूनिंग करके काम करेंगे।

Pretrained बर्ट मॉडल इस ट्यूटोरियल पर आधारित है भी पर उपलब्ध है TensorFlow हब है कि यह कैसे को देखें उपयोग करने के लिए देखने के लिए, हब परिशिष्ट

सेट अप

TensorFlow मॉडल गार्डन पाइप पैकेज स्थापित करें

  • tf-models-official स्थिर मॉडल गार्डन पैकेज है। नोट यह क्षेत्र में नवीनतम परिवर्तनों को शामिल नहीं हो सकता है कि tensorflow_models GitHub रेपो। नवीनतम परिवर्तनों में शामिल करने के लिए आप स्थापित कर सकते हैं tf-models-nightly है, जो दैनिक स्वचालित रूप से बनाया हर रात को मॉडल गार्डन पैकेज है।
  • पाइप स्वचालित रूप से सभी मॉडलों और निर्भरताओं को स्थापित करेगा।
pip install -q -U tensorflow-text
pip install -q tf-models-official==2.4.0

आयात

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.7/site-packages/pkg_resources/__init__.py:119: PkgResourcesDeprecationWarning: 0.18ubuntu0.18.04.1 is an invalid version and will not be supported in a future release
  PkgResourcesDeprecationWarning,

साधन

इस निर्देशिका में इस ट्यूटोरियल में प्रयुक्त कॉन्फ़िगरेशन, शब्दावली और एक पूर्व-प्रशिक्षित चेकपॉइंट है:

gs_folder_bert = "gs://cloud-tpu-checkpoints/bert/v3/uncased_L-12_H-768_A-12"
tf.io.gfile.listdir(gs_folder_bert)
['bert_config.json',
 'bert_model.ckpt.data-00000-of-00001',
 'bert_model.ckpt.index',
 'vocab.txt']

आप से एक पूर्व प्रशिक्षित बर्ट एनकोडर प्राप्त कर सकते हैं TensorFlow हब :

hub_url_bert = "https://hub.tensorflow.google.cn/tensorflow/bert_en_uncased_L-12_H-768_A-12/3"

आँकड़े

इस उदाहरण के लिए हम इस्तेमाल किया TFDS से गोंद MRPC डाटासेट

यह डेटासेट सेट अप नहीं किया गया है ताकि इसे सीधे BERT मॉडल में फीड किया जा सके, इसलिए यह सेक्शन आवश्यक प्रीप्रोसेसिंग को भी हैंडल करता है।

TensorFlow डेटासेट से डेटासेट प्राप्त करें

माइक्रोसॉफ्ट रिसर्च पैराफ्रेज कॉर्पस (डोलन एंड ब्रोकेट, 2005) ऑनलाइन समाचार स्रोतों से स्वचालित रूप से निकाले गए वाक्य जोड़े का एक संग्रह है, जिसमें मानव एनोटेशन के साथ जोड़ा गया है कि जोड़ी में वाक्य शब्दार्थ समकक्ष हैं या नहीं।

  • लेबल की संख्या: 2.
  • प्रशिक्षण डेटासेट का आकार: 3668.
  • मूल्यांकन डेटासेट का आकार: 408।
  • प्रशिक्षण और मूल्यांकन डेटासेट की अधिकतम अनुक्रम लंबाई: 128।
glue, info = tfds.load('glue/mrpc', with_info=True,
                       # It's small, load the whole dataset
                       batch_size=-1)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_datasets/core/dataset_builder.py:622: get_single_element (from tensorflow.python.data.experimental.ops.get_single_element) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.data.Dataset.get_single_element()`.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_datasets/core/dataset_builder.py:622: get_single_element (from tensorflow.python.data.experimental.ops.get_single_element) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.data.Dataset.get_single_element()`.
list(glue.keys())
['train', 'validation', 'test']

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

BERT टोकननाइज़र

पूर्व-प्रशिक्षित मॉडल को ठीक करने के लिए आपको यह सुनिश्चित करने की आवश्यकता है कि आप ठीक उसी टोकननाइज़ेशन, शब्दावली और इंडेक्स मैपिंग का उपयोग कर रहे हैं जैसा आपने प्रशिक्षण के दौरान किया था।

इस ट्यूटोरियल में प्रयुक्त BERT टोकनेज़र शुद्ध पायथन में लिखा गया है (यह TensorFlow ops से निर्मित नहीं है)। तो अगर आप बस इसे अपने मॉडल में एक के रूप में प्लग नहीं कर सकते keras.layer की तरह आप के साथ कर सकते हैं preprocessing.TextVectorization

निम्न कोड टोकननाइज़र का पुनर्निर्माण करता है जिसका उपयोग बेस मॉडल द्वारा किया गया था:

# 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

एक वाक्य को टोकननाइज़ करें:

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

डेटा को प्रीप्रोसेस करें

अनुभाग मैन्युअल रूप से मॉडल द्वारा अपेक्षित प्रारूप में डेटासेट को प्रीप्रोसेस करता है।

यह डेटासेट छोटा है, इसलिए मेमोरी में प्रीप्रोसेसिंग जल्दी और आसानी से की जा सकती है। बड़े डेटासेट के लिए tf_models पुस्तकालय preprocessing और एक डाटासेट फिर से serializing के लिए कुछ उपकरण भी शामिल है। देखें परिशिष्ट: एक बड़े डाटासेट फिर से एन्कोडिंग जानकारी के लिए।

वाक्यों को एनकोड करें

मॉडल को उम्मीद है कि इसके दो इनपुट वाक्यों को एक साथ जोड़ा जाएगा। इस इनपुट के साथ एक शुरू करने के लिए आशा की जाती है [CLS] टोकन "यह एक वर्गीकरण समस्या है", और प्रत्येक वाक्य के साथ समाप्त करना चाहिए [SEP] "विभाजक" टोकन:

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

सभी वाक्य एन्कोडिंग जोड़कर, जबकि एक द्वारा शुरू [SEP] टोकन, और उन्हें प्रचंड-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]

अब पहले जोड़ें एक [CLS] टोकन और प्रचंड tensors श्रेणीबद्ध एक भी फार्म का 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 padding नहीं है।

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

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

पीएनजी

"इनपुट प्रकार" भी एक ही आकार है, लेकिन गैर गद्देदार क्षेत्र के अंदर मौजूद है, जिसमें एक 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 0x7fa1cc682490>

पीएनजी

यह सब एक साथ डालें

एक भी समारोह में ऊपर पाठ पार्स कोड एकत्रित करें, और से प्रत्येक विभाजन में इसे लागू 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 उदाहरणों के परीक्षण बैच पर चलाएँ। आउटपुट दो वर्गों के लिए लॉग है:

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

bert_classifier(
    glue_batch, training=True
).numpy()
array([[ 0.10071337,  0.05758326],
       [ 0.05382514,  0.30056837],
       [ 0.00795104,  0.1443476 ],
       [ 0.03538848, -0.04541291],
       [ 0.0905486 ,  0.3010756 ],
       [-0.09503749,  0.26234314],
       [-0.00378452,  0.19791688],
       [-0.09037939,  0.2433937 ],
       [-0.03041902,  0.07568075],
       [ 0.30516896,  0.08384045]], dtype=float32)

TransformerEncoder वर्गीकारक के केंद्र में ऊपर है bert_encoder

एनकोडर का निरीक्षण करने से हम देखते हैं की अपनी ढेर Transformer परतों उन्हीं तीन आदानों से जुड़ा:

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

पीएनजी

एन्कोडर वज़न पुनर्स्थापित करें

जब एन्कोडर बनाया जाता है तो यादृच्छिक रूप से प्रारंभ किया जाता है। एनकोडर के वज़न को चेकपॉइंट से पुनर्स्थापित करें:

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

ऑप्टिमाइज़र सेट करें

बर्ट वजन क्षय (उर्फ "के साथ एडम अनुकूलक को गोद ले 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 [==============================] - 37s 220ms/step - loss: 0.5972 - accuracy: 0.7034 - val_loss: 0.4941 - val_accuracy: 0.7794
Epoch 2/3
115/115 [==============================] - 24s 211ms/step - loss: 0.4228 - accuracy: 0.8171 - val_loss: 0.4503 - val_accuracy: 0.8137
Epoch 3/3
115/115 [==============================] - 24s 211ms/step - loss: 0.2852 - accuracy: 0.8956 - val_loss: 0.4061 - val_accuracy: 0.8162
<keras.callbacks.History at 0x7fa1884d0b50>

अब यह देखने के लिए कि यह काम करता है, कस्टम उदाहरण पर फ़ाइन-ट्यून किए गए मॉडल को चलाएँ।

कुछ वाक्य युग्मों को कूटबद्ध करके प्रारंभ करें:

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)
2021-11-12 13:12:55.273917: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
WARNING:absl:Found untraced functions such as self_attention_layer_call_fn, self_attention_layer_call_and_return_conditional_losses, dropout_layer_call_fn, dropout_layer_call_and_return_conditional_losses, self_attention_layer_norm_layer_call_fn while saving (showing 5 of 900). These functions will not be directly callable after loading.
INFO:tensorflow:Assets written to: ./saved_model/assets
INFO:tensorflow:Assets written to: ./saved_model/assets
reloaded = tf.saved_model.load(export_dir)
reloaded_result = reloaded([my_examples['input_word_ids'],
                            my_examples['input_mask'],
                            my_examples['input_type_ids']], training=False)

original_result = bert_classifier(my_examples, training=False)

# The results are (nearly) identical:
print(original_result.numpy())
print()
print(reloaded_result.numpy())
[[-1.0493996   1.3163755 ]
 [ 0.674296   -0.87380654]]

[[-1.0493993  1.3163751]
 [ 0.6742962 -0.873807 ]]

अनुबंध

एक बड़े डेटासेट को फिर से एन्कोड करना

इस ट्यूटोरियल में आपने स्पष्टता के लिए डेटासेट को मेमोरी में फिर से एन्कोड किया है।

यह तभी संभव था, क्योंकि 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.AUTOTUNE)
  dataset = dataset.map(
      _select_data_from_record,
      num_parallel_calls=tf.data.AUTOTUNE)
  dataset = dataset.batch(batch_size, drop_remainder=is_training)
  dataset = dataset.prefetch(tf.data.AUTOTUNE)
  return dataset
# Set up batch sizes
batch_size = 32
eval_batch_size = 32

# Return Tensorflow dataset
training_dataset = create_classifier_dataset(
    train_data_output_path,
    input_meta_data['max_seq_length'],
    batch_size,
    is_training=True)

evaluation_dataset = create_classifier_dataset(
    eval_data_output_path,
    input_meta_data['max_seq_length'],
    eval_batch_size,
    is_training=False)
training_dataset.element_spec
({'input_word_ids': TensorSpec(shape=(32, 128), dtype=tf.int64, name=None),
  'input_mask': TensorSpec(shape=(32, 128), dtype=tf.int64, name=None),
  'input_type_ids': TensorSpec(shape=(32, 128), dtype=tf.int64, name=None)},
 TensorSpec(shape=(32,), dtype=tf.int64, name=None))

TFHub पर TFमॉडल BERT

आप प्राप्त कर सकते हैं बर्ट मॉडल से शेल्फ से TFHub । यह इस के शीर्ष पर एक वर्गीकरण सिर जोड़ने के लिए कठिन नहीं होगा hub.KerasLayer

# Note: 350MB download.
import tensorflow_hub as hub

hub_encoder = hub.KerasLayer(f"https://hub.tensorflow.google.cn/tensorflow/{hub_model_name}/3",
                             trainable=True)

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

परीक्षण इसे डेटा के एक बैच पर चलाएँ:

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

print("Pooled output shape:", result['pooled_output'].shape)
print("Sequence output shape:", result['sequence_output'].shape)
Pooled output shape: (10, 768)
Sequence output shape: (10, 103, 768)

इस बिंदु पर स्वयं एक वर्गीकरण शीर्ष जोड़ना आसान होगा।

bert_models.classifier_model समारोह भी TensorFlow हब से एनकोडर पर एक वर्गीकारक निर्माण कर सकते हैं:

hub_classifier = nlp.modeling.models.BertClassifier(
    bert_encoder,
    num_classes=2,
    dropout_rate=0.1,
    initializer=tf.keras.initializers.TruncatedNormal(
        stddev=0.02))

इस मॉडल को TFHub से लोड करने का एक नकारात्मक पहलू यह है कि आंतरिक केरस परतों की संरचना को पुनर्स्थापित नहीं किया जाता है। इसलिए मॉडल का निरीक्षण या संशोधन करना अधिक कठिन है। BertEncoder मॉडल अब एक परत है:

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.BertEncoder और nlp.modeling.models.BertClassifier कक्षाएं। बस याद रखें कि यदि आप आर्किटेक्चर को संशोधित करना शुरू करते हैं तो पूर्व-प्रशिक्षित चेकपॉइंट को फिर से लोड करना सही या संभव नहीं हो सकता है, इसलिए आपको स्क्रैच से फिर से प्रशिक्षित करने की आवश्यकता होगी।

एन्कोडर बनाएं:

bert_encoder_config = config_dict.copy()

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

bert_encoder_config
{'hidden_size': 768,
 'intermediate_size': 3072,
 'num_attention_heads': 12,
 'type_vocab_size': 2,
 'vocab_size': 30522,
 'attention_dropout_rate': 0.1,
 'activation': <function official.modeling.activations.gelu.gelu(x)>,
 'dropout_rate': 0.1,
 'initializer': <keras.initializers.initializers_v2.TruncatedNormal at 0x7f9d1011da50>,
 'max_sequence_length': 512,
 'num_layers': 12}
manual_encoder = nlp.modeling.networks.BertEncoder(**bert_encoder_config)

वजन बहाल करें:

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

परीक्षण इसे चलाएँ:

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=bert_encoder_config['dropout_rate'],
        initializer=bert_encoder_config['initializer'])
manual_classifier(my_examples, training=True).numpy()
array([[-0.23401603, -0.3458405 ],
       [ 0.2552695 , -0.28906718]], 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 0x7f9d11235d90>]

पीएनजी

यह, बारी में एक में लपेटा जाता है 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 0x7f9d109551d0>]

पीएनजी

फिर बनाने 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'])