ถอดรหัส API

ดูบน TensorFlow.org ทำงานใน Google Colab ดูบน GitHub ดาวน์โหลดโน๊ตบุ๊ค

ภาพรวม

ในอดีตที่ผ่านมา มีการวิจัยเกี่ยวกับการสร้างภาษาด้วยแบบจำลองการถดถอยอัตโนมัติเป็นจำนวนมาก ในรุ่นภาษาอัตโนมัติถอยหลังการกระจายความน่าจะเป็นของโทเค็นในขั้นตอนเวลา K ขึ้นอยู่กับรูปแบบของโทเค็นการคาดการณ์จนถึงขั้นตอนที่ K-1 สำหรับรูปแบบเหล่านี้กลยุทธ์การถอดรหัสเช่นการค้นหา Beam, โลภ, Top-P, และ Top-k เป็นส่วนประกอบที่สำคัญของรูปแบบและส่วนใหญ่มีอิทธิพลต่อรูปแบบ / ลักษณะของการส่งออกที่สร้างโทเค็นที่ให้เวลาขั้นตอน K

ยกตัวอย่างเช่นการค้นหา Beam ช่วยลดความเสี่ยงของการขาดหายไปซ่อนราชสกุลความน่าจะเป็นสูงโดยการรักษา num_beams ส่วนใหญ่ของสมมติฐานในแต่ละขั้นตอนเวลาและในที่สุดก็เลือกสมมติฐานที่ว่ามีความน่าจะเป็นสูงสุดโดยรวม เมอร์เรย์และคณะ (2018) และ ยาง, et al (2018) แสดงการค้นหาลำแสงที่ทำงานได้ดีในงานแปลภาษา ทั้งการค้นหา Beam และกลยุทธ์โลภมีความเป็นไปได้ในการสร้างราชสกุลซ้ำ

แฟนเอต อัล (2018) แนะนำ Top-K สุ่มตัวอย่างซึ่งในภาคส่วนใหญ่มีแนวโน้มราชสกุลจะถูกกรองและมวลน่าจะมีการแจกจ่ายในหมู่เฉพาะผู้ราชสกุล K

อารี โฮลท์ซมัน et. อัล (2019) แนะนำการสุ่มตัวอย่างสูงสุด-P ซึ่งเลือกจากชุดเล็กที่สุดของสัญญาณที่มีความน่าจะเป็นที่สะสมที่เพิ่มเกินหน้าความน่าจะเป็น จากนั้นมวลของความน่าจะเป็นจะถูกแจกจ่ายให้กับชุดนี้ ด้วยวิธีนี้ ขนาดของชุดโทเค็นสามารถเพิ่มและลดแบบไดนามิกได้ Top-P, Top-k โดยทั่วไปจะใช้ในงานต่างๆเช่นเรื่องรุ่น

Decoding API จัดเตรียมอินเทอร์เฟซสำหรับทดลองกับกลยุทธ์การถอดรหัสที่แตกต่างกันในแบบจำลองการถดถอยอัตโนมัติ

  1. กลยุทธ์การสุ่มตัวอย่างต่อไปนี้มีให้ใน sampling_module.py ซึ่งสืบทอดมาจากคลาส Decoding พื้นฐาน:

  2. การค้นหาบีมมีให้ใน beam_search.py github

ติดตั้ง

pip install -q -U tensorflow-text
pip install -q tf-models-nightly
import numpy as np
import matplotlib.pyplot as plt

import tensorflow as tf

from official import nlp
from official.nlp.modeling.ops import sampling_module
from official.nlp.modeling.ops import beam_search
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/pkg_resources/__init__.py:119: PkgResourcesDeprecationWarning: 0.18ubuntu0.18.04.1 is an invalid version and will not be supported in a future release
  PkgResourcesDeprecationWarning,

เริ่มต้นโมดูลการสุ่มตัวอย่างใน TF-NLP

  • symbols_to_logits_fn: ใช้ปิดนี้เพื่อเรียกรูปแบบการทำนาย logits สำหรับ index+1 ขั้นตอน อินพุตและเอาต์พุตสำหรับการปิดนี้มีดังนี้:
Args:
  1] ids : Current decoded sequences. int tensor with shape (batch_size, index + 1 or 1 if padded_decode is True)],
  2] index [scalar] : current decoded step,
  3] cache [nested dictionary of tensors] : Only used for faster decoding to store pre-computed attention hidden states for keys and values. More explanation in the cell below.
Returns:
  1] tensor for next-step logits [batch_size, vocab]
  2] the updated_cache [nested dictionary of tensors].

แคชใช้สำหรับถอดรหัสได้เร็วขึ้น นี่คือ การอ้างอิง การดำเนินการให้มีการปิดดังกล่าวข้างต้น

  • length_normalization_fn: ใช้ปิดนี้ได้กลับมาฟื้นฟูความยาวพารามิเตอร์
