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

BERT로 텍스트 분류

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

이 자습서에는 BERT를 미세 조정하여 일반 텍스트 IMDB 영화 리뷰 데이터 세트에 대한 감정 분석을 수행하는 완전한 코드가 포함되어 있습니다. 모델 학습 외에도 텍스트를 적절한 형식으로 사전 처리하는 방법을 배웁니다.

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

  • IMDB 데이터 세트로드
  • TensorFlow Hub에서 BERT 모델로드
  • BERT와 분류기를 결합하여 자신 만의 모델을 구축하세요
  • 자신의 모델을 훈련시키고 그 일부로 BERT를 미세 조정합니다.
  • 모델을 저장하고이를 사용하여 문장 분류

IMDB 데이터 셋을 처음 사용하는 경우 자세한 내용은 기본 텍스트 분류 를 참조하십시오.

BERT 정보

BERT 및 기타 Transformer 인코더 아키텍처는 NLP (자연어 처리)의 다양한 작업에서 크게 성공했습니다. 딥 러닝 모델에 사용하기에 적합한 자연어의 벡터 공간 표현을 계산합니다. BERT 모델 제품군은 Transformer 인코더 아키텍처를 사용하여 전후 모든 토큰의 전체 컨텍스트에서 입력 텍스트의 각 토큰을 처리하므로 이름은 Transformers의 양방향 인코더 표현입니다.

BERT 모델은 일반적으로 큰 텍스트 코퍼스에 대해 사전 훈련 된 다음 특정 작업에 맞게 미세 조정됩니다.

설정

# A dependency of the preprocessing for BERT inputs
pip install -q tensorflow-text

tensorflow / models 에서 AdamW 최적화 프로그램을 사용합니다.

pip install -q tf-models-official
import os
import shutil

import tensorflow as tf
import tensorflow_hub as hub
import tensorflow_text as text
from official.nlp import optimization  # to create AdamW optmizer

import matplotlib.pyplot as plt

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

감정 분석

이 노트북은 리뷰 텍스트를 기반으로 영화 리뷰를 긍정적 또는 부정적 으로 분류하는 감정 분석 모델을 학습합니다.

인터넷 영화 데이터베이스 에서 가져온 50,000 개의 영화 리뷰 텍스트가 포함 된 대형 영화 리뷰 데이터 세트 를 사용합니다.

IMDB 데이터 세트 다운로드

데이터 세트를 다운로드하고 추출한 다음 디렉터리 구조를 살펴 보겠습니다.

url = 'https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz'

dataset = tf.keras.utils.get_file('aclImdb_v1.tar.gz', url,
                                  untar=True, cache_dir='.',
                                  cache_subdir='')

dataset_dir = os.path.join(os.path.dirname(dataset), 'aclImdb')

train_dir = os.path.join(dataset_dir, 'train')

# remove unused folders to make it easier to load the data
remove_dir = os.path.join(train_dir, 'unsup')
shutil.rmtree(remove_dir)
Downloading data from https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
84131840/84125825 [==============================] - 7s 0us/step

다음으로 text_dataset_from_directory 유틸리티를 사용하여 레이블이있는tf.data.Dataset 을 만듭니다.

IMDB 데이터 세트는 이미 훈련과 테스트로 나뉘었지만 검증 세트가 없습니다. 아래 validation_split 인수를 사용하여 훈련 데이터의 80:20 분할을 사용하여 검증 세트를 생성 해 보겠습니다.

AUTOTUNE = tf.data.AUTOTUNE
batch_size = 32
seed = 42

raw_train_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/train',
    batch_size=batch_size,
    validation_split=0.2,
    subset='training',
    seed=seed)

class_names = raw_train_ds.class_names
train_ds = raw_train_ds.cache().prefetch(buffer_size=AUTOTUNE)

val_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/train',
    batch_size=batch_size,
    validation_split=0.2,
    subset='validation',
    seed=seed)

val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

test_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/test',
    batch_size=batch_size)

test_ds = test_ds.cache().prefetch(buffer_size=AUTOTUNE)
Found 25000 files belonging to 2 classes.
Using 20000 files for training.
Found 25000 files belonging to 2 classes.
Using 5000 files for validation.
Found 25000 files belonging to 2 classes.

몇 가지 리뷰를 살펴 보겠습니다.

for text_batch, label_batch in train_ds.take(1):
  for i in range(3):
    print(f'Review: {text_batch.numpy()[i]}')
    label = label_batch.numpy()[i]
    print(f'Label : {label} ({class_names[label]})')
