Explorando o TF-Hub CORD-19 Swivel Embeddings

Ver no TensorFlow.org Executar no Google Colab Ver no GitHub Baixar caderno Veja o modelo TF Hub

O módulo de CABO-19 texto giratória incorporação de TF-Hub (https: //tfhub.dev/ tensorflow / cabo-19 / giratória-128d / 3) foi construído para apoiar pesquisadores que analisam textos em línguas naturais relacionados ao COVID-19. Estas incorporações foram treinados sobre os títulos, autores, resumos, textos do corpo, e os títulos de referência de artigos no conjunto de dados CORD-19 .

Nesta colab iremos:

  • Analise palavras semanticamente semelhantes no espaço de incorporação
  • Treine um classificador no conjunto de dados SciCite usando os embeddings CORD-19

Configurar

import functools
import itertools
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pandas as pd

import tensorflow as tf

import tensorflow_datasets as tfds
import tensorflow_hub as hub

from tqdm import trange

Analise os embeddings

Vamos começar analisando a incorporação, calculando e plotando uma matriz de correlação entre os diferentes termos. Se o embedding aprender a capturar com sucesso o significado de palavras diferentes, os vetores de embedding de palavras semanticamente semelhantes devem estar próximos. Vamos dar uma olhada em alguns termos relacionados ao COVID-19.

# Use the inner product between two embedding vectors as the similarity measure
def plot_correlation(labels, features):
  corr = np.inner(features, features)
  corr /= np.max(corr)
  sns.heatmap(corr, xticklabels=labels, yticklabels=labels)

# Generate embeddings for some terms
queries = [
  # Related viruses
  'coronavirus', 'SARS', 'MERS',
  # Regions
  'Italy', 'Spain', 'Europe',
  # Symptoms
  'cough', 'fever', 'throat'
]

module = hub.load('https://tfhub.dev/tensorflow/cord-19/swivel-128d/3')
embeddings = module(queries)

plot_correlation(queries, embeddings)
2021-08-18 11:10:03.886919: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-18 11:10:03.893914: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-18 11:10:03.894880: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-18 11:10:03.896867: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 AVX512F FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-08-18 11:10:03.897437: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-18 11:10:03.898419: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-18 11:10:03.899326: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-18 11:10:04.499928: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-18 11:10:04.500992: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-18 11:10:04.501940: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-18 11:10:04.502845: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1510] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 14648 MB memory:  -> device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0
2021-08-18 11:10:04.859902: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:185] None of the MLIR Optimization Passes are enabled (registered 2)

png

Podemos ver que a incorporação capturou com sucesso o significado dos diferentes termos. Cada palavra é semelhante às outras palavras do seu cluster (ou seja, "coronavirus" altamente correlacionado com "SARS" e "MERS"), embora sejam diferentes dos termos de outros clusters (ou seja, a semelhança entre "SARS" e "Espanha" é próximo a 0).

Agora vamos ver como podemos usar esses embeddings para resolver uma tarefa específica.

SciCite: Classificação da intenção de citação

Esta seção mostra como se pode usar a incorporação para tarefas posteriores, como classificação de texto. Nós vamos usar o dataset SciCite de TensorFlow conjuntos de dados a intenções de citação classifico em trabalhos acadêmicos. Dada uma frase com uma citação de um artigo acadêmico, classifique se o objetivo principal da citação é como informação de base, uso de métodos ou comparação de resultados.

builder = tfds.builder(name='scicite')
builder.download_and_prepare()
train_data, validation_data, test_data = builder.as_dataset(
    split=('train', 'validation', 'test'),
    as_supervised=True)

Vamos dar uma olhada em alguns exemplos rotulados do conjunto de treinamento

Treinar um classificador de intenção de citaton

Vamos treinar um classificador no conjunto de dados SciCite usando Keras. Vamos construir um modelo que use os embeddings CORD-19 com uma camada de classificação no topo.