Args: 
  1] length : scalar for decoded step index.
  2] dtype : data-type of output tensor
Returns:
  1] value of length normalization factor.
  • vocab_size: เอาท์พุทขนาดคำศัพท์

  • max_decode_length: เกลาสำหรับจำนวนรวมของขั้นตอนการถอดรหัส

  • eos_id: ถอดรหัสจะหยุดถ้าทุกรหัสเอาท์พุทถอดรหัสในชุดมี eos_id นี้

  • padded_decode: ตั้งค่านี้เป็นจริงถ้าทำงานบน TPU เทนเซอร์ถูกเสริมเป็น max_decoding_length หากเป็นจริง

  • top_k: top_k ถูกเปิดใช้งานถ้าค่านี้เป็น> 1

  • top_p: top_p ถูกเปิดใช้งานถ้าค่านี้เป็น> 0 <1.0

  • sampling_temperature: นี้จะใช้ในเรื่องการประเมินการส่งออก softmax อุณหภูมิบิดเบือนการกระจายไปสู่โทเค็นที่มีความเป็นไปได้สูง และลดมวลในการกระจายส่วนท้าย ค่าต้องเป็นบวก อุณหภูมิต่ำเทียบเท่ากับโลภและทำให้การกระจายคมชัดขึ้น ในขณะที่อุณหภูมิสูงทำให้แบนราบมากขึ้น

  • enable_greedy: โดยค่าเริ่มต้นนี้จะเป็นจริงและถอดรหัสโลภถูกเปิดใช้งาน หากต้องการทดลองกับกลยุทธ์อื่นๆ โปรดตั้งค่านี้เป็น "เท็จ"

เริ่มต้นโมเดลไฮเปอร์พารามิเตอร์

params = {}
params['num_heads'] = 2
params['num_layers'] = 2
params['batch_size'] = 2
params['n_dims'] = 256
params['max_decode_length'] = 4

ในสถาปัตยกรรมอัตโนมัติถอยหลังเช่นหม้อแปลงไฟฟ้าตาม Encoder ถอดรหัส รุ่นแคชถูกนำมาใช้สำหรับการถอดรหัสตามลำดับอย่างรวดเร็ว เป็นพจนานุกรมที่ซ้อนกันซึ่งจัดเก็บสถานะที่ซ่อนอยู่ที่คำนวณไว้ล่วงหน้า (คีย์และค่าในบล็อกการเอาใจใส่ตนเองและในบล็อกการเอาใจใส่แบบไขว้) สำหรับทุกเลเยอร์

เริ่มต้นแคช

cache = {
    'layer_%d' % layer: {
        'k': tf.zeros([params['batch_size'], params['max_decode_length'], params['num_heads'], int(params['n_dims']/params['num_heads'])], dtype=tf.float32),
        'v': tf.zeros([params['batch_size'], params['max_decode_length'], params['num_heads'], int(params['n_dims']/params['num_heads'])], dtype=tf.float32)
        } for layer in range(params['num_layers'])
    }
print("cache key shape for layer 1 :", cache['layer_1']['k'].shape)
cache key shape for layer 1 : (2, 4, 2, 128)

กำหนดการปิดสำหรับการปรับความยาวให้เป็นปกติหากจำเป็น

ใช้สำหรับปรับคะแนนสุดท้ายของลำดับที่สร้างขึ้นให้เป็นมาตรฐานและเป็นทางเลือก

def length_norm(length, dtype):
  """Return length normalization factor."""
  return tf.pow(((5. + tf.cast(length, dtype)) / 6.), 0.0)

สร้าง model_fn

ในทางปฏิบัตินี้จะถูกแทนที่ด้วยรูปแบบการดำเนินงานที่เกิดขึ้นจริงเช่น ที่นี่

Args:
i : Step that is being decoded.
Returns:
  logit probabilities of size [batch_size, 1, vocab_size]
probabilities = tf.constant([[[0.3, 0.4, 0.3], [0.3, 0.3, 0.4],
                              [0.1, 0.1, 0.8], [0.1, 0.1, 0.8]],
                            [[0.2, 0.5, 0.3], [0.2, 0.7, 0.1],
                              [0.1, 0.1, 0.8], [0.1, 0.1, 0.8]]])
def model_fn(i):
  return probabilities[:, i, :]

เริ่มต้น symbols_to_logits_fn

def _symbols_to_logits_fn():
  """Calculates logits of the next tokens."""
  def symbols_to_logits_fn(ids, i, temp_cache):
    del ids
    logits = tf.cast(tf.math.log(model_fn(i)), tf.float32)
    return logits, temp_cache
  return symbols_to_logits_fn

โลภ

