Avoir une question? Connectez-vous avec la communauté sur le forum TensorFlow Visiter le forum

Explorer les embeddings pivotants TF-Hub CORD-19

Voir sur TensorFlow.org Exécuter dans Google Colab Afficher sur GitHub Télécharger le cahier Voir le modèle TF Hub

Le module d'intégration de texte CORD-19 Swivel de TF-Hub (https: //tfhub.dev/tensorflow/cord-19/swivel-128d/1) a été conçu pour aider les chercheurs à analyser le texte des COVID-19 [FEMININE. Ces incorporations ont été formées sur les titres, les auteurs, les résumés, les corps du texte et les titres de référence des articles dans l' ensemble de données CORD-19 .

Dans ce colab, nous allons:

  • Analyser des mots sémantiquement similaires dans l'espace d'intégration
  • Former un classificateur sur l'ensemble de données SciCite à l'aide des plongements CORD-19

Installer

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

import tensorflow.compat.v1 as tf
tf.disable_eager_execution()
tf.logging.set_verbosity('ERROR')

import tensorflow_datasets as tfds
import tensorflow_hub as hub

try:
  from google.colab import data_table
  def display_df(df):
    return data_table.DataTable(df, include_index=False)
except ModuleNotFoundError:
  # If google-colab is not available, just display the raw DataFrame
  def display_df(df):
    return df

Analyser les plongements

Commençons par analyser l'incorporation en calculant et en traçant une matrice de corrélation entre différents termes. Si l'incorporation a appris à capturer avec succès la signification de différents mots, les vecteurs d'incorporation de mots sémantiquement similaires devraient être rapprochés. Jetons un coup d'œil à quelques termes liés au 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)


with tf.Graph().as_default():
  # Load the module
  query_input = tf.placeholder(tf.string)
  module = hub.Module('https://tfhub.dev/tensorflow/cord-19/swivel-128d/1')
  embeddings = module(query_input)

  with tf.train.MonitoredTrainingSession() as sess:

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

    features = sess.run(embeddings, feed_dict={query_input: queries})
    plot_correlation(queries, features)

png

Nous pouvons voir que l'intégration a réussi à saisir le sens des différents termes. Chaque mot est similaire aux autres mots de son cluster (c'est-à-dire que «coronavirus» est fortement corrélé avec «SRAS» et «MERS»), alors qu'ils sont différents des termes d'autres clusters (c'est-à-dire que la similitude entre «SRAS» et «Espagne» est proche de 0).

Voyons maintenant comment nous pouvons utiliser ces incorporations pour résoudre une tâche spécifique.

SciCite: Classification des intentions de citation

Cette section montre comment utiliser l'incorporation pour des tâches en aval telles que la classification de texte. Nous utiliserons l' ensemble de données SciCite des ensembles de données TensorFlow pour classer les intentions de citation dans les articles universitaires. Étant donné une phrase avec une citation d'un article académique, indiquez si l'intention principale de la citation est une information de base, l'utilisation de méthodes ou la comparaison des résultats.

Configurer le jeu de données de TFDS

Downloading and preparing dataset scicite/1.0.0 (download: 22.12 MiB, generated: Unknown size, total: 22.12 MiB) to /home/kbuilder/tensorflow_datasets/scicite/1.0.0...
Shuffling and writing examples to /home/kbuilder/tensorflow_datasets/scicite/1.0.0.incompleteHWK5SE/scicite-train.tfrecord
Shuffling and writing examples to /home/kbuilder/tensorflow_datasets/scicite/1.0.0.incompleteHWK5SE/scicite-validation.tfrecord
Shuffling and writing examples to /home/kbuilder/tensorflow_datasets/scicite/1.0.0.incompleteHWK5SE/scicite-test.tfrecord
Dataset scicite downloaded and prepared to /home/kbuilder/tensorflow_datasets/scicite/1.0.0. Subsequent calls will reuse this data.

Jetons un coup d'œil à quelques exemples étiquetés de l'ensemble de formation

Formation d'un classificateur d'intention Citaton

Nous allons former un classificateur sur l' ensemble de données SciCite à l' aide d'un Estimator. Configurons input_fns pour lire l'ensemble de données dans le modèle

def preprocessed_input_fn(for_eval):
  data = THE_DATASET.get_data(for_eval=for_eval)
  data = data.map(THE_DATASET.example_fn, num_parallel_calls=1)
  return data


def input_fn_train(params):
  data = preprocessed_input_fn(for_eval=False)
  data = data.repeat(None)
  data = data.shuffle(1024)
  data = data.batch(batch_size=params['batch_size'])
  return data


def input_fn_eval(params):
  data = preprocessed_input_fn(for_eval=True)
  data = data.repeat(1)
  data = data.batch(batch_size=params['batch_size'])
  return data


def input_fn_predict(params):
  data = preprocessed_input_fn(for_eval=True)
  data = data.batch(batch_size=params['batch_size'])
  return data

Construisons un modèle qui utilise les incorporations CORD-19 avec une couche de classification sur le dessus.

def model_fn(features, labels, mode, params):
  # Embed the text
  embed = hub.Module(params['module_name'], trainable=params['trainable_module'])
  embeddings = embed(features['feature'])

  # Add a linear layer on top
  logits = tf.layers.dense(
      embeddings, units=THE_DATASET.num_classes(), activation=None)
  predictions = tf.argmax(input=logits, axis=1)

  if mode == tf.estimator.ModeKeys.PREDICT:
    return tf.estimator.EstimatorSpec(
        mode=mode,
        predictions={
            'logits': logits,
            'predictions': predictions,
            'features': features['feature'],
            'labels': features['label']
        })

  # Set up a multi-class classification head
  loss = tf.nn.sparse_softmax_cross_entropy_with_logits(
      labels=labels, logits=logits)
  loss = tf.reduce_mean(loss)

  if mode == tf.estimator.ModeKeys.TRAIN:
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=params['learning_rate'])
    train_op = optimizer.minimize(loss, global_step=tf.train.get_or_create_global_step())
    return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)

  elif mode == tf.estimator.ModeKeys.EVAL:
    accuracy = tf.metrics.accuracy(labels=labels, predictions=predictions)
    precision = tf.metrics.precision(labels=labels, predictions=predictions)
    recall = tf.metrics.recall(labels=labels, predictions=predictions)

    return tf.estimator.EstimatorSpec(
        mode=mode,
        loss=loss,
        eval_metric_ops={
            'accuracy': accuracy,
            'precision': precision,
            'recall': recall,
        })

