حل مهام الغراء باستخدام BERT على TPU

عرض على TensorFlow.org تشغيل في Google Colab عرض على جيثب تحميل دفتر انظر نموذج TF Hub

يمكن استخدام BERT لحل العديد من المشكلات في معالجة اللغة الطبيعية. سوف تتعلم كيفية ضبط BERT للعديد من المهام من معيار GLUE :

  1. CoLA (مجموعة القبول اللغوي): هل الجملة صحيحة نحويًا؟

  2. SST-2 (Stanford Sentiment Treebank): المهمة هي التنبؤ بمشاعر جملة معينة.

  3. MRPC (مجموعة أبحاث Microsoft Research Paraphrase Corpus): حدد ما إذا كان زوج من الجمل متكافئًا دلاليًا.

  4. QQP ( Quora Question Pairs2): حدد ما إذا كان زوج من الأسئلة مكافئًا لغويًا.

  5. MNLI (استدلال اللغة الطبيعية متعدد الأنواع ): بالنظر إلى جملة فرضية وجملة فرضية ، فإن المهمة هي التنبؤ بما إذا كانت الفرضية تستلزم الفرضية (الاستنتاج) ، أو تتعارض مع الفرضية (التناقض) ، أو لا (محايدة).

  6. QNLI (استدلال اللغة الطبيعية للإجابة على الأسئلة): المهمة هي تحديد ما إذا كانت جملة السياق تحتوي على إجابة السؤال.

  7. RTE (التعرف على الاستحقاق النصي): تحديد ما إذا كانت الجملة تستلزم فرضية معينة أم لا.

  8. WNLI (استدلال اللغة الطبيعية في Winograd ): المهمة هي التنبؤ بما إذا كانت الجملة التي تحتوي على الضمير المستبدل تستلزمها الجملة الأصلية.

يحتوي هذا البرنامج التعليمي على رمز كامل شامل لتدريب هذه النماذج على TPU. يمكنك أيضًا تشغيل هذا الكمبيوتر الدفتري على وحدة معالجة الرسومات ، عن طريق تغيير سطر واحد (كما هو موضح أدناه).

في هذا دفتر الملاحظات ، سوف:

  • قم بتحميل نموذج BERT من TensorFlow Hub
  • اختر إحدى مهام GLUE وقم بتنزيل مجموعة البيانات
  • المعالجة المسبقة للنص
  • ضبط BERT (يتم تقديم أمثلة لمجموعات البيانات المكونة من جملة واحدة ومتعددة الجمل)
  • احفظ النموذج المدرب واستخدمه

يثبت

ستستخدم نموذجًا منفصلاً للمعالجة المسبقة للنص قبل استخدامه لضبط BERT. يعتمد هذا النموذج على tensorflow / text ، والذي ستقوم بتثبيته أدناه.

pip install -q -U tensorflow-text

ستستخدم مُحسِّن AdamW من tensorflow / الطرز لضبط BERT ، والذي ستقوم بتثبيته أيضًا.

pip install -q -U tf-models-official
00bfaac23
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')

بعد ذلك ، قم بتكوين TFHub لقراءة نقاط التفتيش مباشرة من دلاء التخزين السحابي TFHub. يوصى بهذا فقط عند تشغيل طرازات TFHub على TPU.

بدون هذا الإعداد ، سيقوم TFHub بتنزيل الملف المضغوط واستخراج نقطة التفتيش محليًا. ستفشل محاولة التحميل من هذه الملفات المحلية بسبب الخطأ التالي:

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

وذلك لأن TPU لا يمكن القراءة مباشرة إلا من حاويات التخزين السحابي .

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

اتصل بعامل TPU

يتصل الكود التالي بعامل TPU ويغير جهاز TensorFlow الافتراضي إلى جهاز CPU على عامل TPU. كما تحدد أيضًا إستراتيجية توزيع TPU التي ستستخدمها لتوزيع تدريب النموذج على 8 نوى منفصلة لـ TPU المتاحة لعامل TPU هذا. راجع دليل TPU الخاص بـ TensorFlow لمزيد من المعلومات.

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.test.is_gpu_available():
  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 نفس بنية BERT (بثلاثة أحجام مختلفة) ، ولكن يتم تدريبها مسبقًا كمميز في إعداد يشبه شبكة الخصومة التوليدية (GAN).
  • يحتوي BERT مع Talking-Heads Attention و GELU [ قاعدة كبيرة ] على تحسينين في جوهر بنية المحولات.

