Zapisz datę! Google I / O powraca w dniach 18-20 maja Zarejestruj się teraz
Ta strona została przetłumaczona przez Cloud Translation API.
Switch to English

Rozwiązuj zadania KLEJU za pomocą BERT na TPU

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl w serwisie GitHub Pobierz notatnik Zobacz model piasty TF

BERT można wykorzystać do rozwiązania wielu problemów związanych z przetwarzaniem języka naturalnego. Dowiesz się, jak dostroić BERT do wielu zadań z benchmarku GLUE :

  1. CoLA (Corpus of Linguistic Acceptability): Czy zdanie jest poprawne gramatycznie?

  2. SST-2 (Stanford Sentiment Treebank): Zadanie polega na przewidywaniu nastroju danego zdania.

  3. MRPC (Microsoft Research Paraphrase Corpus): Określ, czy para zdań jest semantycznie równoważna.

  4. QQP (Quora Question Pairs2): Określ, czy para pytań jest semantycznie równoważna.

  5. MNLI (Multi-Genre Natural Language Inference): Biorąc pod uwagę zdanie zakładające i zdanie hipotezy, zadaniem jest przewidzenie, czy przesłanka pociąga za sobą hipotezę (wynikanie), zaprzecza hipotezie (sprzeczność), czy też żadna (neutralna).

  6. QNLI (wnioskowanie z języka naturalnego odpowiadające na pytania): Zadanie polega na ustaleniu, czy zdanie kontekstowe zawiera odpowiedź na pytanie.

  7. RTE (Recognizing Textual Entailment): Określ, czy zdanie pociąga za sobą daną hipotezę, czy nie.

  8. WNLI (Winograd Natural Language Inference): Zadanie polega na przewidywaniu, czy zdanie z podstawionym zaimkiem jest zawarte w zdaniu oryginalnym.

Ten samouczek zawiera pełny, kompleksowy kod do trenowania tych modeli na TPU. Możesz także uruchomić ten notebook na GPU, zmieniając jedną linię (opisaną poniżej).

W tym notatniku będziesz:

  • Załaduj model BERT z TensorFlow Hub
  • Wybierz jedno z zadań GLUE i pobierz zestaw danych
  • Przetwórz wstępnie tekst
  • Dostosuj BERT (przykłady podano dla zestawów danych zawierających jedno i wiele zdań)
  • Zapisz wytrenowany model i użyj go

Ustawiać

Użyjesz oddzielnego modelu do wstępnego przetworzenia tekstu przed użyciem go do dostrojenia BERT. Ten model zależy od tensorflow / text , które zainstalujesz poniżej.

pip install -q -U tensorflow-text

Użyjesz optymalizatora AdamW z tensorflow / models do dostrojenia BERT, który również zainstalujesz.

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

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

Następnie skonfiguruj TFHub do odczytywania punktów kontrolnych bezpośrednio z zasobników Cloud Storage TFHub. Jest to zalecane tylko w przypadku uruchamiania modeli TFHub na TPU.

Bez tego ustawienia TFHub pobierałby skompresowany plik i lokalnie wyodrębniał punkt kontrolny. Próba załadowania z tych plików lokalnych zakończy się niepowodzeniem z następującym błędem:

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

Dzieje się tak, ponieważ TPU może czytać tylko bezpośrednio z zasobników Cloud Storage .

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

Połącz się z pracownikiem TPU

Poniższy kod łączy się z procesem roboczym TPU i zmienia domyślne urządzenie TensorFlow na urządzenie procesora w module roboczym TPU. Definiuje również strategię dystrybucji TPU, której będziesz używać do dystrybucji szkolenia modelu na 8 oddzielnych rdzeni TPU dostępnych dla tego jednego pracownika TPU. Więcej informacji można znaleźć w przewodniku TensorFlow dotyczącym TPU .

import os

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

Ładowanie modeli z TensorFlow Hub

