def get_domain_meta(self): # get domain_meta id_domain_meta = Pack() id_domain_meta['sys_id'] = self.rev_vocab[SYS] id_domain_meta['usr_id'] = self.rev_vocab[USR] for domain, meta in self.domain_meta.items(): description = [domain, SEP] + list(meta.usr_id2slot) + [SEP] + list(meta.sys_id2slot) description = [self.rev_vocab[t] for t in description] templates, acts = [], [] templates.append([self.rev_vocab[t] for t in meta.greet]) acts.append([self.rev_vocab[t] for t in [REQ, '0', 'greet', 'greet']]) for s, value in meta.items(): if '#' not in s: continue for example in value: if s == '#QUERY': s_id = 0 else: s_id = list(meta.usr_id2slot).index(s) if example.is_usr else list(meta.sys_id2slot).index(s) type = INF if example.is_usr else REQ acts.append([self.rev_vocab[t] for t in [type, str(s_id), example.intent, example.slot]]) templates.append([self.rev_vocab[t] for t in example.utt]) id_domain_meta[domain] = Pack(description=description, templates=templates, acts=acts) self.logger.info("{} templates for {}".format(len(templates), domain)) return id_domain_meta
def _process_dialog(self, data): """ For the return dialog corpus, each uttearnce is is represented by: (speaker, conf, utterance) :param data: a list of list of utterances :return: a dialog coprus. """ dialogs = [] all_length = [] all_dialog_len = [] for raw_dialog in data: norm_dialog = [Pack(speaker=USR, conf=1.0, utt= [BOS, raw_dialog[0]['domain'], BOD, EOS])] for l in raw_dialog: msg = Pack.msg_from_dict(l, self.tokenize, {"SYS": SYS, "USR": USR}, BOS, EOS, include_domain=self.include_domain) norm_dialog.append(msg) all_length.append(len(msg.utt)) dialogs.append(norm_dialog) all_dialog_len.append(len(norm_dialog)) max_len = np.max(all_length) mean_len = float(np.average(all_length)) coverage = len(np.where(np.array(all_length) < self.max_utt_len)[0]) / float(len(all_length)) self.logger.info("Max utt len %d, mean utt len %.2f, %d covers %.2f" % (max_len, mean_len, self.max_utt_len, coverage)) self.logger.info("Max dialog len %d, mean dialog len %.2f" % (np.max(all_dialog_len), np.average(all_dialog_len))) return dialogs
def forward(self, data_feed, mode, gen_type='greedy', return_latent=False): """ B: batch_size, D: context_size U: utt_size, X: response_size 1. ctx_lens: B x 1 2. ctx_utts: B x D x U 3. ctx_confs: B x D 4. ctx_floors: B x D 5. out_lens: B x 1 6. out_utts: B x X :param data_feed: {'ctx_lens': vec_ctx_lens, 'ctx_utts': vec_ctx_utts, 'ctx_confs': vec_ctx_confs, 'ctx_floors': vec_ctx_floors, 'out_lens': vec_out_lens, 'out_utts': vec_out_utts} :param return_label :param dec_type :return: outputs """ ctx_lens = data_feed['context_lens'] ctx_utts = self.np2var(data_feed['contexts'], LONG) ctx_confs = self.np2var(data_feed['context_confs'], FLOAT) out_utts = self.np2var(data_feed['outputs'], LONG) batch_size = len(ctx_lens) enc_inputs = self.utt_encoder(ctx_utts, ctx_confs) enc_outs, enc_last = self.ctx_encoder(enc_inputs, ctx_lens) # get decoder inputs labels = out_utts[:, 1:].contiguous() dec_inputs = out_utts[:, 0:-1] # pack attention context if self.config.use_attn: attn_inputs = enc_outs else: attn_inputs = None # create decoder initial states dec_init_state = self.connector(enc_last) # decode dec_outs, dec_last, dec_ctx = self.decoder(batch_size, dec_inputs, dec_init_state, attn_context=attn_inputs, mode=mode, gen_type=gen_type, beam_size=self.config.beam_size) if mode == GEN: return dec_ctx, labels else: if return_latent: return Pack(nll=self.nll(dec_outs, labels), latent_actions=dec_init_state) else: return Pack(nll=self.nll(dec_outs, labels))
def _process_dialog(self, data): new_dialog = [] all_lens = [] all_dialog_lens = [] speaker_map = {'assistant': SYS, 'driver': USR} for raw_dialog in data: domain = raw_dialog['scenario']['task']['intent'] kb_items = [] if raw_dialog['scenario']['kb']['items'] is not None: for item in raw_dialog['scenario']['kb']['items']: kb_items.append([KB] + self.tokenize(" ".join( ["{} {}".format(k, v) for k, v in item.items()]))) dialog = [ Pack(utt=[BOS, domain, BOD, EOS], speaker=USR, slots=None, domain=domain) ] for turn in raw_dialog['dialogue']: utt = turn['data']['utterance'] slots = turn['data'].get('slots') speaker = speaker_map[turn['turn']] if self.config.include_domain: utt = [BOS, speaker, domain] + self.tokenize(utt) + [EOS] else: utt = [BOS, speaker] + self.tokenize(utt) + [EOS] all_lens.append(len(utt)) if speaker == SYS: dialog.append( Pack(utt=utt, speaker=speaker, slots=slots, domain=domain, kb=kb_items)) else: dialog.append( Pack(utt=utt, speaker=speaker, slots=slots, domain=domain, kb=[])) all_dialog_lens.append(len(dialog)) new_dialog.append(dialog) print("Max utt len %d, mean utt len %.2f" % (np.max(all_lens), float(np.mean(all_lens)))) print("Max dialog len %d, mean dialog len %.2f" % (np.max(all_dialog_lens), float(np.mean(all_dialog_lens)))) return new_dialog
def get_dialog_corpus(self): """ Convert utt into word IDs and return the corpus in dictionary. :return: {train: [d1, d2, ...], valid: [d1, d2, ...], test: [d1, d2, ...]} """ # get equal amount of valid data from each domains id2domains = defaultdict(list) for d_id, d in enumerate(self.corpus): id2domains[d[1].domain].append(d_id) domain_valid_size = int( min(1000, int(len(self.corpus) * 0.1)) / len(id2domains)) train_ids, valid_ids = [], [] for ids in id2domains.values(): train_ids.extend(ids[domain_valid_size:]) valid_ids.extend(ids[0:domain_valid_size]) self.logger.info( "Loaded Corpus with train %d, valid %d, test %d" % (len(train_ids), len(valid_ids), len(self.test_corpus))) train_corpus = [self.corpus[i] for i in train_ids] valid_corpus = [self.corpus[i] for i in valid_ids] id_train = self._to_id_corpus('train', train_corpus, use_black_list=True) id_valid = self._to_id_corpus('valid', valid_corpus, use_black_list=True) id_test = self._to_id_corpus('test', self.test_corpus, use_black_list=False) return Pack(train=id_train, valid=id_valid, test=id_test)
def _prepare_warmup_batch(self, selected_ids): # the batch index, the starting point and end point for segment rows = [self.warmup_data[idx] for idx in selected_ids] out_utts, out_lens = [], [] out_acts, out_act_lens = [], [] domains, domain_metas = [], [] for row in rows: out_utt = row.utt # target response out_acts.append(row.actions) out_act_lens.append(len(row.actions)) out_utts.append(out_utt) out_lens.append(len(out_utt)) domains.append(row.domain) domain_metas.append(self.domain_meta[row.domain].description) vec_out_lens = np.array(out_lens) vec_out_utts = np.zeros((self.batch_size, np.max(out_lens)), dtype=np.int32) vec_out_acts = np.zeros((self.batch_size, np.max(out_act_lens)), dtype=np.int32) vec_domain_metas = np.zeros((self.batch_size, self.max_utt_size), dtype=np.int32) for b_id in range(self.batch_size): vec_out_utts[b_id, 0:vec_out_lens[b_id]] = out_utts[b_id] vec_out_acts[b_id, 0:out_act_lens[b_id]] = out_acts[b_id] vec_domain_metas[b_id, :] = domain_metas[b_id] return Pack(output_lens=vec_out_lens, outputs=vec_out_utts, output_actions=vec_out_acts, domains=domains, domain_metas=vec_domain_metas)
def _to_id_corpus(self, name, data, use_black_list): results = [] kick_cnt = 0 domain_cnt = [] for dialog in data: if len(dialog) < 1: continue domain = dialog[0].domain should_filter = np.random.rand() < self.black_ratio if use_black_list and self.black_domains \ and domain in self.black_domains \ and should_filter: kick_cnt += 1 continue temp = [] # convert utterance and feature into numeric numbers for turn in dialog: id_turn = Pack( utt=self._sent2id(turn.utt), speaker=turn.speaker, domain=turn.domain, domain_id=self.rev_vocab[domain], meta=turn.get('meta'), kb=[self._sent2id(item) for item in turn.get('kb', [])]) temp.append(id_turn) results.append(temp) domain_cnt.append(domain) self.logger.info("Filter {} samples from {}".format(kick_cnt, name)) self.logger.info(Counter(domain_cnt).most_common()) return results
def _read_file(domain): with open( os.path.join(path, 'domain_descriptions/{}.tsv'.format(domain)), 'rb') as f: lines = f.readlines() for l in lines[1:]: tokens = l.split('\t') if tokens[2] == "": break utt = tokens[1] speaker = tokens[0] action = tokens[3] if self.config.include_domain: utt = [BOS, speaker_map[speaker], domain ] + self.tokenize(utt) + [EOS] action = [BOS, speaker_map[speaker], domain ] + self.tokenize(action) + [EOS] else: utt = [BOS, speaker_map[speaker] ] + self.tokenize(utt) + [EOS] action = [BOS, speaker_map[speaker] ] + self.tokenize(action) + [EOS] seed_responses.append( Pack(domain=domain, speaker=speaker, utt=utt, actions=action))
def prepare_domain_meta(self, domain_meta): # pre-compute domain meta since it's independent of dialogs # domain description just slot names # domain sys/usr templates example sys or user utterances vec_domain_meta = {} for domain, meta in domain_meta.items(): if type(meta) is not Pack: continue sys_templates = [] sys_acts = [] usr_templates = [] usr_acts = [] for template, act in zip(meta.templates, meta.acts): padded_template = self.pad_to(self.max_utt_size, template) if domain_meta.sys_id in padded_template: # warmup_data.append(Pack(domain=domain, utt=template, act=act)) sys_templates.append(padded_template) sys_acts.append(act) else: usr_templates.append(padded_template) usr_acts.append(act) padded_desc = self.pad_to(self.max_utt_size, meta.description) vec_domain_meta[domain] = Pack(sys_templates=sys_templates, sys_acts=sys_acts, usr_templates=usr_templates, usr_acts=usr_acts, description=padded_desc) return vec_domain_meta
def get_corpus(self): id_train = self._to_id_corpus("Train", self.train_corpus, use_black_list=True) id_valid = self._to_id_corpus("Valid", self.valid_corpus, use_black_list=False) id_test = self._to_id_corpus("Test", self.test_corpus, use_black_list=False) return Pack(train=id_train, valid=id_valid, test=id_test)
def get_turn_corpus(self, speaker): """ :return: all system utterances -> actions """ data = self.corpus + self.test_corpus utt2act = [] for dialog in data: for msg in dialog: if msg.speaker == speaker: utt2act.append(Pack(utt=msg.utt, actions=msg.actions, domain=msg.domain)) return utt2act
def _prepare_batch(self, selected_index): # the batch index, the starting point and end point for segment rows = [self.data[idx] for idx in selected_index] laed_z = self.laed_z_dialog[selected_index, :] cxt_lens, ctx_utts = [], [] out_utts, out_lens = [], [] domains, domain_metas = [], [] for row in rows: in_row, out_row = row.context, row.response # source context batch_ctx = [] #for item in out_row.kb: # batch_ctx.append(item) for turn in in_row: batch_ctx.append(self.pad_to(self.max_utt_size, turn.utt)) cxt_lens.append(len(batch_ctx)) ctx_utts.append(batch_ctx) # target response out_utt = [t for idx, t in enumerate(out_row.utt)] out_utts.append(out_utt) out_lens.append(len(out_utt)) domains.append(out_row.domain) domain_metas.append(out_row.domain_id) domain_metas = np.array(domain_metas) vec_ctx_lens = np.array(cxt_lens) max_ctx_len = np.max(vec_ctx_lens) vec_ctx_utts = np.zeros( (self.batch_size, max_ctx_len, self.max_utt_size), dtype=np.int32) vec_ctx_confs = np.ones((self.batch_size, max_ctx_len), dtype=np.float32) vec_out_utts = np.zeros((self.batch_size, np.max(out_lens)), dtype=np.int32) vec_out_lens = np.array(out_lens) for b_id in range(self.batch_size): vec_out_utts[b_id, 0:vec_out_lens[b_id]] = out_utts[b_id] vec_ctx_utts[b_id, 0:vec_ctx_lens[b_id], :] = ctx_utts[b_id] return Pack(context_lens=vec_ctx_lens, contexts=vec_ctx_utts, context_confs=vec_ctx_confs, output_lens=vec_out_lens, outputs=vec_out_utts, domains=domains, domain_metas=domain_metas, laed_z=laed_z)
def flatten_dialog(self, data, backward_size): results = [] for dialog in data: for i in range(1, len(dialog)): e_id = i s_id = max(0, e_id - backward_size) response = dialog[i].copy() if response.speaker == USR: continue response['utt'] = self.pad_to(self.max_utt_size, response.utt, do_pad=False) response['kb'] = [self.pad_to(self.max_utt_size, item, do_pad=True) for item in response.kb] contexts = [] for turn in dialog[s_id:e_id]: turn['utt'] = self.pad_to(self.max_utt_size, turn.utt, do_pad=False) contexts.append(turn) results.append(Pack(context=contexts, response=response)) return results
def _prepare_batch(self, selected_index): rows = [self.data[idx] for idx in selected_index] # input_context, context_lens, floors, topics, a_profiles, b_Profiles, outputs, output_lens context_lens, context_utts, out_utts, out_lens = [], [], [], [] metas = [] for row in rows: ctx = row.context resp = row.response out_utt = resp.utt context_lens.append(len(ctx)) context_utts.append([turn.utt for turn in ctx]) out_utt = out_utt out_utts.append(out_utt) out_lens.append(len(out_utt)) metas.append(resp.meta) vec_context_lens = np.array(context_lens) vec_context = np.zeros( (self.batch_size, np.max(vec_context_lens), self.max_utt_size), dtype=np.int32) vec_outs = np.zeros((self.batch_size, np.max(out_lens)), dtype=np.int32) vec_out_lens = np.array(out_lens) for b_id in range(self.batch_size): vec_outs[b_id, 0:vec_out_lens[b_id]] = out_utts[b_id] # fill the context tensor new_array = np.empty((vec_context_lens[b_id], self.max_utt_size)) new_array.fill(0) for i, row in enumerate(context_utts[b_id]): for j, ele in enumerate(row): new_array[i, j] = ele vec_context[b_id, 0:vec_context_lens[b_id], :] = new_array return Pack(contexts=vec_context, context_lens=vec_context_lens, outputs=vec_outs, output_lens=vec_out_lens, metas=metas)
def compute_loss(self, dec_outs, dec_ctx, labels): rnn_loss = self.nll_loss(dec_outs, labels) # find attention loss g = dec_ctx.get(DecoderPointerGen.KEY_G) if g is not None: ptr_softmax = dec_ctx[DecoderPointerGen.KEY_PTR_SOFTMAX] flat_ptr = ptr_softmax.view(-1, self.vocab_size) label_mask = labels.view(-1, 1) == self.rev_vocab[PAD] label_ptr = flat_ptr.gather(1, labels.view(-1, 1)) not_in_ctx = label_ptr == 0 mix_ptr = torch.cat([label_ptr, g.view(-1, 1)], dim=1).gather(1, not_in_ctx.long()) # mix_ptr = g.view(-1, 1) + label_ptr attention_loss = -1.0 * torch.log(mix_ptr.clamp(min=1e-10)) attention_loss.masked_fill_(label_mask, 0) valid_cnt = (label_mask.size(0) - torch.sum(label_mask).float()).clamp(min=1e-10) avg_attn_loss = torch.sum(attention_loss) / valid_cnt else: avg_attn_loss = None return Pack(nll=rnn_loss, attn_loss=avg_attn_loss)
def _prepare_warmup_batch(self, selected_ids): # the batch index, the starting point and end point for segment rows = [self.warmup_data[idx] for idx in selected_ids] out_utts, out_lens = [], [] out_acts, out_act_lens = [], [] domains, domain_metas = [], [] laed_z = [] for row in rows: out_utt = [t for idx, t in enumerate(row.utt)] # target response out_acts.append(row.actions) out_act_lens.append(len(row.actions)) out_utts.append(out_utt) out_lens.append(len(out_utt)) domains.append(row.domain) domain_metas.append(row.domain_id) laed_z.append(row.laed_z) laed_z = np.array(laed_z) vec_out_lens = np.array(out_lens) domain_metas = np.array(domain_metas) vec_out_utts = np.zeros((self.batch_size, np.max(out_lens)), dtype=np.int32) vec_out_acts = np.zeros((self.batch_size, np.max(out_act_lens)), dtype=np.int32) for b_id in range(self.batch_size): vec_out_utts[b_id, 0:vec_out_lens[b_id]] = out_utts[b_id] vec_out_acts[b_id, 0:out_act_lens[b_id]] = out_acts[b_id] return Pack(output_lens=vec_out_lens, outputs=vec_out_utts, output_actions=vec_out_acts, domains=domains, domain_metas=domain_metas, laed_z=laed_z)
def flatten_dialog(self, data, laed_z, backward_size): results = [] laed_z_flat = [] for dialog, dialog_laed_z in zip(data, laed_z): for i in range(1, len(dialog)): e_id = i s_id = max(0, e_id - backward_size) response = dialog[i].copy() if response.speaker == USR: continue response['utt'] = self.pad_to(self.max_utt_size, response.utt, do_pad=False) contexts = [] for turn in dialog[s_id:e_id]: turn['utt'] = self.pad_to(self.max_utt_size, turn.utt, do_pad=False) contexts.append(turn) results.append(Pack(context=contexts, response=response)) laed_z_flat.append(dialog_laed_z[i]) return results, np.array(laed_z_flat)
def flatten_dialog(self, data, backward_size): results = [] for dialog in data: for i in range(1, len(dialog) - 1): e_id = i s_id = max(0, e_id - backward_size) response = dialog[i] if response.speaker == USR: continue prev = dialog[i - 1] next = dialog[i + 1] response['utt'] = self.pad_to(self.max_utt_size, response.utt, do_pad=False) prev['utt'] = self.pad_to(self.max_utt_size, prev.utt, do_pad=False) next['utt'] = self.pad_to(self.max_utt_size, next.utt, do_pad=False) contexts = [] for turn in dialog[s_id:e_id]: turn['utt'] = self.pad_to(self.max_utt_size, turn.utt, do_pad=False) contexts.append(turn) results.append( Pack(context=contexts, response=response, prev_resp=prev, next_resp=next)) return results
def _process_meta(self, domain_meta): all_norm_meta = {} for domain_name, domain in domain_meta.items(): norm_meta = Pack() nlg_spec = domain['nlg_spec'] usr_slots = {"#" + s[0]: s[2] for s in domain['usr_slots']} sys_slots = {"#" + s[0]: s[2] for s in domain['sys_slots']} sys_slots['#default'] = [str(t) for t in range(domain['db_size'])] # save the dictionary norm_meta['usr_slots'] = usr_slots norm_meta['sys_slots'] = sys_slots norm_meta['usr_id2slot'] = usr_slots.keys() norm_meta['sys_id2slot'] = sys_slots.keys() norm_meta['greet'] = [BOS, SYS] + self.tokenize( domain['greet']) + [EOS] # add KB searches kb_meta = [] for i in range(1): sample = {} for usr_key in norm_meta.usr_id2slot: sample[usr_key] = np.random.choice(usr_slots[usr_key]) sample_ret = np.random.choice(norm_meta.sys_id2slot) search_str = self._dict_to_str("QUERY", sample, norm_meta.usr_id2slot) search_str += " RET {}".format(sample_ret) search_tkns = [BOS, SYS] + self.tokenize(search_str) + [EOS] kb_meta.append( Pack(slot="#QUERY", is_usr=False, intent="query", utt=search_tkns, kb_search=sample, ret=sample_ret)) norm_meta['#QUERY'] = kb_meta # a dictionary slot_id -> [1 nlg example, dialog act, sys/usr] for slot, examples in nlg_spec.items(): slot = "#{}".format(slot) is_usr = slot in usr_slots vocab = usr_slots[slot] if is_usr else sys_slots[slot] slot_meta = [] for intent, utts in examples.items(): if type(utts) is list: for u in utts: if intent == 'inform': speaker = USR if is_usr else SYS template_utt = [BOS, speaker ] + self.tokenize(u) + [EOS] # cap the example number up to 10 examples = [[BOS, speaker] + self.tokenize(u % word) + [EOS] for word in vocab[0:10]] slot_meta.append( Pack(slot=slot, intent=intent, utt=template_utt, is_usr=is_usr, examples=examples)) else: speaker = SYS if is_usr else USR template_utt = [BOS, speaker ] + self.tokenize(u) + [EOS] slot_meta.append( Pack(slot=slot, intent=intent, is_usr=is_usr, utt=template_utt)) elif type(utts) is dict: # we cap to at most 10 YN questions for expect_answer, qs in utts.items()[0:5]: for q in qs: template_utt = [BOS, USR, expect_answer ] + self.tokenize(q) + [EOS] slot_meta.append( Pack(slot=slot, intent=intent, is_usr=is_usr, expected=expect_answer, utt=template_utt)) else: raise ValueError("Unknown meta type") norm_meta[slot] = slot_meta all_norm_meta[domain_name] = norm_meta # END OF reading self.logger.info("Read {} domain metas".format(len(all_norm_meta))) return all_norm_meta
def forward(self, data_feed, mode, gen_type='greedy', return_latent=False): """ B: batch_size, D: context_size U: utt_size, X: response_size 1. ctx_lens: B x 1 2. ctx_utts: B x D x U 3. ctx_confs: B x D 4. ctx_floors: B x D 5. out_lens: B x 1 6. out_utts: B x X :param data_feed: {'ctx_lens': vec_ctx_lens, 'ctx_utts': vec_ctx_utts, 'ctx_confs': vec_ctx_confs, 'ctx_floors': vec_ctx_floors, 'out_lens': vec_out_lens, 'out_utts': vec_out_utts} :param return_label :param dec_type :return: outputs """ # optional fields ctx_lens = data_feed.get('context_lens') ctx_utts = self.np2var(data_feed.get('contexts'), LONG) ctx_confs = self.np2var(data_feed.get('context_confs'), FLOAT) out_acts = self.np2var(data_feed.get('output_actions'), LONG) domain_metas = self.np2var(data_feed.get('domain_metas'), LONG) # required fields out_utts = self.np2var(data_feed['outputs'], LONG) batch_size = len(data_feed['outputs']) out_confs = self.np2var(np.ones((batch_size, 1)), FLOAT) # forward pass out_embedded, out_outs, _, _ = self.utt_encoder(out_utts.unsqueeze(1), out_confs, return_all=True) out_embedded = self.utt_policy(out_embedded.squeeze(1)) if ctx_lens is None: act_embedded, act_outs, _, _ = self.utt_encoder(out_acts.unsqueeze(1), out_confs, return_all=True) act_embedded = act_embedded.squeeze(1) # create attention contexts attn_inputs = act_outs.contiguous().view(batch_size, -1, self.utt_encoder.output_size) attn_words = out_acts.view(batch_size, -1) latent_action = self.utt_policy(act_embedded) else: utt_embedded, utt_outs, _, _ = self.utt_encoder(ctx_utts, ctx_confs, return_all=True) ctx_outs, ctx_last = self.ctx_encoder(utt_embedded, ctx_lens) # create decoder initial states latent_action = self.policy(ctx_last) # create attention contexts ctx_outs = ctx_outs.unsqueeze(2).repeat(1, 1, ctx_utts.size(2), 1).view(batch_size, -1, self.ctx_encoder.output_size) utt_outs = utt_outs.contiguous().view(batch_size, -1, self.utt_encoder.output_size) attn_inputs = ctx_outs + utt_outs # batch_size x num_word x attn_size attn_words = ctx_utts.view(batch_size, -1) # batch_size x num_words dec_init_state = self.connector(latent_action) # mask out PAD words in the attention inputs attn_inputs, attn_words = self._remove_padding(attn_inputs, attn_words) # get decoder inputs labels = out_utts[:, 1:].contiguous() dec_inputs = out_utts[:, 0:-1] # decode dec_outs, dec_last, dec_ctx = self.decoder(batch_size, dec_inputs, dec_init_state, attn_context=attn_inputs, mode=mode, gen_type=gen_type, beam_size=self.config.beam_size) if mode == GEN: return dec_ctx, labels else: rnn_loss = self.nll_loss(dec_outs, labels) loss_pack = Pack(nll=rnn_loss) if return_latent: loss_pack['latent_actions'] = latent_action loss_pack['distance'] = self.l2_loss(out_embedded,latent_action) return loss_pack
def _prepare_batch(self, selected_index): # the batch index, the starting point and end point for segment rows = [self.data[idx] for idx in selected_index] cxt_lens, ctx_utts, ctx_utts_raw = [], [], [] out_utts, out_lens, out_utts_raw = [], [], [] domains, domain_metas = [], [] for row in rows: in_row, out_row = row.context, row.response # source context batch_ctx = [] for item in out_row.kb: batch_ctx.append(item) for turn in in_row: batch_ctx.append(self.pad_to(self.max_utt_size, turn.utt)) # source context for ELMo raw_batch_ctx = [] for item_raw in out_row.kb_raw: ctx_utts_raw.append(item_raw) for turn in in_row: ctx_utts_raw.append( self.pad_to(self.max_utt_size, turn.utt_raw, pad_value='')) cxt_lens.append(len(batch_ctx)) ctx_utts.append(batch_ctx) # target response out_utt = [t for idx, t in enumerate(out_row.utt)] out_utts.append(out_utt) # out_utts_raw.append(self.pad_to(self.max_dec_utt_size, out_row.utt_raw, pad_value='')) out_lens.append(len(out_utt)) domains.append(out_row.domain) domain_metas.append(out_row.domain_id) ctx_utts_raw = batch_to_ids(ctx_utts_raw) # out_utts_raw = batch_to_ids(out_utts_raw) domain_metas = np.array(domain_metas) vec_ctx_lens = np.array(cxt_lens) max_ctx_len = np.max(vec_ctx_lens) vec_ctx_utts = np.zeros( (self.batch_size, max_ctx_len, self.max_utt_size), dtype=np.int32) vec_ctx_confs = np.ones((self.batch_size, max_ctx_len), dtype=np.float32) vec_out_utts = np.zeros((self.batch_size, np.max(out_lens)), dtype=np.int32) vec_out_lens = np.array(out_lens) vec_ctx_elmo = np.zeros([self.batch_size, max_ctx_len] + list(ctx_utts_raw.shape)[-2:], dtype=np.int32) # vec_out_utts_elmo = out_utts_raw.numpy().reshape([self.batch_size] + list(out_utts_raw.shape)[-2:]) ctx_len_counter = 0 for b_id in range(self.batch_size): vec_out_utts[b_id, 0:vec_out_lens[b_id]] = out_utts[b_id] vec_ctx_utts[b_id, 0:vec_ctx_lens[b_id], :] = ctx_utts[b_id] vec_ctx_elmo[b_id, 0:vec_ctx_lens[b_id], :] = ctx_utts_raw[ ctx_len_counter:ctx_len_counter + vec_ctx_lens[b_id]] ctx_len_counter += vec_ctx_lens[b_id] return Pack( context_lens=vec_ctx_lens, contexts=vec_ctx_utts, context_confs=vec_ctx_confs, contexts_elmo=vec_ctx_elmo, output_lens=vec_out_lens, outputs=vec_out_utts, # outputs_elmo=vec_out_utts_elmo, domains=domains, domain_metas=domain_metas)
def _prepare_batch(self, selected_index): # the batch index, the starting point and end point for segment rows = [self.data[idx] for idx in selected_index] cxt_lens, ctx_utts, ctx_utts_raw = [], [], [] out_utts, out_lens, out_utts_raw = [], [], [] domains, domain_metas = [], [] laed_z = [] for row in rows: in_row, out_row = row.context, row.response # source context batch_ctx = [] for item in out_row.kb: batch_ctx.append(item) # for turn in in_row: #Code for adding the utterance to the batc_ctx. # batch_ctx.append(self.pad_to(self.max_utt_size, turn.utt)) raw_batch_ctx = [] for item_raw in out_row.kb_raw: ctx_utts_raw.append(item_raw) for turn in in_row: ctx_utts_raw.append( self.pad_to(self.max_utt_size, turn.utt_raw, pad_value='')) cxt_lens.append(len(batch_ctx)) ctx_utts.append(batch_ctx) # target response #below commented work is useless. # out_utt = [] # for idx, t in enumerate(out_row.utt): # if type(t) != list and t != '<s>' and t != '</s>' and t != '<sys>': # out_utt.append(t) out_utt = [idx for idx, t in enumerate(out_row.utt)] #index coding out_utts.append(out_utt) out_lens.append(len(out_utt)) domains.append(out_row.domain) domain_metas.append(int(1)) #domain_meta.append(out_row.domain_id) laed_z.append(row.response.laed_z) laed_z = np.array(laed_z) ctx_utts_raw = batch_to_ids(ctx_utts_raw[0]) domain_metas = np.array(domain_metas) vec_ctx_lens = np.array(cxt_lens) max_ctx_len = np.max(vec_ctx_lens) vec_ctx_utts = np.zeros( (self.batch_size, max_ctx_len, self.max_utt_size), dtype=np.int32) vec_ctx_confs = np.ones((self.batch_size, max_ctx_len), dtype=np.float32) vec_out_utts = np.zeros((self.batch_size, np.max(out_lens)), dtype=np.int32) vec_out_lens = np.array(out_lens) vec_ctx_elmo = np.zeros([self.batch_size, max_ctx_len] + list(ctx_utts_raw.shape)[-2:], dtype=np.int32) ctx_len_counter = 0 for b_id in range(self.batch_size): vec_out_utts[b_id, 0:vec_out_lens[b_id]] = out_utts[b_id] vec_ctx_utts[b_id, 0:vec_ctx_lens[b_id], :] = ctx_utts[b_id] #vec_ctx_elmo[b_id, 0:vec_ctx_lens[b_id], :] = ctx_utts_raw[ctx_len_counter: ctx_len_counter + vec_ctx_lens[b_id]] ctx_len_counter += vec_ctx_lens[b_id] return Pack(context_lens=vec_ctx_lens, contexts=vec_ctx_utts, context_confs=vec_ctx_confs, contexts_elmo=vec_ctx_elmo, output_lens=vec_out_lens, outputs=vec_out_utts, domains=domains, domain_metas=domain_metas, laed_z=laed_z)
def _prepare_batch(self, cur_grid, prev_grid): # the batch index, the starting point and end point for segment b_id, s_id, e_id = cur_grid batch_ids = self.batch_indexes[b_id] rows = [self.data[idx] for idx in batch_ids] cxt_lens, ctx_utts, ctx_confs = [], [], [] out_utts, out_lens = [], [] out_acts, out_act_lens = [], [] # sys_templates, sys_acts, sys_lens = [], [], [] # usr_templates, usr_acts, usr_lens = [], [], [] domains, domain_metas= [], [] for row in rows: if s_id < len(row) - 1: if s_id > 0: cut_row = row[0:1] + row[s_id+1:e_id] else: cut_row = row[s_id:e_id] in_row, out_row = cut_row[0:-1], cut_row[-1] out_utt = out_row.utt # source context cxt_lens.append(len(in_row)) batch_ctx, batch_confs = [], [] for turn in in_row: batch_ctx.append(self.pad_to(self.max_utt_size, turn.utt)) batch_confs.append(turn.conf) ctx_utts.append(batch_ctx) ctx_confs.append(batch_confs) # target response out_utts.append(out_utt) out_lens.append(len(out_utt)) out_acts.append(out_row.actions) out_act_lens.append(len(out_row.actions)) domains.append(out_row.domain) domain_metas.append(self.domain_meta[out_row.domain].description) #sys_templates.append(self.domain_meta[out_row.domain].sys_templates) #sys_acts.append(self.domain_meta[out_row.domain].sys_acts) #sys_lens.append(len(sys_templates[-1])) #usr_templates.append(self.domain_meta[out_row.domain].usr_templates) #usr_acts.append(self.domain_meta[out_row.domain].usr_acts) #usr_lens.append(len(usr_templates[-1])) else: raise ValueError("s_id %d larger than row" % s_id) vec_ctx_lens = np.array(cxt_lens) max_ctx_len = np.max(vec_ctx_lens) vec_ctx_utts = np.zeros((self.batch_size, max_ctx_len, self.max_utt_size), dtype=np.int32) vec_ctx_confs = np.zeros((self.batch_size, max_ctx_len), dtype=np.float32) vec_out_utts = np.zeros((self.batch_size, np.max(out_lens)), dtype=np.int32) vec_out_acts = np.zeros((self.batch_size, np.max(out_act_lens)), dtype=np.int32) vec_out_lens = np.array(out_lens) #vec_sys_templates = np.zeros((self.batch_size, np.max(sys_lens), self.max_utt_size), dtype=np.int32) #vec_sys_acts = np.zeros((self.batch_size, np.max(sys_lens), len(sys_acts[0][0])), dtype=np.int32) #vec_usr_templates = np.zeros((self.batch_size, np.max(usr_lens), self.max_utt_size), dtype=np.int32) #vec_usr_acts = np.zeros((self.batch_size, np.max(usr_lens), len(usr_acts[0][0])), dtype=np.int32) vec_domain_metas = np.zeros((self.batch_size, self.max_utt_size), dtype=np.int32) for b_id in range(self.batch_size): vec_out_utts[b_id, 0:vec_out_lens[b_id]] = out_utts[b_id] vec_out_acts[b_id, 0:out_act_lens[b_id]] = out_acts[b_id] vec_ctx_confs[b_id, 0:vec_ctx_lens[b_id]] = ctx_confs[b_id] vec_ctx_utts[b_id, 0:vec_ctx_lens[b_id], :] = ctx_utts[b_id] #vec_sys_templates[b_id, 0:sys_lens[b_id], :] = sys_templates[b_id] #vec_sys_acts[b_id, 0:sys_lens[b_id], :] = sys_acts[b_id] vec_domain_metas[b_id, :] = domain_metas[b_id] #vec_usr_templates[b_id, 0:usr_lens[b_id], :] = usr_templates[b_id] #vec_usr_acts[b_id, 0:usr_lens[b_id]] = usr_acts[b_id] return Pack(context_lens=vec_ctx_lens, contexts=vec_ctx_utts, context_confs=vec_ctx_confs, output_lens=vec_out_lens, outputs=vec_out_utts, output_actions=vec_out_acts, domains=domains, domain_metas=vec_domain_metas)
def _to_id_corpus(self, name, data, use_black_list): results = [] kick_cnt = 0 for dialog in data: temp = [] is_kicked = False should_filter = np.random.rand() < self.black_ratio # convert utterance and feature into numeric numbers for msg in dialog: domain = msg.get("domain") if use_black_list and self.black_domains \ and domain in self.black_domains \ and should_filter: is_kicked = True break copy_msg = msg.copy() copy_msg['utt'] = [self.rev_vocab[t] for t in msg.utt] # make state become Ids if self.include_state and 'state' in copy_msg.keys()\ and copy_msg.state is not None: id_state = [] state = copy_msg.state sys_goals = state['sys_goals'] usr_slots = state['usr_slots'] for slot in usr_slots: # name, expected, value, max_val one_hot_s = self._get_id_slot(slot, domain) # is is_usr, delivered, conf, max_conf, just_kb float_s = [1.0, 0.0, 0.0, slot['max_conf'], 0.0] id_state.append(Pack(cat=one_hot_s, real=float_s)) for goal in sys_goals: # name, expected, value, max_val one_hot_s = self._get_id_slot(goal, domain) # is is_usr, delivered, conf, max_conf, just_kb float_s = [ 0.0, float(goal['delivered']), goal['conf'], 0.0, float(state['kb_update']) ] id_state.append(Pack(cat=one_hot_s, real=float_s)) copy_msg['state'] = id_state # make action become Ids if 'actions' in copy_msg.keys(): str_acts = [] for act in msg.actions: tokens = self._act_to_str(msg.speaker, act) str_acts.append(' '.join(tokens)) str_acts = self.tokenize("|".join(str_acts)) if self.include_domain and False: str_acts = [msg.speaker, domain] + str_acts else: str_acts = [msg.speaker] + str_acts tkn_acts = [self.rev_vocab[t] for t in str_acts] copy_msg['actions'] = tkn_acts temp.append(copy_msg) if not is_kicked: results.append(temp) else: kick_cnt += 1 self.logger.info("Filter {} samples from {}".format(kick_cnt, name)) return results