راجع وثائق النموذج المرتبطة أعلاه لمزيد من التفاصيل.

في هذا البرنامج التعليمي ، ستبدأ بقاعدة BERT. يمكنك استخدام نماذج أكبر وأحدث للحصول على دقة أعلى ، أو نماذج أصغر لأوقات تدريب أسرع. لتغيير النموذج ، ما عليك سوى تبديل سطر واحد من التعليمات البرمجية (كما هو موضح أدناه). يتم تغليف جميع الاختلافات في 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 ، يتم استخدام نموذج المعالجة المسبقة المضمّن مباشرةً مع مشفر BERT.

يوضح هذا البرنامج التعليمي كيفية إجراء المعالجة المسبقة كجزء من خط أنابيب الإدخال الخاص بك للتدريب ، باستخدام Dataset.map ، ثم دمجها في النموذج الذي يتم تصديره للاستدلال. بهذه الطريقة ، يمكن أن يعمل كل من التدريب والاستنتاج من مدخلات النص الخام ، على الرغم من أن TPU نفسها تتطلب مدخلات رقمية.

بغض النظر عن متطلبات TPU ، يمكن أن تساعد الأداء في إجراء المعالجة المسبقة بشكل غير متزامن في خط أنابيب الإدخال (يمكنك معرفة المزيد في دليل أداء 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]]]>

يوفر كل نموذج معالجة .bert_pack_inputs(tensors, seq_length) أيضًا طريقة ، .bert_pack_inputs(tensors, seq_length) ، والتي تأخذ قائمة من الرموز المميزة (مثل tok أعلاه) .bert_pack_inputs(tensors, seq_length) طول التسلسل. يقوم هذا بحزم المدخلات لإنشاء قاموس للموترات بالتنسيق المتوقع بواسطة نموذج 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_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_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_type_ids', 'input_word_ids', 'input_mask']
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)
('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):
  inputs = dict(
      input_word_ids=tf.keras.layers.Input(shape=(None,), dtype=tf.int32),
      input_mask=tf.keras.layers.Input(shape=(None,), dtype=tf.int32),
      input_type_ids=tf.keras.layers.Input(shape=(None,), dtype=tf.int32),
  )

  encoder = hub.KerasLayer(tfhub_handle_encoder, trainable=True, name='encoder')
  net = encoder(inputs)['pooled_output']
  net = tf.keras.layers.Dropout(rate=0.1)(net)
  net = tf.keras.layers.Dense(num_classes, activation=None, name='classifier')(net)
  return tf.keras.Model(inputs, net, name='prediction')

دعنا نحاول تشغيل النموذج على بعض المدخلات المعالجة مسبقًا.

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

دعنا نلقي نظرة على هيكل النموذج. يمكنك رؤية مدخلات BERT الثلاثة المتوقعة.

tf.keras.utils.plot_model(test_classifier_model)
('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.')

اختر مهمة من GLUE

كنت تسير على استخدام TensorFlow DataSet من الغراء جناح المعيار.

يتيح لك 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 ['test', 'train', 'validation']
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

تدريب نموذجك

أخيرًا ، يمكنك تدريب النموذج من البداية إلى النهاية على مجموعة البيانات التي اخترتها.

توزيع

استرجع رمز الإعداد في الجزء العلوي ، والذي ربط وقت تشغيل colab بعامل TPU مع أجهزة TPU متعددة. لتوزيع التدريب عليهم ، ستقوم بإنشاء وتجميع نموذج Keras الرئيسي الخاص بك في نطاق استراتيجية توزيع TPU. (لمزيد من التفاصيل ، راجع التدريب الموزع مع Keras .)

من ناحية أخرى ، تعمل المعالجة المسبقة على وحدة المعالجة المركزية للمضيف العامل ، وليس وحدات TPU ، لذا فإن نموذج Keras للمعالجة المسبقة بالإضافة إلى مجموعات بيانات التدريب والتحقق التي تم تعيينها معها مبنية خارج نطاق استراتيجية التوزيع. Model.fit() استدعاء 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/tensorflow/python/keras/engine/functional.py:591: 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)
266/267 [============================>.] - ETA: 0s - loss: 0.5234 - MatthewsCorrelationCoefficient: 0.0000e+00
/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/metrics.py:257: UserWarning: Metric MatthewsCorrelationCoefficient implements a `reset_states()` method; rename it to `reset_state()` (without the final "s"). The name `reset_states()` has been deprecated to improve API consistency.
  'consistency.' % (self.__class__.__name__,))