Tutaj możesz wybrać, który model BERT załadujesz z TensorFlow Hub i dostroić. Do wyboru jest wiele modeli BERT.

  • BERT-Base , Uncased i siedem innych modeli z wytrenowanymi ciężarami wydanymi przez oryginalnych autorów BERT.
  • Małe BERT mają tę samą ogólną architekturę, ale mniej i / lub mniejsze bloki transformatora, co pozwala odkrywać kompromisy między szybkością, rozmiarem i jakością.
  • ALBERT : cztery różne rozmiary „A Lite BERT”, które zmniejszają rozmiar modelu (ale nie czas obliczeń) poprzez współdzielenie parametrów między warstwami.
  • Eksperci BERT : osiem modeli, z których wszystkie mają architekturę bazową BERT, ale oferują wybór między różnymi dziedzinami przedtreningowymi, aby lepiej dostosować się do zadania docelowego.
  • Electra ma taką samą architekturę jak BERT (w trzech różnych rozmiarach), ale została wstępnie przeszkolona jako dyskryminator w konfiguracji przypominającej Generative Adversarial Network (GAN).
  • BERT z Talking-Heads Attention i Gated GELU [ podstawowy , duży ] ma dwa ulepszenia rdzenia architektury transformatora.

Więcej informacji można znaleźć w dokumentacji modelu, do której link znajduje się powyżej.

W tym samouczku zaczniesz od bazy BERT. Możesz używać większych i nowszych modeli w celu uzyskania większej dokładności lub mniejszych modeli w celu skrócenia czasu treningu. Aby zmienić model, wystarczy zamienić jeden wiersz kodu (pokazany poniżej). Wszystkie różnice są zawarte w modelu SavedModel, który można pobrać z TensorFlow Hub.

Wybierz model BERT do dopracowania

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

Przetwórz wstępnie tekst

W przypadku tekstu Classify with BERT colab model przetwarzania wstępnego jest używany bezpośrednio z koderem BERT.

W tym samouczku pokazano, jak wykonać wstępne przetwarzanie jako część potoku wejściowego do szkolenia, używając Dataset.map, a następnie scalić go z modelem, który jest eksportowany w celu wnioskowania. W ten sposób zarówno uczenie, jak i wnioskowanie mogą działać na podstawie danych wejściowych nieprzetworzonego tekstu, chociaż sam TPU wymaga danych liczbowych.

Pomijając wymagania TPU, może to pomóc wydajności w przetwarzaniu wstępnym wykonanym asynchronicznie w potoku wejściowym (możesz dowiedzieć się więcej w przewodniku po wydajności tf.data ).

W tym samouczku pokazano również, jak tworzyć modele z wieloma wejściami i jak dostosować długość sekwencji danych wejściowych do BERT.

Pokażmy model przetwarzania wstępnego.

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

Każdy model przetwarzania wstępnego udostępnia również metodę .bert_pack_inputs(tensors, seq_length) , która pobiera listę tokenów (podobnie jak tok powyżej) i argument długości sekwencji. Spowoduje to spakowanie danych wejściowych do utworzenia słownika tensorów w formacie oczekiwanym przez model 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)

Oto kilka szczegółów, na które należy zwrócić uwagę:

  • input_mask Maska umożliwia modelowi wyraźne rozróżnienie między zawartością a dopełnieniem. Maska ma taki sam kształt jak input_word_ids i zawiera 1 wszędzie tam, gdzie input_word_ids nie jest input_word_ids .
  • input_type_ids ma taki sam kształt jak input_mask , ale wewnątrz obszaru bez input_mask zawiera 0 lub 1 wskazujące, którego zdania jest token.

Następnie utworzysz model przetwarzania wstępnego, który zawiera całą tę logikę. Twój model przyjmie ciągi znaków jako dane wejściowe i zwróci odpowiednio sformatowane obiekty, które można przekazać do BERT.

Każdy model BERT ma określony model przetwarzania wstępnego, upewnij się, że używasz właściwego modelu opisanego w dokumentacji modelu 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)

Pokażmy model przetwarzania wstępnego. Utworzysz test z dwoma zdaniami wejściowymi (input1 i input2). Dane wyjściowe są zgodne z oczekiwaniami modelu BERT jako input_word_ids wejściowymi: input_word_ids , input_masks i 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_mask', 'input_type_ids', 'input_word_ids']
Shape Word Ids :  (1, 128)
Word Ids       :  tf.Tensor(
[ 101 2070 6721 3231 6251  102 2178 6251  102    0    0    0    0    0
    0    0], shape=(16,), dtype=int32)
Shape Mask     :  (1, 128)
Input Mask     :  tf.Tensor([1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0], shape=(16,), dtype=int32)
Shape Type Ids :  (1, 128)
Type Ids       :  tf.Tensor([0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0], shape=(16,), dtype=int32)

