Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Recuperación de preguntas y respuestas del codificador de oraciones universal multilingüe

Ver en TensorFlow.org Ejecutar en Google Colab Ver en GitHub Descargar cuaderno Ver modelos TF Hub

Esta es una demostración para usar el modelo de preguntas y respuestas multilingüe de Univeral Encoder para la recuperación de texto de preguntas y respuestas , que ilustra el uso de question_encoder y response_encoder del modelo. Usamos oraciones de párrafos SQuAD como el conjunto de datos de demostración, cada oración y su contexto (el texto que rodea la oración) se codifica en incrustaciones de alta dimensión con el response_encoder . Estas incorporaciones se almacenan en un índice creado utilizando la biblioteca simpleneighbors para la recuperación de preguntas y respuestas.

En la recuperación, se selecciona una pregunta aleatoria del conjunto de datos SQuAD y se codifica en una incrustación de alta dimensión con el question_encoder y se consulta el índice simpleneighbors que devuelve una lista de vecinos más cercanos aproximados en el espacio semántico.

Más modelos

Puede encontrar todos los modelos de inserción de texto alojados actualmente aquí y todos los modelos que han sido entrenados en SQuAD también aquí .

Preparar

%%capture

# Install the latest Tensorflow version.
!pip install -q tensorflow_text
!pip install -q simpleneighbors[annoy]
!pip install -q nltk
!pip install -q tqdm

import json
import nltk
import os
import pprint
import random
import simpleneighbors
import urllib
from IPython.display import HTML, display
from tqdm.notebook import tqdm

import tensorflow.compat.v2 as tf
import tensorflow_hub as hub
from tensorflow_text import SentencepieceTokenizer

nltk.download('punkt')


def download_squad(url):
  return json.load(urllib.request.urlopen(url))

def extract_sentences_from_squad_json(squad):
  all_sentences = []
  for data in squad['data']:
    for paragraph in data['paragraphs']:
      sentences = nltk.tokenize.sent_tokenize(paragraph['context'])
      all_sentences.extend(zip(sentences, [paragraph['context']] * len(sentences)))
  return list(set(all_sentences)) # remove duplicates

def extract_questions_from_squad_json(squad):
  questions = []
  for data in squad['data']:
    for paragraph in data['paragraphs']:
      for qas in paragraph['qas']:
        if qas['answers']:
          questions.append((qas['question'], qas['answers'][0]['text']))
  return list(set(questions))

def output_with_highlight(text, highlight):
  output = "<li> "
  i = text.find(highlight)
  while True:
    if i == -1:
      output += text
      break
    output += text[0:i]
    output += '<b>'+text[i:i+len(highlight)]+'</b>'
    text = text[i+len(highlight):]
    i = text.find(highlight)
  return output + "</li>\n"

def display_nearest_neighbors(query_text, answer_text=None):
  query_embedding = model.signatures['question_encoder'](tf.constant([query_text]))['outputs'][0]
  search_results = index.nearest(query_embedding, n=num_results)

  if answer_text:
    result_md = '''
    <p>Random Question from SQuAD:</p>
    <p>&nbsp;&nbsp;<b>%s</b></p>
    <p>Answer:</p>
    <p>&nbsp;&nbsp;<b>%s</b></p>
    ''' % (query_text , answer_text)
  else:
    result_md = '''
    <p>Question:</p>
    <p>&nbsp;&nbsp;<b>%s</b></p>
    ''' % query_text

  result_md += '''
    <p>Retrieved sentences :
    <ol>
  '''

  if answer_text:
    for s in search_results:
      result_md += output_with_highlight(s, answer_text)
  else:
    for s in search_results:
      result_md += '<li>' + s + '</li>\n'

  result_md += "</ol>"
  display(HTML(result_md))
[nltk_data] Downloading package punkt to /home/kbuilder/nltk_data...
[nltk_data]   Unzipping tokenizers/punkt.zip.