Review: b'"Pandemonium" is a horror movie spoof that comes off more stupid than funny. Believe me when I tell you, I love comedies. Especially comedy spoofs. "Airplane", "The Naked Gun" trilogy, "Blazing Saddles", "High Anxiety", and "Spaceballs" are some of my favorite comedies that spoof a particular genre. "Pandemonium" is not up there with those films. Most of the scenes in this movie had me sitting there in stunned silence because the movie wasn\'t all that funny. There are a few laughs in the film, but when you watch a comedy, you expect to laugh a lot more than a few times and that\'s all this film has going for it. Geez, "Scream" had more laughs than this film and that was more of a horror film. How bizarre is that?<br /><br />*1/2 (out of four)'
Label : 0 (neg)
Review: b"David Mamet is a very interesting and a very un-equal director. His first movie 'House of Games' was the one I liked best, and it set a series of films with characters whose perspective of life changes as they get into complicated situations, and so does the perspective of the viewer.<br /><br />So is 'Homicide' which from the title tries to set the mind of the viewer to the usual crime drama. The principal characters are two cops, one Jewish and one Irish who deal with a racially charged area. The murder of an old Jewish shop owner who proves to be an ancient veteran of the Israeli Independence war triggers the Jewish identity in the mind and heart of the Jewish detective.<br /><br />This is were the flaws of the film are the more obvious. The process of awakening is theatrical and hard to believe, the group of Jewish militants is operatic, and the way the detective eventually walks to the final violent confrontation is pathetic. The end of the film itself is Mamet-like smart, but disappoints from a human emotional perspective.<br /><br />Joe Mantegna and William Macy give strong performances, but the flaws of the story are too evident to be easily compensated."
Label : 0 (neg)
Review: b'Great documentary about the lives of NY firefighters during the worst terrorist attack of all time.. That reason alone is why this should be a must see collectors item.. What shocked me was not only the attacks, but the"High Fat Diet" and physical appearance of some of these firefighters. I think a lot of Doctors would agree with me that,in the physical shape they were in, some of these firefighters would NOT of made it to the 79th floor carrying over 60 lbs of gear. Having said that i now have a greater respect for firefighters and i realize becoming a firefighter is a life altering job. The French have a history of making great documentary\'s and that is what this is, a Great Documentary.....'
Label : 1 (pos)

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 아키텍처의 핵심을 두 가지 개선했습니다.

TensorFlow Hub의 모델 문서에는 연구 문헌에 대한 자세한 내용과 참조가 있습니다. 위의 링크를 따르거나 다음 셀 실행 후 인쇄 된 tfhub.dev URL을 클릭합니다.

미세 조정이 더 빠르기 때문에 작은 BERT (매개 변수가 더 적음)로 시작하는 것이 좋습니다. 작은 모델을 좋아하지만 정확도가 더 높은 경우 ALBERT가 다음 옵션이 될 수 있습니다. 더 나은 정확도를 원한다면 클래식 BERT 크기 중 하나를 선택하거나 Electra, Talking Heads 또는 BERT Expert와 같은 최근 개선 사항을 선택하십시오.

아래에서 사용할 수있는 모델 외에도 더 크고 더 나은 정확도를 자랑 할 수있는 여러 버전 의 모델이 있지만 단일 GPU에서 미세 조정하기에는 너무 큽니다. TPU colab에서 BERT를 사용하여 Solve GLUE 작업 에서이를 수행 할 수 있습니다.

아래 코드에서 tfhub.dev URL을 전환하면 이러한 모델을 시도하기에 충분하다는 것을 알 수 있습니다. 두 모델 간의 모든 차이점은 TF 허브의 저장된 모델에 캡슐화되어 있기 때문입니다.

미세 조정할 BERT 모델 선택

BERT model selected           : https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-4_H-512_A-8/1
Preprocess model auto-selected: https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3

전처리 모델

텍스트 입력은 BERT에 입력되기 전에 숫자 토큰 ID로 변환되고 여러 Tensor로 정렬되어야합니다. TensorFlow Hub는 위에서 설명한 각 BERT 모델에 대해 일치하는 전처리 모델을 제공하며, TF.text 라이브러리의 TF 작업을 사용하여이 변환을 구현합니다. 텍스트를 전처리하기 위해 TensorFlow 모델 외부에서 순수한 Python 코드를 실행할 필요는 없습니다.

전처리 모델은 위에 인쇄 된 URL에서 읽을 수있는 BERT 모델의 문서에서 참조하는 모델이어야합니다. 위 드롭 다운의 BERT 모델의 경우 전처리 모델이 자동으로 선택됩니다.

bert_preprocess_model = hub.KerasLayer(tfhub_handle_preprocess)