Hiperparâmetros

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
keras_layer (KerasLayer)     (None, 128)               17301632  
_________________________________________________________________
dense (Dense)                (None, 3)                 387       
=================================================================
Total params: 17,302,019
Trainable params: 387
Non-trainable params: 17,301,632
_________________________________________________________________

Treine e avalie o modelo

Vamos treinar e avaliar o modelo para ver o desempenho na tarefa SciCite

EPOCHS =   35
BATCH_SIZE = 32

history = model.fit(train_data.shuffle(10000).batch(BATCH_SIZE),
                    epochs=EPOCHS,
                    validation_data=validation_data.batch(BATCH_SIZE),
                    verbose=1)
Epoch 1/35
257/257 [==============================] - 4s 9ms/step - loss: 0.9212 - accuracy: 0.5792 - val_loss: 0.7661 - val_accuracy: 0.6812
Epoch 2/35
257/257 [==============================] - 2s 5ms/step - loss: 0.7001 - accuracy: 0.7191 - val_loss: 0.6689 - val_accuracy: 0.7358
Epoch 3/35
257/257 [==============================] - 3s 6ms/step - loss: 0.6263 - accuracy: 0.7574 - val_loss: 0.6223 - val_accuracy: 0.7533
Epoch 4/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5897 - accuracy: 0.7724 - val_loss: 0.5993 - val_accuracy: 0.7511
Epoch 5/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5685 - accuracy: 0.7778 - val_loss: 0.5844 - val_accuracy: 0.7555
Epoch 6/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5549 - accuracy: 0.7831 - val_loss: 0.5767 - val_accuracy: 0.7675
Epoch 7/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5456 - accuracy: 0.7870 - val_loss: 0.5703 - val_accuracy: 0.7718
Epoch 8/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5387 - accuracy: 0.7907 - val_loss: 0.5673 - val_accuracy: 0.7675
Epoch 9/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5335 - accuracy: 0.7905 - val_loss: 0.5599 - val_accuracy: 0.7784
Epoch 10/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5296 - accuracy: 0.7923 - val_loss: 0.5582 - val_accuracy: 0.7762
Epoch 11/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5254 - accuracy: 0.7916 - val_loss: 0.5568 - val_accuracy: 0.7740
Epoch 12/35
257/257 [==============================] - 3s 5ms/step - loss: 0.5222 - accuracy: 0.7922 - val_loss: 0.5553 - val_accuracy: 0.7751
Epoch 13/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5200 - accuracy: 0.7944 - val_loss: 0.5530 - val_accuracy: 0.7795
Epoch 14/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5178 - accuracy: 0.7941 - val_loss: 0.5550 - val_accuracy: 0.7762
Epoch 15/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5157 - accuracy: 0.7939 - val_loss: 0.5517 - val_accuracy: 0.7773
Epoch 16/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5142 - accuracy: 0.7956 - val_loss: 0.5500 - val_accuracy: 0.7817
Epoch 17/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5123 - accuracy: 0.7977 - val_loss: 0.5498 - val_accuracy: 0.7871
Epoch 18/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5112 - accuracy: 0.7968 - val_loss: 0.5476 - val_accuracy: 0.7838
Epoch 19/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5100 - accuracy: 0.7974 - val_loss: 0.5485 - val_accuracy: 0.7871
Epoch 20/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5089 - accuracy: 0.7977 - val_loss: 0.5491 - val_accuracy: 0.7817
Epoch 21/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5073 - accuracy: 0.7981 - val_loss: 0.5479 - val_accuracy: 0.7828
Epoch 22/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5064 - accuracy: 0.7984 - val_loss: 0.5471 - val_accuracy: 0.7817
Epoch 23/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5054 - accuracy: 0.7981 - val_loss: 0.5463 - val_accuracy: 0.7838
Epoch 24/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5050 - accuracy: 0.8019 - val_loss: 0.5465 - val_accuracy: 0.7882
Epoch 25/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5046 - accuracy: 0.7984 - val_loss: 0.5467 - val_accuracy: 0.7849
Epoch 26/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5038 - accuracy: 0.7997 - val_loss: 0.5456 - val_accuracy: 0.7838
Epoch 27/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5033 - accuracy: 0.8003 - val_loss: 0.5456 - val_accuracy: 0.7828
Epoch 28/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5026 - accuracy: 0.7996 - val_loss: 0.5461 - val_accuracy: 0.7849
Epoch 29/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5019 - accuracy: 0.8025 - val_loss: 0.5447 - val_accuracy: 0.7828
Epoch 30/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5014 - accuracy: 0.8007 - val_loss: 0.5465 - val_accuracy: 0.7849
Epoch 31/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5005 - accuracy: 0.8011 - val_loss: 0.5434 - val_accuracy: 0.7860
Epoch 32/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5004 - accuracy: 0.8018 - val_loss: 0.5444 - val_accuracy: 0.7882
Epoch 33/35
257/257 [==============================] - 2s 5ms/step - loss: 0.5000 - accuracy: 0.8003 - val_loss: 0.5457 - val_accuracy: 0.7882
Epoch 34/35
257/257 [==============================] - 2s 5ms/step - loss: 0.4995 - accuracy: 0.8025 - val_loss: 0.5461 - val_accuracy: 0.7882
Epoch 35/35
257/257 [==============================] - 2s 5ms/step - loss: 0.4991 - accuracy: 0.8006 - val_loss: 0.5432 - val_accuracy: 0.7893
from matplotlib import pyplot as plt
def display_training_curves(training, validation, title, subplot):
  if subplot%10==1: # set up the subplots on the first call
    plt.subplots(figsize=(10,10), facecolor='#F0F0F0')
    plt.tight_layout()
  ax = plt.subplot(subplot)
  ax.set_facecolor('#F8F8F8')
  ax.plot(training)
  ax.plot(validation)
  ax.set_title('model '+ title)
  ax.set_ylabel(title)
  ax.set_xlabel('epoch')
  ax.legend(['train', 'valid.'])