Przyjrzyjmy się strukturze modelu, zwracając uwagę na dwa zdefiniowane dane wejściowe.

tf.keras.utils.plot_model(test_preprocess_model)
('Failed to import pydot. You must `pip install pydot` and install graphviz (https://graphviz.gitlab.io/download/), ', 'for `pydotprint` to work.')

Aby zastosować przetwarzanie wstępne we wszystkich wejściach ze zbioru danych, użyjesz funkcji map z zestawu danych. Wynik jest następnie zapisywany w pamięci podręcznej w celu zapewnienia wydajności .

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

Zdefiniuj swój model

Jesteś teraz gotowy do zdefiniowania modelu klasyfikacji zdań lub par zdań, dostarczając wstępnie przetworzone dane wejściowe przez koder BERT i umieszczając na górze klasyfikator liniowy (lub inny układ warstw, jak wolisz), a także wykorzystując dropout do regularyzacji.

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

Spróbujmy uruchomić model na niektórych wstępnie przetworzonych danych wejściowych.

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

Przyjrzyjmy się strukturze modelu. Możesz zobaczyć trzy oczekiwane dane wejściowe BERT.

tf.keras.utils.plot_model(test_classifier_model)
('Failed to import pydot. You must `pip install pydot` and install graphviz (https://graphviz.gitlab.io/download/), ', 'for `pydotprint` to work.')

Wybierz zadanie od GLUE

Zamierzasz użyć zestawu danych TensorFlow z pakietu wzorcowego GLUE .

Colab pozwala pobrać te małe zestawy danych do lokalnego systemu plików, a poniższy kod wczytuje je w całości do pamięci, ponieważ oddzielny host roboczy TPU nie może uzyskać dostępu do lokalnego systemu plików środowiska wykonawczego colab.

W przypadku większych zbiorów danych musisz utworzyć własny zasobnik Google Cloud Storage i poprosić pracownika TPU o odczytanie z niego danych. Możesz dowiedzieć się więcej w przewodniku TPU .

Zaleca się rozpocząć od zbioru danych CoLa (dla jednego zdania) lub MRPC (dla wielu zdań), ponieważ są one małe i nie wymagają dużo czasu na ich dopracowanie.

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)

Zbiór danych określa również typ problemu (klasyfikację lub regresję) oraz odpowiednią funkcję straty do treningu.

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

Wytrenuj swój model

Na koniec możesz wytrenować model od końca do końca na wybranym zestawie danych.

Dystrybucja

Przywołaj kod konfiguracyjny u góry, który połączył środowisko wykonawcze colab z pracownikiem TPU z wieloma urządzeniami TPU. Aby rozdzielić na nich szkolenie, utworzysz i skompilujesz swój główny model Keras w ramach strategii dystrybucji TPU. (Aby uzyskać szczegółowe informacje, zobacz Rozproszone szkolenie z Keras ).

Z drugiej strony przetwarzanie wstępne działa na procesorze hosta roboczego, a nie na modułach TPU, więc model Keras do przetwarzania wstępnego, a także zmapowane zestawy danych treningowych i walidacyjnych są zbudowane poza zakresem strategii dystrybucji. Wywołanie Model.fit() zajmie się dystrybucją przekazanego zestawu danych do replik modelu.

Optimizer

Precyzyjne strojenie jest zgodne z ustawieniami optymalizatora z przedtreningiem BERT (jak w Classify text with BERT ): Wykorzystuje optymalizator AdamW z liniowym zanikiem nominalnego początkowego tempa uczenia się, poprzedzony liniową fazą rozgrzewki w stosunku do pierwszego 10% kroków treningowych ( num_warmup_steps ). Zgodnie z artykułem BERT, początkowy wskaźnik uczenia się jest mniejszy w przypadku dostrajania (najlepiej 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:595: 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:437: UserWarning: Converting sparse IndexedSlices(IndexedSlices(indices=Tensor("AdamWeightDecay/gradients/StatefulPartitionedCall:1", shape=(None,), dtype=int32), values=Tensor("clip_by_global_norm/clip_by_global_norm/_0:0", dtype=float32), dense_shape=Tensor("AdamWeightDecay/gradients/StatefulPartitionedCall:2", shape=(None,), dtype=int32))) to a dense Tensor of unknown shape. This may consume a large amount of memory.
  "shape. This may consume a large amount of memory." % value)