267/267 [==============================] - 81s 73ms/step - loss: 0.5224 - MatthewsCorrelationCoefficient: 0.0000e+00 - val_loss: 0.5404 - val_MatthewsCorrelationCoefficient: 0.0000e+00
Epoch 2/3
267/267 [==============================] - 14s 54ms/step - loss: 0.3468 - MatthewsCorrelationCoefficient: 0.0000e+00 - val_loss: 0.6059 - val_MatthewsCorrelationCoefficient: 0.0000e+00
Epoch 3/3
267/267 [==============================] - 14s 54ms/step - loss: 0.2320 - MatthewsCorrelationCoefficient: 0.0000e+00 - val_loss: 0.6276 - val_MatthewsCorrelationCoefficient: 0.0000e+00

تصدير للاستدلال

ستنشئ نموذجًا نهائيًا يحتوي على جزء المعالجة المسبقة و BERT الدقيق الذي أنشأناه للتو.

في وقت الاستدلال ، يجب أن تكون المعالجة المسبقة جزءًا من النموذج (لأنه لم يعد هناك قائمة انتظار منفصلة للإدخال بالنسبة لبيانات التدريب التي تقوم بذلك). المعالجة المسبقة ليست مجرد حساب ؛ له موارده الخاصة (جدول المفردات) التي يجب إرفاقها بنموذج Keras الذي تم حفظه للتصدير. هذا التجميع النهائي هو ما سيتم حفظه.

ستحفظ النموذج على 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'the putter on the table left.']
This sentence is acceptable
BERT raw results: tf.Tensor([-1.9087534  2.614734 ], shape=(2,), dtype=float32)

sentence: [b'Doug cleared the table of dishes.']
This sentence is acceptable
BERT raw results: tf.Tensor([-2.746095   3.2254264], 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([-2.7611763  2.8297088], shape=(2,), dtype=float32)

sentence: [b'I presented it to John dead.']
This sentence is unacceptable
BERT raw results: tf.Tensor([ 2.3774471 -2.079125 ], shape=(2,), dtype=float32)

sentence: [b'The only thing capable of consuming this food has four legs and flies.']
This sentence is acceptable
BERT raw results: tf.Tensor([-1.4872739  1.9206202], 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'There was believed to have been a riot in the kitchen.'
This sentence is acceptable
BERT raw results: tf.Tensor([-3.196773   2.9193494], shape=(2,), dtype=float32)

sentence: b'Tom swam the English Channel because he believed that Suzy ex.'
This sentence is acceptable
BERT raw results: tf.Tensor([-1.2277479  1.9688965], shape=(2,), dtype=float32)

sentence: b'I was convinced by John to leave.'
This sentence is acceptable
BERT raw results: tf.Tensor([-1.669661   2.0653794], shape=(2,), dtype=float32)

sentence: b'I can find the baker in whom to place your trust.'
This sentence is acceptable
BERT raw results: tf.Tensor([-2.5297134  2.9251165], shape=(2,), dtype=float32)

sentence: b'John promised Bill to be examined.'
This sentence is unacceptable
BERT raw results: tf.Tensor([ 2.2290623 -1.1185381], shape=(2,), dtype=float32)

أنت فعلت ذلك! يمكن استخدام نموذجك المحفوظ للخدمة أو الاستدلال البسيط في عملية ما ، باستخدام واجهة برمجة تطبيقات أبسط برمز أقل وأسهل في الصيانة.

الخطوات التالية

الآن بعد أن جربت أحد نماذج BERT الأساسية ، يمكنك تجربة نماذج أخرى لتحقيق مزيد من الدقة أو ربما باستخدام إصدارات أصغر.

يمكنك أيضًا المحاولة في مجموعات البيانات الأخرى.