Ejecute el siguiente bloque de código para descargar y extraer el conjunto de datos SQuAD en:

  • oraciones es una lista de tuplas (texto, contexto): cada párrafo del conjunto de datos SQuAD se divide en oraciones usando la biblioteca nltk y la oración y el texto del párrafo forman la tupla (texto, contexto).
  • preguntas es una lista de tuplas (pregunta, respuesta).

squad_url = 'https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json' 

squad_json = download_squad(squad_url)
sentences = extract_sentences_from_squad_json(squad_json)
questions = extract_questions_from_squad_json(squad_json)
print("%s sentences, %s questions extracted from SQuAD %s" % (len(sentences), len(questions), squad_url))

print("\nExample sentence and context:\n")
sentence = random.choice(sentences)
print("sentence:\n")
pprint.pprint(sentence[0])
print("\ncontext:\n")
pprint.pprint(sentence[1])
print()
10455 sentences, 10552 questions extracted from SQuAD https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json

Example sentence and context:

sentence:

('The Reverend Alexander Dyce was another benefactor of the library, leaving '
 'over 14,000 books to the museum in 1869.')

context:

('One of the great treasures in the library is the Codex Forster, some of '
 "Leonardo da Vinci's note books. The Codex consists of three parchment-bound "
 'manuscripts, Forster I, Forster II, and Forster III, quite small in size, '
 'dated between 1490 and 1505. Their contents include a large collection of '
 'sketches and references to the equestrian sculpture commissioned by the Duke '
 'of Milan Ludovico Sforza to commemorate his father Francesco Sforza. These '
 'were bequeathed with over 18,000 books to the museum in 1876 by John '
 'Forster. The Reverend Alexander Dyce was another benefactor of the library, '
 'leaving over 14,000 books to the museum in 1869. Amongst the books he '
 'collected are early editions in Greek and Latin of the poets and playwrights '
 'Aeschylus, Aristotle, Homer, Livy, Ovid, Pindar, Sophocles and Virgil. More '
 'recent authors include Giovanni Boccaccio, Dante, Racine, Rabelais and '
 'Molière.')


El siguiente bloque de código configura el gráfico de tensorflow gy la sesión con las firmas question_encoder y response_encoder del modelo Univeral Encoder Multilingual Q&A .


module_url = "https://tfhub.dev/google/universal-sentence-encoder-multilingual-qa/3" 
model = hub.load(module_url)

El siguiente bloque de código calcula las incrustaciones para todo el texto, las tuplas de contexto y las almacena en un índice simpleneighbors usando el response_encoder .


batch_size = 100

encodings = model.signatures['response_encoder'](
  input=tf.constant([sentences[0][0]]),
  context=tf.constant([sentences[0][1]]))
index = simpleneighbors.SimpleNeighbors(
    len(encodings['outputs'][0]), metric='angular')

print('Computing embeddings for %s sentences' % len(sentences))
slices = zip(*(iter(sentences),) * batch_size)
num_batches = int(len(sentences) / batch_size)
for s in tqdm(slices, total=num_batches):
  response_batch = list([r for r, c in s])
  context_batch = list([c for r, c in s])
  encodings = model.signatures['response_encoder'](
    input=tf.constant(response_batch),
    context=tf.constant(context_batch)
  )
  for batch_index, batch in enumerate(response_batch):
    index.add_one(batch, encodings['outputs'][batch_index])

index.build()
print('simpleneighbors index for %s sentences built.' % len(sentences))

Computing embeddings for 10455 sentences

HBox(children=(HTML(value=''), FloatProgress(value=0.0, max=104.0), HTML(value='')))

simpleneighbors index for 10455 sentences built.

En la recuperación, la pregunta se codifica usando el question_encoder y la incrustación de preguntas se usa para consultar el índice simpleneighbors.


num_results = 25 

query = random.choice(questions)
display_nearest_neighbors(query[0], query[1])