<br />

|---|---|---|---|---|
| [![](https://www.tensorflow.org/images/tf_logo_32px.png)View on TensorFlow.org](https://www.tensorflow.org/hub/tutorials/cord_19_embeddings) | [![](https://www.tensorflow.org/images/colab_logo_32px.png)Run in Google Colab](https://colab.research.google.com/github/tensorflow/docs/blob/master/site/en/hub/tutorials/cord_19_embeddings.ipynb) | [![](https://www.tensorflow.org/images/GitHub-Mark-32px.png)View on GitHub](https://github.com/tensorflow/docs/blob/master/site/en/hub/tutorials/cord_19_embeddings.ipynb) | [![](https://www.tensorflow.org/images/download_logo_32px.png)Download notebook](https://storage.googleapis.com/tensorflow_docs/docs/site/en/hub/tutorials/cord_19_embeddings.ipynb) | [![](https://www.tensorflow.org/images/hub_logo_32px.png)See TF Hub model](https://tfhub.dev/tensorflow/cord-19/swivel-128d/1) |

The CORD-19 Swivel text embedding module from TF-Hub (<https://tfhub.dev/tensorflow/cord-19/swivel-128d/1>)
was built to support researchers analyzing natural languages text related to COVID-19.
These embeddings were trained on the titles, authors, abstracts, body texts, and
reference titles of articles in the [CORD-19 dataset](https://api.semanticscholar.org/CorpusID:216056360).

In this colab we will:

- Analyze semantically similar words in the embedding space
- Train a classifier on the SciCite dataset using the CORD-19 embeddings

## Setup

    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

# Analyze the embeddings

Let's start off by analyzing the embedding by calculating and plotting a correlation matrix between different terms. If the embedding learned to successfully capture the meaning of different words, the embedding vectors of semantically similar words should be close together. Let's take a look at some COVID-19 related terms.

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

We can see that the embedding successfully captured the meaning of the different terms. Each word is similar to the other words of its cluster (i.e. "coronavirus" highly correlates with "SARS" and "MERS"), while they are different from terms of other clusters (i.e. the similarity between "SARS" and "Spain" is close to 0).

Now let's see how we can use these embeddings to solve a specific task.

## SciCite: Citation Intent Classification

This section shows how one can use the embedding for downstream tasks such as text classification. We'll use the [SciCite dataset](https://www.tensorflow.org/datasets/catalog/scicite) from TensorFlow Datasets to classify citation intents in academic papers. Given a sentence with a citation from an academic paper, classify whether the main intent of the citation is as background information, use of methods, or comparing results.

### Set up the dataset from TFDS

<br />

<button type="button" class="button-red button expand-control">Toggle code</button>

<br />

    class Dataset:
      """Build a dataset from a TFDS dataset."""
      def __init__(self, tfds_name, feature_name, label_name):
        self.dataset_builder = tfds.builder(tfds_name)
        self.dataset_builder.download_and_prepare()
        self.feature_name = feature_name
        self.label_name = label_name

      def get_data(self, for_eval):
        splits = THE_DATASET.dataset_builder.info.splits
        if tfds.Split.TEST in splits:
          split = tfds.Split.TEST if for_eval else tfds.Split.TRAIN
        else:
          SPLIT_PERCENT = 80
          split = "train[{}%:]".format(SPLIT_PERCENT) if for_eval else "train[:{}%]".format(SPLIT_PERCENT)
        return self.dataset_builder.as_dataset(split=split)

      def num_classes(self):
        return self.dataset_builder.info.features[self.label_name].num_classes

      def class_names(self):
        return self.dataset_builder.info.features[self.label_name].names

      def preprocess_fn(self, data):
        return data[self.feature_name], data[self.label_name]

      def example_fn(self, data):
        feature, label = self.preprocess_fn(data)
        return {'feature': feature, 'label': label}, label


    def get_example_data(dataset, num_examples, **data_kw):
      """Show example data"""
      with tf.Session() as sess:
        batched_ds = dataset.get_data(**data_kw).take(num_examples).map(dataset.preprocess_fn).batch(num_examples)
        it = tf.data.make_one_shot_iterator(batched_ds).get_next()
        data = sess.run(it)
      return data


    TFDS_NAME = 'scicite'
    TEXT_FEATURE_NAME = 'string'
    LABEL_NAME = 'label'
    THE_DATASET = Dataset(TFDS_NAME, TEXT_FEATURE_NAME, LABEL_NAME)

<br />

<br />

### Let's take a look at a few labeled examples from the training set

<br />

<button type="button" class="button-red button expand-control">Toggle code</button>

<br />

    NUM_EXAMPLES = 20 
    data = get_example_data(THE_DATASET, NUM_EXAMPLES, for_eval=False)
    display_df(
        pd.DataFrame({
            TEXT_FEATURE_NAME: [ex.decode('utf8') for ex in data[0]],
            LABEL_NAME: [THE_DATASET.class_names()[x] for x in data[1]]
        }))

<br />

<br />

## Training a citaton intent classifier

We'll train a classifier on the [SciCite dataset](https://www.tensorflow.org/datasets/catalog/scicite) using an Estimator. Let's set up the input_fns to read the dataset into the model

    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

Let's build a model which use the CORD-19 embeddings with a classification layer on top.

    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,
            })

### Hyperparmeters

<br />

<button type="button" class="button-red button expand-control">Toggle code</button>

<br />

    EMBEDDING = 'https://tfhub.dev/tensorflow/cord-19/swivel-128d/1' 
    TRAINABLE_MODULE = False 
    STEPS =   8000
    EVAL_EVERY = 200 
    BATCH_SIZE = 10 
    LEARNING_RATE = 0.01 

    params = {
        'batch_size': BATCH_SIZE,
        'learning_rate': LEARNING_RATE,
        'module_name': EMBEDDING,
        'trainable_module': TRAINABLE_MODULE
    }

<br />

<br />

## Train and evaluate the model

Let's train and evaluate the model to see the performance on the SciCite task

    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_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")

We can see that the loss quickly decreases while especially the accuracy rapidly increases. Let's plot some examples to check how the prediction relates to the true labels:

    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]
      }))

We can see that for this random sample, the model predicts the correct label most of the times, indicating that it can embed scientific sentences pretty well.

# What's next?

Now that you've gotten to know a bit more about the CORD-19 Swivel embeddings from TF-Hub, we encourage you to participate in the CORD-19 Kaggle competition to contribute to gaining scientific insights from COVID-19 related academic texts.

- Participate in the [CORD-19 Kaggle Challenge](https://www.kaggle.com/allen-institute-for-ai/CORD-19-research-challenge)
- Learn more about the [COVID-19 Open Research Dataset (CORD-19)](https://api.semanticscholar.org/CorpusID:216056360)
- See documentation and more about the TF-Hub embeddings at <https://tfhub.dev/tensorflow/cord-19/swivel-128d/1>
- Explore the CORD-19 embedding space with the [TensorFlow Embedding Projector](http://projector.tensorflow.org/?config=https://storage.googleapis.com/tfhub-examples/tensorflow/cord-19/swivel-128d/1/tensorboard/full_projector_config.json)