일부 텍스트에 대해 전처리 모델을 시도하고 출력을 보겠습니다.

text_test = ['this is such an amazing movie!']
text_preprocessed = bert_preprocess_model(text_test)

print(f'Keys       : {list(text_preprocessed.keys())}')
print(f'Shape      : {text_preprocessed["input_word_ids"].shape}')
print(f'Word Ids   : {text_preprocessed["input_word_ids"][0, :12]}')
print(f'Input Mask : {text_preprocessed["input_mask"][0, :12]}')
print(f'Type Ids   : {text_preprocessed["input_type_ids"][0, :12]}')
Keys       : ['input_word_ids', 'input_type_ids', 'input_mask']
Shape      : (1, 128)
Word Ids   : [ 101 2023 2003 2107 2019 6429 3185  999  102    0    0    0]
Input Mask : [1 1 1 1 1 1 1 1 1 0 0 0]
Type Ids   : [0 0 0 0 0 0 0 0 0 0 0 0]

보시다시피 이제 BERT 모델이 사용할 전처리의 3 가지 출력 ( input_words_id , input_maskinput_type_ids )이 있습니다.

기타 중요한 사항 :

  • 입력은 128 개의 토큰으로 잘립니다. 토큰 수는 맞춤 설정할 수 있으며 TPU colab에서 BERT를 사용하여 Solve GLUE 작업 에 대한 자세한 내용을 볼 수 있습니다.
  • input_type_ids 는 단일 문장 입력이기 때문에 하나의 값 (0) 만 갖습니다. 여러 문장 입력의 경우 각 입력에 대해 하나의 숫자가 있습니다.

이 텍스트 전처리 기는 TensorFlow 모델이므로 모델에 직접 포함될 수 있습니다.

BERT 모델 사용

BERT를 자신의 모델에 적용하기 전에 출력을 살펴 보겠습니다. TF Hub에서로드하고 반환 된 값을 확인합니다.

bert_model = hub.KerasLayer(tfhub_handle_encoder)
bert_results = bert_model(text_preprocessed)

print(f'Loaded BERT: {tfhub_handle_encoder}')
print(f'Pooled Outputs Shape:{bert_results["pooled_output"].shape}')
print(f'Pooled Outputs Values:{bert_results["pooled_output"][0, :12]}')
print(f'Sequence Outputs Shape:{bert_results["sequence_output"].shape}')
print(f'Sequence Outputs Values:{bert_results["sequence_output"][0, :12]}')
Loaded BERT: https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-4_H-512_A-8/1
Pooled Outputs Shape:(1, 512)
Pooled Outputs Values:[ 0.76262873  0.9928097  -0.18611881  0.36673862  0.15233737  0.6550447
  0.9681153  -0.9486272   0.00216161 -0.9877732   0.06842697 -0.9763058 ]
Sequence Outputs Shape:(1, 128, 512)
Sequence Outputs Values:[[-0.28946346  0.34321272  0.33231515 ...  0.21300808  0.71020764
  -0.05771098]
 [-0.28742087  0.31980985 -0.23018607 ...  0.58455014 -0.21329728
   0.72692114]
 [-0.6615697   0.6887685  -0.87432986 ...  0.10877222 -0.2617324
   0.4785539 ]
 ...
 [-0.22561133 -0.2892562  -0.07064445 ...  0.47565985  0.83277136
   0.40025374]
 [-0.29824236 -0.27473187 -0.05450562 ...  0.48849723  1.0955356
   0.1816333 ]
 [-0.4437813   0.00930756  0.07223685 ...  0.17290069  1.1833248
   0.07897997]]

BERT 모델은 3 중요한 키 맵을 반환 : pooled_output , sequence_output , encoder_outputs :

  • pooled_output 은 각 입력 시퀀스를 전체로 나타냅니다. 모양은 [batch_size, H] 입니다. 이것은 전체 영화 리뷰에 대한 임베딩으로 생각할 수 있습니다.
  • sequence_output 은 컨텍스트의 각 입력 토큰을 나타냅니다. 모양은 [batch_size, seq_length, H] 입니다. 이것을 영화 리뷰의 모든 토큰에 대한 문맥 삽입으로 생각할 수 있습니다.
  • encoder_outputsL Transformer 블록의 중간 활성화입니다. outputs["encoder_outputs"][i]0 <= i < L 에 대해 i 번째 Transformer 블록의 출력을 갖는 [batch_size, seq_length, 1024] 모양의 Tensor입니다. 목록의 마지막 값은 sequence_output 과 같습니다.

미세 조정을 위해 pooled_output 배열을 사용합니다.

모델 정의

