오늘 현지 TensorFlow Everywhere 이벤트에 참석하세요!
이 페이지는 Cloud Translation API를 통해 번역되었습니다.
Switch to English

TPU에서 BERT를 사용하여 GLUE 작업 해결

TensorFlow.org에서보기 Google Colab에서 실행 GitHub에서보기 노트북 다운로드 TF Hub 모델보기

BERT는 자연어 처리의 많은 문제를 해결하는 데 사용할 수 있습니다. GLUE 벤치 마크 에서 여러 작업에 대해 BERT를 미세 조정하는 방법을 배웁니다.

  1. CoLA (Corpus of Linguistic Acceptability) : 문장이 문법적으로 정확합니까?

  2. SST-2 (Stanford Sentiment Treebank) : 주어진 문장의 감정을 예측하는 작업입니다.

  3. MRPC (Microsoft Research Paraphrase Corpus) : 한 쌍의 문장이 의미 상 동일한 지 확인합니다.

  4. QQP (Quora Question Pairs2) : 한 쌍의 질문이 의미 상 동일한 지 여부를 결정합니다.

  5. MNLI (Multi-Genre Natural Language Inference) : 전제 문장과 가설 문장이 주어지면 전제가 가설 (수반)을 수반하는지, 가설과 모순되는지 (모순) 또는 둘 다 (중립적) 여부를 예측하는 것이 과제입니다.

  6. QNLI (질문 응답 자연어 추론) : 작업은 문맥 문장에 질문에 대한 답이 포함되어 있는지 여부를 결정하는 것입니다.

  7. RTE (텍스트 수반 인식) : 문장이 주어진 가설을 수반하는지 여부를 결정합니다.

  8. WNLI (Winograd Natural Language Inference) : 대명사가 대체 된 문장이 원래 문장에 포함되는지 예측하는 작업입니다.

이 가이드에는 TPU에서 이러한 모델을 학습시키기위한 완전한 엔드 투 엔드 코드가 포함되어 있습니다. 한 줄을 변경하여 GPU에서이 노트북을 실행할 수도 있습니다 (아래 설명 참조).

이 노트북에서는 다음을 수행합니다.

  • TensorFlow Hub에서 BERT 모델로드
  • GLUE 작업 중 하나를 선택하고 데이터 세트를 다운로드합니다.
  • 텍스트 전처리
  • BERT 미세 조정 (단일 문장 및 다중 문장 데이터 세트에 대한 예가 제공됨)
  • 훈련 된 모델을 저장하고 사용

설정

BERT를 미세 조정하기 위해 텍스트를 사용하기 전에 별도의 모델을 사용하여 텍스트를 전처리합니다. 이 모델은 아래에 설치할 tensorflow / text 에 따라 다릅니다.

pip install -q -U tensorflow-text

tensorflow / models 의 AdamW 옵티 마이저를 사용하여 BERT를 미세 조정합니다.

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

다음으로 TFHub의 Cloud Storage 버킷에서 직접 체크 포인트를 읽도록 TFHub를 구성합니다. TPU에서 TFHub 모델을 실행할 때만 권장됩니다.

이 설정이 없으면 TFHub는 압축 파일을 다운로드하고 로컬에서 체크 포인트를 추출합니다. 이러한 로컬 파일에서로드하려고하면 다음 오류와 함께 실패합니다.

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

이는 TPU가 Cloud Storage 버킷에서만 직접 읽을 수 있기 때문입니다.

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

TPU 작업자에 연결

다음 코드는 TPU 작업자에 연결하고 TensorFlow의 기본 기기를 TPU 작업자의 CPU 기기로 변경합니다. 또한이 하나의 TPU 작업자에서 사용할 수있는 8 개의 별도 TPU 코어에 모델 학습을 배포하는 데 사용할 TPU 배포 전략을 정의합니다. 자세한 내용은 TensorFlow의 TPU 가이드 를 참조하세요.

import os

if os.environ['COLAB_TPU_ADDR']:
  cluster_resolver = tf.distribute.cluster_resolver.TPUClusterResolver(tpu='grpc://' + os.environ['COLAB_TPU_ADDR'])
  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 recomended.')
Using TPU

TensorFlow Hub에서 모델로드

여기서 TensorFlow Hub에서로드 할 BERT 모델을 선택하고 미세 조정할 수 있습니다. 선택할 수있는 여러 BERT 모델이 있습니다.

  • BERT-Base , Uncased 및 원래 BERT 작성자가 발표 한 훈련 된 가중치가있는 7 개의 추가 모델 .
  • 소형 BERT 는 동일한 일반 아키텍처를 갖지만 Transformer 블록 수가 적거나 작아 속도, 크기 및 품질 간의 균형을 탐색 할 수 있습니다.
  • ALBERT : 레이어간에 매개 변수를 공유하여 모델 크기 (계산 시간이 아님)를 줄이는 4 가지 크기의 "A Lite BERT".
  • BERT 전문가 : 모두 BERT 기반 아키텍처를 가지고 있지만 대상 작업에보다 밀접하게 맞추기 위해 서로 다른 사전 교육 도메인 중에서 선택할 수있는 8 개의 모델.
  • Electra 는 BERT와 동일한 아키텍처 (세 가지 다른 크기)를 갖지만 GAN (Generative Adversarial Network)과 유사한 설정에서 판별 자로 사전 훈련됩니다.
  • Talking-Heads Attention 및 Gated GELU [ base , large ]가있는 BERT는 Transformer 아키텍처의 핵심을 두 가지 개선했습니다.