display_training_curves(history.history['accuracy'], history.history['val_accuracy'], 'accuracy', 211)
display_training_curves(history.history['loss'], history.history['val_loss'], 'loss', 212)

png

Avalie o modelo

E vamos ver como o modelo funciona. Dois valores serão retornados. Perda (um número que representa nosso erro, valores mais baixos são melhores) e precisão.

results = model.evaluate(test_data.batch(512), verbose=2)

for name, value in zip(model.metrics_names, results):
  print('%s: %.3f' % (name, value))
4/4 - 2s - loss: 0.5345 - accuracy: 0.7891
loss: 0.534
accuracy: 0.789

Podemos ver que a perda diminui rapidamente enquanto, especialmente, a precisão aumenta rapidamente. Vamos plotar alguns exemplos para verificar como a previsão se relaciona com os rótulos verdadeiros:

prediction_dataset = next(iter(test_data.batch(20)))

prediction_texts = [ex.numpy().decode('utf8') for ex in prediction_dataset[0]]
prediction_labels = [label2str(x) for x in prediction_dataset[1]]

predictions = [
    label2str(x) for x in np.argmax(model.predict(prediction_texts), axis=-1)]


pd.DataFrame({
    TEXT_FEATURE_NAME: prediction_texts,
    LABEL_NAME: prediction_labels,
    'prediction': predictions
})

Podemos ver que, para essa amostra aleatória, o modelo prevê o rótulo correto na maioria das vezes, indicando que ele pode incorporar frases científicas muito bem.

Qual é o próximo?

Agora que você aprendeu um pouco mais sobre os embeddings CORD-19 Swivel do TF-Hub, incentivamos você a participar da competição CORD-19 Kaggle para contribuir com a obtenção de conhecimentos científicos de textos acadêmicos relacionados ao COVID-19.