전처리 모델, 선택된 BERT 모델, 하나의 Dense 및 Dropout 레이어를 사용하여 매우 간단한 미세 조정 된 모델을 생성합니다.

def build_classifier_model():
  text_input = tf.keras.layers.Input(shape=(), dtype=tf.string, name='text')
  preprocessing_layer = hub.KerasLayer(tfhub_handle_preprocess, name='preprocessing')
  encoder_inputs = preprocessing_layer(text_input)
  encoder = hub.KerasLayer(tfhub_handle_encoder, trainable=True, name='BERT_encoder')
  outputs = encoder(encoder_inputs)
  net = outputs['pooled_output']
  net = tf.keras.layers.Dropout(0.1)(net)
  net = tf.keras.layers.Dense(1, activation=None, name='classifier')(net)
  return tf.keras.Model(text_input, net)

모델이 전처리 모델의 출력으로 실행되는지 확인해 보겠습니다.

classifier_model = build_classifier_model()
bert_raw_result = classifier_model(tf.constant(text_test))
print(tf.sigmoid(bert_raw_result))
tf.Tensor([[0.25782508]], shape=(1, 1), dtype=float32)

물론 모델이 아직 훈련되지 않았기 때문에 결과는 의미가 없습니다.

모델의 구조를 살펴 보겠습니다.

tf.keras.utils.plot_model(classifier_model)

png

모델 훈련

이제 전처리 모듈, BERT 인코더, 데이터 및 분류기를 포함하여 모델을 학습하는 데 필요한 모든 부분이 준비되었습니다.

손실 기능

이것은 이진 분류 문제이고 모델이 확률 (단일 단위 계층)을 출력하므로 losses.BinaryCrossentropy 손실 함수를 사용합니다.

loss = tf.keras.losses.BinaryCrossentropy(from_logits=True)
metrics = tf.metrics.BinaryAccuracy()

옵티 마이저

미세 조정을 위해 BERT가 원래 훈련 된 것과 동일한 최적화 프로그램 인 "Adaptive Moments"(Adam)를 사용하겠습니다. 이 옵티마이 저는 예측 손실을 최소화하고 AdamW 라고도하는 가중치 감소 (모멘트를 사용하지 않음)로 정규화를 수행 합니다.

학습률 ( init_lr )의 경우 BERT 사전 학습과 동일한 일정을 사용합니다. 즉, 학습 단계의 처음 10 % ( num_warmup_steps )에 걸쳐 선형 워밍업 단계가 접두사로 붙은 개념적 초기 학습률의 선형 감쇠입니다. BERT 논문에 따르면 미세 조정을위한 초기 학습률은 더 작습니다 (5e-5, 3e-5, 2e-5 중 최고).

epochs = 5
steps_per_epoch = tf.data.experimental.cardinality(train_ds).numpy()
num_train_steps = steps_per_epoch * epochs
num_warmup_steps = int(0.1*num_train_steps)

init_lr = 3e-5
optimizer = optimization.create_optimizer(init_lr=init_lr,
                                          num_train_steps=num_train_steps,
                                          num_warmup_steps=num_warmup_steps,
                                          optimizer_type='adamw')

BERT 모델로드 및 훈련

이전에 생성 한 classifier_model 을 사용하여 손실, 측정 항목 및 최적화 프로그램으로 모델을 컴파일 할 수 있습니다.

classifier_model.compile(optimizer=optimizer,
                         loss=loss,
                         metrics=metrics)
print(f'Training model with {tfhub_handle_encoder}')
history = classifier_model.fit(x=train_ds,
                               validation_data=val_ds,
                               epochs=epochs)
Training model with https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-4_H-512_A-8/1
Epoch 1/5
625/625 [==============================] - 99s 146ms/step - loss: 0.6006 - binary_accuracy: 0.6609 - val_loss: 0.3906 - val_binary_accuracy: 0.8356
Epoch 2/5
625/625 [==============================] - 89s 142ms/step - loss: 0.3581 - binary_accuracy: 0.8387 - val_loss: 0.3768 - val_binary_accuracy: 0.8460
Epoch 3/5
625/625 [==============================] - 89s 142ms/step - loss: 0.2684 - binary_accuracy: 0.8848 - val_loss: 0.3909 - val_binary_accuracy: 0.8466
Epoch 4/5
625/625 [==============================] - 90s 144ms/step - loss: 0.2048 - binary_accuracy: 0.9166 - val_loss: 0.4477 - val_binary_accuracy: 0.8498
Epoch 5/5
625/625 [==============================] - 89s 142ms/step - loss: 0.1566 - binary_accuracy: 0.9382 - val_loss: 0.4789 - val_binary_accuracy: 0.8512