Hyperparmètres

Former et évaluer le modèle

Entraînons et évaluons le modèle pour voir les performances de la tâche SciCite

estimator = tf.estimator.Estimator(functools.partial(model_fn, params=params))
metrics = []

for step in range(0, STEPS, EVAL_EVERY):
  estimator.train(input_fn=functools.partial(input_fn_train, params=params), steps=EVAL_EVERY)
  step_metrics = estimator.evaluate(input_fn=functools.partial(input_fn_eval, params=params))
  print('Global step {}: loss {:.3f}, accuracy {:.3f}'.format(step, step_metrics['loss'], step_metrics['accuracy']))
  metrics.append(step_metrics)
Global step 0: loss 0.796, accuracy 0.670
Global step 200: loss 0.701, accuracy 0.732
Global step 400: loss 0.682, accuracy 0.719
Global step 600: loss 0.650, accuracy 0.747
Global step 800: loss 0.620, accuracy 0.762
Global step 1000: loss 0.609, accuracy 0.762
Global step 1200: loss 0.605, accuracy 0.762
Global step 1400: loss 0.585, accuracy 0.783
Global step 1600: loss 0.586, accuracy 0.768
Global step 1800: loss 0.577, accuracy 0.774
Global step 2000: loss 0.584, accuracy 0.765
Global step 2200: loss 0.565, accuracy 0.778
Global step 2400: loss 0.570, accuracy 0.776
Global step 2600: loss 0.556, accuracy 0.789
Global step 2800: loss 0.563, accuracy 0.778
Global step 3000: loss 0.557, accuracy 0.784
Global step 3200: loss 0.566, accuracy 0.774
Global step 3400: loss 0.552, accuracy 0.782
Global step 3600: loss 0.551, accuracy 0.785
Global step 3800: loss 0.547, accuracy 0.788
Global step 4000: loss 0.549, accuracy 0.784
Global step 4200: loss 0.548, accuracy 0.785
Global step 4400: loss 0.553, accuracy 0.783
Global step 4600: loss 0.543, accuracy 0.786
Global step 4800: loss 0.548, accuracy 0.783
Global step 5000: loss 0.547, accuracy 0.785
Global step 5200: loss 0.539, accuracy 0.791
Global step 5400: loss 0.546, accuracy 0.782
Global step 5600: loss 0.548, accuracy 0.781
Global step 5800: loss 0.540, accuracy 0.791
Global step 6000: loss 0.542, accuracy 0.790
Global step 6200: loss 0.539, accuracy 0.792
Global step 6400: loss 0.545, accuracy 0.788
Global step 6600: loss 0.552, accuracy 0.781
Global step 6800: loss 0.549, accuracy 0.783
Global step 7000: loss 0.540, accuracy 0.788
Global step 7200: loss 0.543, accuracy 0.782
Global step 7400: loss 0.541, accuracy 0.787
Global step 7600: loss 0.532, accuracy 0.790
Global step 7800: loss 0.537, accuracy 0.792
global_steps = [x['global_step'] for x in metrics]
fig, axes = plt.subplots(ncols=2, figsize=(20,8))

for axes_index, metric_names in enumerate([['accuracy', 'precision', 'recall'],
                                            ['loss']]):
  for metric_name in metric_names:
    axes[axes_index].plot(global_steps, [x[metric_name] for x in metrics], label=metric_name)
  axes[axes_index].legend()
  axes[axes_index].set_xlabel("Global Step")

png

On voit que la perte diminue rapidement alors que surtout la précision augmente rapidement. Tracons quelques exemples pour vérifier comment la prédiction se rapporte aux vraies étiquettes:

predictions = estimator.predict(functools.partial(input_fn_predict, params))
first_10_predictions = list(itertools.islice(predictions, 10))

display_df(
  pd.DataFrame({
      TEXT_FEATURE_NAME: [pred['features'].decode('utf8') for pred in first_10_predictions],
      LABEL_NAME: [THE_DATASET.class_names()[pred['labels']] for pred in first_10_predictions],
      'prediction': [THE_DATASET.class_names()[pred['predictions']] for pred in first_10_predictions]
  }))

Nous pouvons voir que pour cet échantillon aléatoire, le modèle prédit la bonne étiquette la plupart du temps, indiquant qu'il peut assez bien intégrer des phrases scientifiques.

Et après?

Maintenant que vous en savez un peu plus sur les intégrations CORD-19 Swivel de TF-Hub, nous vous encourageons à participer au concours CORD-19 Kaggle pour contribuer à obtenir des informations scientifiques à partir de textes académiques liés au COVID-19.