Format: text/x-python
⬇ Download File (3.2 KB)
   1  import tensorflow as tf
   2  
   3  import model
   4  
   5  def top_k_logits(logits, k):
   6      if k == 0:
   7          # no truncation
   8          return logits
   9  
  10      def _top_k():
  11          values, _ = tf.nn.top_k(logits, k=k)
  12          min_values = values[:, -1, tf.newaxis]
  13          return tf.where(
  14              logits < min_values,
  15              tf.ones_like(logits, dtype=logits.dtype) * -1e10,
  16              logits,
  17          )
  18      return tf.cond(
  19         tf.equal(k, 0),
  20         lambda: logits,
  21         lambda: _top_k(),
  22      )
  23  
  24  
  25  def top_p_logits(logits, p):
  26      """Nucleus sampling"""
  27      batch, _ = logits.shape.as_list()
  28      sorted_logits = tf.sort(logits, direction='DESCENDING', axis=-1)
  29      cumulative_probs = tf.cumsum(tf.nn.softmax(sorted_logits, axis=-1), axis=-1)
  30      indices = tf.stack([
  31          tf.range(0, batch),
  32          # number of indices to include
  33          tf.maximum(tf.reduce_sum(tf.cast(cumulative_probs <= p, tf.int32), axis=-1) - 1, 0),
  34      ], axis=-1)
  35      min_values = tf.gather_nd(sorted_logits, indices)
  36      return tf.where(
  37          logits < min_values,
  38          tf.ones_like(logits) * -1e10,
  39          logits,
  40      )
  41  
  42  
  43  def sample_sequence(*, hparams, length, start_token=None, batch_size=None, context=None, temperature=1, top_k=0, top_p=1):
  44      if start_token is None:
  45          assert context is not None, 'Specify exactly one of start_token and context!'
  46      else:
  47          assert context is None, 'Specify exactly one of start_token and context!'
  48          context = tf.fill([batch_size, 1], start_token)
  49  
  50      def step(hparams, tokens, past=None):
  51          lm_output = model.model(hparams=hparams, X=tokens, past=past, reuse=tf.AUTO_REUSE)
  52  
  53          logits = lm_output['logits'][:, :, :hparams.n_vocab]
  54          presents = lm_output['present']
  55          presents.set_shape(model.past_shape(hparams=hparams, batch_size=batch_size))
  56          return {
  57              'logits': logits,
  58              'presents': presents,
  59          }
  60  
  61      with tf.name_scope('sample_sequence'):
  62          def body(past, prev, output):
  63              next_outputs = step(hparams, prev, past=past)
  64              logits = next_outputs['logits'][:, -1, :]  / tf.to_float(temperature)
  65              logits = top_k_logits(logits, k=top_k)
  66              logits = top_p_logits(logits, p=top_p)
  67              samples = tf.multinomial(logits, num_samples=1, output_dtype=tf.int32)
  68              return [
  69                  next_outputs['presents'] if past is None else tf.concat([past, next_outputs['presents']], axis=-2),
  70                  samples,
  71                  tf.concat([output, samples], axis=1)
  72              ]
  73  
  74          past, prev, output = body(None, context, context)
  75  
  76          def cond(*args):
  77              return True
  78  
  79          _, _, tokens = tf.while_loop(
  80              cond=cond, body=body,
  81              maximum_iterations=length - 1,
  82              loop_vars=[
  83                  past,
  84                  prev,
  85                  output
  86              ],
  87              shape_invariants=[
  88                  tf.TensorShape(model.past_shape(hparams=hparams, batch_size=batch_size)),
  89                  tf.TensorShape([batch_size, None]),
  90                  tf.TensorShape([batch_size, None]),
  91              ],
  92              back_prop=False,
  93          )
  94  
  95          return tokens
  96