모델 평가

모델의 성능을 살펴 보겠습니다. 두 개의 값이 반환됩니다. 손실 (오류를 나타내는 숫자, 낮은 값이 더 좋음) 및 정확도.

loss, accuracy = classifier_model.evaluate(test_ds)

print(f'Loss: {loss}')
print(f'Accuracy: {accuracy}')
782/782 [==============================] - 63s 81ms/step - loss: 0.4613 - binary_accuracy: 0.8559
Loss: 0.4613250494003296
Accuracy: 0.8558800220489502

시간 경과에 따른 정확도와 손실을 플로팅합니다.

model.fit() 의해 반환 된 History 객체를 기반으로합니다. 비교를 위해 훈련 및 검증 손실과 훈련 및 검증 정확도를 플로팅 할 수 있습니다.

history_dict = history.history
print(history_dict.keys())

acc = history_dict['binary_accuracy']
val_acc = history_dict['val_binary_accuracy']
loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs = range(1, len(acc) + 1)
fig = plt.figure(figsize=(10, 6))
fig.tight_layout()

plt.subplot(2, 1, 1)
# "bo" is for "blue dot"
plt.plot(epochs, loss, 'r', label='Training loss')
# b is for "solid blue line"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
# plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.subplot(2, 1, 2)
plt.plot(epochs, acc, 'r', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')
dict_keys(['loss', 'binary_accuracy', 'val_loss', 'val_binary_accuracy'])

<matplotlib.legend.Legend at 0x7f5a20ba8780>

png

이 그림에서 빨간색 선은 훈련 손실 및 정확도를 나타내고 파란색 선은 검증 손실 및 정확도를 나타냅니다.

추론을 위해 내보내기

이제 나중에 사용하기 위해 미세 조정 된 모델을 저장하기 만하면됩니다.

dataset_name = 'imdb'
saved_model_path = './{}_bert'.format(dataset_name.replace('/', '_'))

classifier_model.save(saved_model_path, include_optimizer=False)
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 310). 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 310). These functions will not be directly callable after loading.

아직 메모리에있는 모델과 나란히 시도 할 수 있도록 모델을 다시로드 해 보겠습니다.

reloaded_model = tf.saved_model.load(saved_model_path)

여기에서 원하는 문장으로 모델을 테스트 할 수 있습니다. 아래 예제 변수에 추가하기 만하면됩니다.

def print_my_examples(inputs, results):
  result_for_printing = \
    [f'input: {inputs[i]:<30} : score: {results[i][0]:.6f}'
                         for i in range(len(inputs))]
  print(*result_for_printing, sep='\n')
  print()


examples = [
    'this is such an amazing movie!',  # this is the same sentence tried earlier
    'The movie was great!',
    'The movie was meh.',
    'The movie was okish.',
    'The movie was terrible...'
]

reloaded_results = tf.sigmoid(reloaded_model(tf.constant(examples)))
original_results = tf.sigmoid(classifier_model(tf.constant(examples)))

print('Results from the saved model:')
print_my_examples(examples, reloaded_results)
print('Results from the model in memory:')
print_my_examples(examples, original_results)
Results from the saved model:
input: this is such an amazing movie! : score: 0.999721
input: The movie was great!           : score: 0.996092
input: The movie was meh.             : score: 0.945743
input: The movie was okish.           : score: 0.039043
input: The movie was terrible...      : score: 0.000866

Results from the model in memory:
input: this is such an amazing movie! : score: 0.999721
input: The movie was great!           : score: 0.996092
input: The movie was meh.             : score: 0.945743
input: The movie was okish.           : score: 0.039043
input: The movie was terrible...      : score: 0.000866


TF Serving 에서 모델을 사용하려는 경우 명명 된 서명 중 하나를 통해 저장된 모델을 호출한다는 점을 기억하세요. Python에서는 다음과 같이 테스트 할 수 있습니다.

serving_results = reloaded_model \
            .signatures['serving_default'](tf.constant(examples))

serving_results = tf.sigmoid(serving_results['classifier'])

print_my_examples(examples, serving_results)
input: this is such an amazing movie! : score: 0.999721
input: The movie was great!           : score: 0.996092
input: The movie was meh.             : score: 0.945743
input: The movie was okish.           : score: 0.039043
input: The movie was terrible...      : score: 0.000866


다음 단계

다음 단계 로 TPU에서 실행되고 여러 입력으로 작업하는 방법을 보여주는 TPU 가이드에서 BERT를 사용하여 Solve GLUE 작업을 시도 할 수 있습니다.