def reward_progressive_match_label(sample, batch, sample_score=None): seq_len = util.find_first_min_zero(sample) mask, __ = util.masked_full_like(sample, 1, num_non_padding=seq_len + 1, dtype=np.int32) mask = mask * (seq_len > 0) sample, _sample = sample * mask, sample label = _label = batch.labels.label pad_width = abs(len(sample) - len(label)) pad_width = ((0, pad_width), (0, 0)) if len(label) < len(sample): label = np.pad(label, pad_width, 'constant', constant_values=0) elif len(sample) < len(label): sample = np.pad(sample, pad_width, 'constant', constant_values=0) diff = np.abs(sample - label) match = (diff == 0).astype(np.float32) # / batch.features.dec_seq_len if len(_label) < len(_sample): match[len(_label) - 1:, :] = 0 elif len(_sample) < len(_label): match = match[:len(_sample), :] avgmatch = np.sum(match * mask) / np.sum(mask) summatch = np.sum(match, axis=0) mismatch = np.argmin(match, axis=0) mismatch_mask, __ = util.masked_full_like(match, 1, num_non_padding=mismatch) match = match * mismatch_mask for ib in range(sample.shape[1]): if summatch[ib] > 0 and mismatch[ib] == 0: continue match[mismatch[ib], ib] = -0.1 return match, avgmatch
def reward_match_label(sample, batch, partial_match=True, sample_score=None): seq_len = util.find_first_min_zero(sample) mask, __ = util.masked_full_like(sample, 1, num_non_padding=seq_len + 1, dtype=np.int32) mask = mask * (seq_len > 0) sample, _sample = sample * mask, sample label = _label = batch.labels.label pad_width = abs(len(sample) - len(label)) pad_width = ((0, pad_width), (0, 0)) if len(label) < len(sample): label = np.pad(label, pad_width, 'constant', constant_values=0) elif len(sample) < len(label): sample = np.pad(sample, pad_width, 'constant', constant_values=0) diff = np.abs(sample - label) if partial_match: match = (diff == 0).astype(np.float32) / (seq_len + 1) if len(_label) < len(_sample): match[len(_label) - 1:, :] = 0 elif len(_sample) < len(_label): match = match[:len(_sample), :] else: sumdiff = np.sum(diff, axis=0) match = np.zeros_like(sample, dtype=np.float32) for ib in range(seq_len.shape[0]): if sumdiff[ib] == 0: match[seq_len[ib], ib] = 1 match = match * mask avgmatch = np.sum(match) / np.sum(seq_len > 0) return match, avgmatch
def get_batch_data(batch, y_arr, unmasked_token_weight=None, unmasked_seq_weight=None, start_id=1, seq_len_idx=1, input_key='inputs', seq_len_key='seq_len'): y_len = np.argmin(y_arr, axis=0) + 1 y_len[batch.features[seq_len_idx] <= 0] = 0 seq_weight = np.where(y_len > 0, 1, 0).astype(np.float32) if unmasked_seq_weight is not None: seq_weight *= unmasked_seq_weight token_weight, num_tokens = util.masked_full_like(y_arr, 1, y_len) if unmasked_token_weight is not None: token_weight *= unmasked_token_weight start = np.full((1, len(y_len)), start_id, dtype=np.int32) * seq_weight x_arr = np.vstack((start.astype(np.int32), y_arr))[:-1, :] features = batch.features._replace(**{ input_key: x_arr, seq_len_key: y_len }) labels = ds.SeqLabelTuple(y_arr, token_weight, seq_weight) batch = ds.BatchTuple(features, labels, num_tokens, batch.keep_state) return batch
def create_seq_data_graph(in_data, out_data, prefix='decoder'): x_arr, x_len = util.hstack_list(in_data, padding=0, dtype=np.int32) y_arr, y_len = util.hstack_list(out_data, padding=0, dtype=np.int32) seq_weight = np.where(y_len > 0, 1, 0).astype(np.float32) token_weight, num_tokens = util.masked_full_like(y_arr, 1, num_non_padding=y_len) all_x = tf.constant(x_arr.T, name='data_input') all_y = tf.constant(y_arr.T, name='data_label') all_len = tf.constant(x_len, name='data_len') all_seq_weight = tf.constant(seq_weight, name='data_seq_weight') all_token_weight = tf.constant(token_weight.T, name='data_token_weight') batch_idx_ = tf.placeholder(tf.int32, shape=[None], name=f'{prefix}_batch_idx') input_ = tf.transpose(tf.gather(all_x, batch_idx_, name=f'{prefix}_input')) label_ = tf.transpose(tf.gather(all_y, batch_idx_, name=f'{prefix}_label')) seq_len_ = tf.gather(all_len, batch_idx_, name=f'{prefix}_seq_len') seq_weight_ = tf.gather(all_seq_weight, batch_idx_, name=f'{prefix}_seq_weight') token_weight_ = tf.transpose( tf.gather(all_token_weight, batch_idx_, name=f'{prefix}_token_weight')) return { f'{prefix}_{k}': v for k, v in util.dict_with_key_endswith(locals(), '_').items() }
def lseq2seq_batch_iter(enc_data, dec_data, label_data, mask_data, batch_size=1, shuffle=True): """same as seq2seq_batch_iter, just add label""" data_tuple = (enc_data, dec_data, label_data, mask_data) for x, y, L, M in batch_iter(batch_size, shuffle, *data_tuple, pad=[[], [], 0, 2]): enc, enc_len = util.hstack_list(x) dec, dec_len = util.hstack_list(y) label = np.array(L, dtype=np.int32) mask = np.array(M, dtype=np.int32) in_dec = dec[:-1, :] out_dec = dec[1:, :] seq_weight = np.where(dec_len > 0, 1, 0) dec_len -= seq_weight token_weight, num_tokens = util.masked_full_like( out_dec, 1, num_non_padding=dec_len) seq_weight = seq_weight.astype(np.float32) features = ds.LSeq2SeqFeatureTuple(enc, enc_len, in_dec, dec_len, label, mask) labels = ds.SeqLabelTuple(out_dec, token_weight, seq_weight) yield ds.BatchTuple(features, labels, num_tokens, False)
def reward_constant(sample, batch, constant=-0.1, sample_score=None): # return batch.labels.label_weight, np.mean(batch.labels.label_weight) seq_len = util.find_first_min_zero(sample) mask, __ = util.masked_full_like(sample, 1, num_non_padding=seq_len + 1, dtype=np.int32) mask = mask * (seq_len > 0) * constant return mask * constant, np.mean(seq_len + 1) * constant
def seq_batch_iter(in_data, out_data, weights, batch_size=1, shuffle=True, keep_sentence=True): """wrapper of batch_iter to format seq data""" keep_state = not keep_sentence # add one more argumennt and pass it to "batch_iter" below # also add 0 for the padding if weights: # import pdb; pdb.set_trace() for x, y, w in batch_iter(batch_size, shuffle, in_data, out_data, weights, pad=[[], [], 0]): x_arr, x_len = util.hstack_list(x) y_arr, y_len = util.hstack_list(y) # w_arr, w_len = util.hstack_list(w) # change seq_weight to be the input weight seq_weight = np.where(y_len > 0, w, 0).astype(np.float32) # import pdb; pdb.set_trace() token_weight, num_tokens = util.masked_full_like( y_arr, w, num_non_padding=y_len) features = ds.SeqFeatureTuple(x_arr, x_len) labels = ds.SeqLabelTuple(y_arr, token_weight, seq_weight) yield ds.BatchTuple(features, labels, num_tokens, keep_state) else: for x, y in batch_iter(batch_size, shuffle, in_data, out_data, pad=[[], []]): x_arr, x_len = util.hstack_list(x) y_arr, y_len = util.hstack_list(y) seq_weight = np.where(y_len > 0, 1, 0).astype(np.float32) token_weight, num_tokens = util.masked_full_like( y_arr, 1, num_non_padding=y_len) features = ds.SeqFeatureTuple(x_arr, x_len) labels = ds.SeqLabelTuple(y_arr, token_weight, seq_weight) yield ds.BatchTuple(features, labels, num_tokens, keep_state)
def test_masked_full_like(self): data = np.random.randn(4, 3) num_non_padding = np.array([4, 1, 0]) outputs, total = util.masked_full_like(data, 1, num_non_padding=num_non_padding, padding=0, dtype=np.float32) self.assertEqual(total, np.sum(num_non_padding), 'num padding is correct') self.assertTrue(np.all(np.sum(outputs, axis=0) == num_non_padding), 'num padding is correct') self.assertEqual(data.shape, outputs.shape, 'output has the same shape') self.assertTrue(np.all(outputs[:, -1] == 0), 'padding value is correct')
def _format_word2def(x, w, c, y, sw): enc, enc_len = util.hstack_list(x) dec, dec_len = util.hstack_list(y) word = np.array(w, dtype=np.int32) char, char_len = util.vstack_list(c) in_dec = dec[:-1, :] out_dec = dec[1:, :] seq_weight = np.array(sw, dtype=np.float32) dec_len -= np.where(dec_len > 0, 1, 0) token_weight, num_tokens = util.masked_full_like(out_dec, 1, num_non_padding=dec_len) seq_weight = seq_weight.astype(np.float32) features = ds.Word2DefFeatureTuple(enc, enc_len, word, char, char_len, in_dec, dec_len) labels = ds.SeqLabelTuple(out_dec, token_weight, seq_weight) return ds.BatchTuple(features, labels, num_tokens, False)
def seq2seq_batch_iter(enc_data, dec_data, batch_size=1, shuffle=True): """wrapper of batch_iter to format seq2seq data""" for x, y in batch_iter(batch_size, shuffle, enc_data, dec_data, pad=[[], []]): enc, enc_len = util.hstack_list(x) dec, dec_len = util.hstack_list(y) in_dec = dec[:-1, :] out_dec = dec[1:, :] seq_weight = np.where(dec_len > 0, 1, 0) dec_len -= seq_weight token_weight, num_tokens = util.masked_full_like( out_dec, 1, num_non_padding=dec_len) seq_weight = seq_weight.astype(np.float32) features = ds.Seq2SeqFeatureTuple(enc, enc_len, in_dec, dec_len) labels = ds.SeqLabelTuple(out_dec, token_weight, seq_weight) yield ds.BatchTuple(features, labels, num_tokens, False)
def reward_ngram_lm(sample, batch, lm, vocab, token_score=True, sample_score=None): # XXX: This is incredibly inefficient. We need a better way to get sequence # likelihood from LM using a list of word ids. if sample_score is None: def score(s): return np.power(10, s) else: def score(s): score = (s / np.log10(np.e)) - sample_score[it, ib] return score seq_len = np.argmin(sample, axis=0) mask, __ = util.masked_full_like(sample, 1, num_non_padding=seq_len + 1, dtype=np.int32) sample, _sample = sample * mask, sample scores = np.zeros_like(sample, dtype=np.float32) words = vocab.i2w(sample) for ib in range(sample.shape[1]): state1, state2 = kenlm.State(), kenlm.State() lm.BeginSentenceWrite(state1) # sentence = [] for it in range(sample.shape[0]): s = lm.BaseScore(state1, words[it][ib], state2) scores[it, ib] = score(s) state1, state2 = state2, state1 if words[it][ib] == '</s>': # scores[it, ib] = 1 / (1 + lm.perplexity(' '.join(sentence))) break # sentence.append(words[it][ib]) # scores = scores * mask # scores = (1 / (1 - scores)) * mask return scores, np.sum(scores) / np.sum(mask)
def seq_batch_iter(in_data, out_data, batch_size=1, shuffle=True, keep_sentence=True): """wrapper of batch_iter to format seq data""" keep_state = not keep_sentence for x, y in batch_iter(batch_size, shuffle, in_data, out_data, pad=[[], []]): x_arr, x_len = util.hstack_list(x) y_arr, y_len = util.hstack_list(y) seq_weight = np.where(y_len > 0, 1, 0).astype(np.float32) token_weight, num_tokens = util.masked_full_like(y_arr, 1, num_non_padding=y_len) features = ds.SeqFeatureTuple(x_arr, x_len) labels = ds.SeqLabelTuple(y_arr, token_weight, seq_weight) yield ds.BatchTuple(features, labels, num_tokens, keep_state)