ถอดรหัสโลภเลือก ID โทเค็นกับความน่าจะเป็นสูงสุดเป็นรหัสต่อไป: \(id_t = argmax_{w}P(id | id_{1:t-1})\) ในแต่ละ timestep \(t\)ภาพร่างต่อไปนี้แสดงให้เห็นถึงการถอดรหัสที่โลภ

greedy_obj = sampling_module.SamplingModule(
    length_normalization_fn=None,
    dtype=tf.float32,
    symbols_to_logits_fn=_symbols_to_logits_fn(),
    vocab_size=3,
    max_decode_length=params['max_decode_length'],
    eos_id=10,
    padded_decode=False)
ids, _ = greedy_obj.generate(
    initial_ids=tf.constant([9, 1]), initial_cache=cache)
print("Greedy Decoded Ids:", ids)
Greedy Decoded Ids: tf.Tensor(
[[9 1 2 2 2]
 [1 1 1 2 2]], shape=(2, 5), dtype=int32)

top_k การสุ่มตัวอย่าง

ใน Top-K สุ่มตัวอย่าง K ส่วนใหญ่มีแนวโน้มรหัสโทเค็นต่อไปจะถูกกรองและมวลน่าจะมีการแจกจ่ายในหมู่เฉพาะผู้ที่รหัส K

top_k_obj = sampling_module.SamplingModule(
    length_normalization_fn=length_norm,
    dtype=tf.float32,
    symbols_to_logits_fn=_symbols_to_logits_fn(),
    vocab_size=3,
    max_decode_length=params['max_decode_length'],
    eos_id=10,
    sample_temperature=tf.constant(1.0),
    top_k=tf.constant(3),
    padded_decode=False,
    enable_greedy=False)
ids, _ = top_k_obj.generate(
    initial_ids=tf.constant([9, 1]), initial_cache=cache)
print("top-k sampled Ids:", ids)
top-k sampled Ids: tf.Tensor(
[[9 1 0 2 2]
 [1 0 1 2 2]], shape=(2, 5), dtype=int32)

top_p การสุ่มตัวอย่าง

แทนการสุ่มตัวอย่างจากส่วนใหญ่มีแนวโน้ม K โทเค็นรหัสใน Top-P สุ่มตัวอย่าง Chooses จากชุดเล็กที่สุดของรหัสที่มีความน่าจะเป็นที่สะสมเกินหน้าน่าจะเป็น

top_p_obj = sampling_module.SamplingModule(
    length_normalization_fn=length_norm,
    dtype=tf.float32,
    symbols_to_logits_fn=_symbols_to_logits_fn(),
    vocab_size=3,
    max_decode_length=params['max_decode_length'],
    eos_id=10,
    sample_temperature=tf.constant(1.0),
    top_p=tf.constant(0.9),
    padded_decode=False,
    enable_greedy=False)
ids, _ = top_p_obj.generate(
    initial_ids=tf.constant([9, 1]), initial_cache=cache)
print("top-p sampled Ids:", ids)
top-p sampled Ids: tf.Tensor(
[[9 1 1 2 2]
 [1 1 1 0 2]], shape=(2, 5), dtype=int32)

การถอดรหัสการค้นหาบีม

การค้นหาบีมช่วยลดความเสี่ยงของการไม่มีรหัสโทเค็นความน่าจะเป็นสูงที่ซ่อนอยู่โดยการรักษา num_beams ของสมมติฐานที่มีแนวโน้มมากที่สุดในแต่ละขั้นตอนของเวลา และสุดท้ายเลือกสมมติฐานที่มีความน่าจะเป็นสูงสุดโดยรวม

beam_size = 2
params['batch_size'] = 1
beam_cache = {
    'layer_%d' % layer: {
        'k': tf.zeros([params['batch_size'], params['max_decode_length'], params['num_heads'], params['n_dims']], dtype=tf.float32),
        'v': tf.zeros([params['batch_size'], params['max_decode_length'], params['num_heads'], params['n_dims']], dtype=tf.float32)
        } for layer in range(params['num_layers'])
    }
print("cache key shape for layer 1 :", beam_cache['layer_1']['k'].shape)
ids, _ = beam_search.sequence_beam_search(
    symbols_to_logits_fn=_symbols_to_logits_fn(),
    initial_ids=tf.constant([9], tf.int32),
    initial_cache=beam_cache,
    vocab_size=3,
    beam_size=beam_size,
    alpha=0.6,
    max_decode_length=params['max_decode_length'],
    eos_id=10,
    padded_decode=False,
    dtype=tf.float32)
print("Beam search ids:", ids)
cache key shape for layer 1 : (1, 4, 2, 256)
Beam search ids: tf.Tensor(
[[[9 0 1 2 2]
  [9 1 2 2 2]]], shape=(1, 2, 5), dtype=int32)