267/267 [==============================] - 79s 77ms/step - loss: 0.5812 - MatthewsCorrelationCoefficient: 0.5968 - val_loss: 0.4688 - val_MatthewsCorrelationCoefficient: 0.5871
Epoch 2/3
267/267 [==============================] - 15s 58ms/step - loss: 0.3561 - MatthewsCorrelationCoefficient: 0.5906 - val_loss: 0.5723 - val_MatthewsCorrelationCoefficient: 0.5871
Epoch 3/3
267/267 [==============================] - 15s 58ms/step - loss: 0.2352 - MatthewsCorrelationCoefficient: 0.5909 - val_loss: 0.6748 - val_MatthewsCorrelationCoefficient: 0.5871

Eksportuj do wnioskowania

Utworzysz ostateczny model, który będzie zawierał część wstępnego przetwarzania i dopracowany BERT, który właśnie stworzyliśmy.

W czasie wnioskowania wstępne przetwarzanie musi być częścią modelu (ponieważ nie ma już oddzielnej kolejki wejściowej, jak w przypadku danych uczących, które to robią). Wstępne przetwarzanie to nie tylko obliczenia; ma własne zasoby (tabelę słownictwa), które należy dołączyć do modelu Keras zapisanego do eksportu. To ostateczne zgromadzenie będzie tym, co zostanie uratowane.

Zamierzasz zapisać model na colab, a później możesz go pobrać, aby zachować go na przyszłość ( Widok -> Spis treści -> Pliki ).

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

Przetestuj model

Ostatnim krokiem jest przetestowanie wyników eksportowanego modelu.

Aby dokonać porównania, przeładujmy model i przetestujmy go przy użyciu niektórych danych wejściowych z testu rozdzielonego ze zbioru danych.

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

Metody użytkowe

Test

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'Onto the table jumped a cat.']
This sentence is acceptable
BERT raw results: tf.Tensor([-1.5364362  3.0245366], shape=(2,), dtype=float32)

sentence: [b'it is important to John to leave.']
This sentence is acceptable
BERT raw results: tf.Tensor([-2.1081586  4.0080795], shape=(2,), dtype=float32)

sentence: [b'Gina filled the pitcher with lemonade.']
This sentence is acceptable
BERT raw results: tf.Tensor([-2.5824902  3.740626 ], shape=(2,), dtype=float32)

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

sentence: [b'The student hated his morphology professor.']
This sentence is acceptable
BERT raw results: tf.Tensor([-2.4559186  3.5234451], shape=(2,), dtype=float32)

Jeśli chcesz używać swojego modelu w TF Serving , pamiętaj, że wywoła on Twój SavedModel za pomocą jednego ze swoich nazwanych sygnatur. Zauważ, że są pewne drobne różnice w danych wejściowych. W Pythonie możesz je przetestować w następujący sposób:

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'His loves him'
This sentence is unacceptable
BERT raw results: tf.Tensor([ 2.160802  -2.4170692], shape=(2,), dtype=float32)

sentence: b'John says Mary likes himself.'
This sentence is unacceptable
BERT raw results: tf.Tensor([ 1.759533  -2.0088294], shape=(2,), dtype=float32)

sentence: b'He treats John very under.'
This sentence is acceptable
BERT raw results: tf.Tensor([-0.19971004  1.1566539 ], shape=(2,), dtype=float32)

sentence: b'Karen asked where him to vote for.'
This sentence is unacceptable
BERT raw results: tf.Tensor([ 2.1606677 -2.1753395], shape=(2,), dtype=float32)

sentence: b"I didn't give Jack Ed's picture of anybody."
This sentence is unacceptable
BERT raw results: tf.Tensor([ 1.755337 -1.904901], shape=(2,), dtype=float32)

Zrobiłeś to! Zapisany model można wykorzystać do obsługi lub prostego wnioskowania w procesie, z prostszym interfejsem API z mniejszą ilością kodu i łatwiejszym w utrzymaniu.

Następne kroki

Teraz, gdy wypróbowałeś jeden z podstawowych modeli BERT, możesz wypróbować inne, aby uzyskać większą dokładność lub może z mniejszymi wersjami modeli.

Możesz także spróbować w innych zbiorach danych.