자세한 내용은 위에 링크 된 모델 문서를 참조하십시오.

이 자습서에서는 BERT 기반으로 시작합니다. 더 높은 정확도를 위해 더 크고 최신 모델을 사용하거나 더 빠른 학습 시간을 위해 더 작은 모델을 사용할 수 있습니다. 모델을 변경하려면 한 줄의 코드 만 전환하면됩니다 (아래 참조). 모든 차이점은 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) 메서드를 제공합니다.이 메서드는 토큰 목록 (위의 tok 와 유사)과 시퀀스 길이 인수를받습니다. 이것은 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_word_ids 와 모양이 input_word_ids 가 패딩이 아닌 곳에 1을 포함합니다.
  • input_type_idsinput_mask 와 같은 모양을 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_masksinput_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)
('Failed to import pydot. You must `pip install pydot` and install graphviz (https://graphviz.gitlab.io/download/), ', 'for `pydotprint` 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.53649646 0.56444836]], shape=(1, 2), dtype=float32)

모델의 구조를 살펴 보겠습니다. 3 개의 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.')

GLUE에서 작업 선택

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 is 'glue/cola':
    metrics = tfa.metrics.MatthewsCorrelationCoefficient()
  else:
    metrics = tf.keras.metrics.SparseCategoricalAccuracy(
        'accuracy', dtype=tf.float32)

  return metrics, loss

모델 훈련

마지막으로 선택한 데이터 세트에서 모델을 종단 간 학습 할 수 있습니다.

분포

여러 TPU 기기가있는 TPU 작업자에 colab 런타임을 연결 한 상단의 설정 코드를 기억하세요. 학습을 배포하려면 TPU 배포 전략 범위 내에서 기본 Keras 모델을 만들고 컴파일합니다. (자세한 내용 은 Keras를 사용한 분산 교육을 참조하십시오.)

반면에 사전 처리는 TPU가 아닌 작업자 호스트의 CPU에서 실행되므로 사전 처리를위한 Keras 모델과 함께 매핑 된 학습 및 유효성 검사 데이터 세트는 배포 전략 범위 외부에서 빌드됩니다. 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: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 75ms/step - loss: 0.6242 - accuracy: 0.6785 - val_loss: 0.4657 - val_accuracy: 0.8213
Epoch 2/3
267/267 [==============================] - 15s 58ms/step - loss: 0.3980 - accuracy: 0.8471 - val_loss: 0.5457 - val_accuracy: 0.8174
Epoch 3/3
267/267 [==============================] - 16s 58ms/step - loss: 0.2987 - accuracy: 0.8991 - val_loss: 0.5861 - val_accuracy: 0.8262

추론을 위해 내보내기

방금 생성 한 전처리 부품과 미세 조정 된 BERT가 포함 된 최종 모델을 생성합니다.

추론 시간에 전처리는 모델의 일부 여야합니다 (이를 수행하는 훈련 데이터에 대해 더 이상 별도의 입력 대기열이 없기 때문입니다). 전처리는 단순한 계산이 아닙니다. 내보내기를 위해 저장되는 Keras 모델에 연결되어야하는 자체 리소스 (vocab 테이블)가 있습니다. 이 최종 어셈블리가 저장됩니다.

모델을 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(f'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.

모델 테스트

마지막 단계는 내 보낸 모델의 결과를 테스트하는 것입니다.

비교를 위해 모델을 다시로드하고 데이터 세트에서 분할 된 테스트의 일부 입력을 사용하여 테스트 해 보겠습니다.

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'Danger was sensed by John.']
This sentence is acceptable
Bert raw results:[-2.144082   1.1691043]

sentence: [b'Has John seen Mary?']
This sentence is acceptable
Bert raw results:[-3.0128813  1.2067829]

sentence: [b'Anyone handed a note will be watched closely.']
This sentence is acceptable
Bert raw results:[-2.8751733  2.1580284]

sentence: [b'There is too likely to be a riot for there to be a serious discussion of the issues.']
This sentence is acceptable
Bert raw results:[-2.257368   1.4583347]

sentence: [b'Dana walked and Leslie running.']
This sentence is unacceptable
Bert raw results:[ 2.0557225 -1.722092 ]


TF Serving 에서 모델을 사용하려는 경우 명명 된 서명 중 하나를 통해 저장된 모델을 호출한다는 점을 기억하세요. 입력에 약간의 차이가 있습니다. 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'Nobody told Susan.'
This sentence is acceptable
Bert raw results:[-2.926764   1.5997491]

sentence: b"We should put them in the dining room but it's not clear where."
This sentence is acceptable
Bert raw results:[-2.5918398   0.94283235]

sentence: b"The lawyer can't prove Paul innocent but he can prove Della innocent."
This sentence is acceptable
Bert raw results:[-2.851595   1.5111862]

sentence: b'There is a run in that stocking.'
This sentence is acceptable
Bert raw results:[-2.3499408  1.2573525]

sentence: b"Ideas are put into children's heads."
This sentence is acceptable
Bert raw results:[-3.0248435  1.702605 ]


훌륭해! 저장된 모델은 더 적은 코드와 더 쉽게 유지 관리 할 수있는 더 간단한 API를 사용하여 프로세스에서 제공하거나 간단한 추론에 사용할 수 있습니다.

다음 단계

이제 기본 BERT 모델 중 하나를 시도 했으므로 다른 모델을 시도하여 정확도를 높이거나 더 작은 모델 버전을 사용해 볼 수 있습니다.

다른 데이터 세트에서도 시도해 볼 수 있습니다.