def beam_search(self, seqs, lens, B, L, vocab): n_best = 1 K = constant.beam_size beam = [Beam(K, n_best=n_best, global_scorer=GNMTGlobalScorer(),) # min_length=self.min_length, # stepwise_penalty=self.stepwise_penalty, # block_ngram_repeat=self.block_ngram_repeat, # exclusion_tokens=exclusion_tokens) for _ in range(B)] # (1) Run the encoder on the src. src_h, dec_h_t = self.encode(seqs, lens) # (2) Repeat src objects `beam_size` times. # Tile states and inputs K times dec_h_t = tile(dec_h_t, K, dim=1) if self.use_attn: src_h = tile(src_h.contiguous(), K, dim=0) # We use now batch_size x beam_size (same as fast mode) # (3) run the decoder to generate sentences, using beam search. for t in range(L): if all((b.done() for b in beam)): break # (a) Construct batch x beam_size nxt words. # Get all the pending current beam words and arrange for forward. x_t = torch.stack([b.get_current_state() for b in beam])#.t().contiguous() x_t = x_t.view(-1) # (b) Decode and forward y_t, dec_h_t = self.decoder(x_t, dec_h_t, src_h) y_t = y_t.view(B, K, -1) # B, K, V y_t = F.log_softmax(y_t, dim=2) # (c) Advance each beam. select_indices_array = [] # Loop over the batch_size number of beams (beam search per sequence) for j, b in enumerate(beam): b.advance(y_t[j], None) select_indices_array.append( b.get_current_origin() + j * K) select_indices = torch.cat(select_indices_array) dec_h_t = dec_h_t.index_select(1, select_indices) # select correct nodes # (4) Extract sentences from beam. preds = [] for b in beam: scores, ks = b.sort_finished(minimum=n_best) hyps = [] for times, k in ks[:n_best]: hyp, _ = b.get_hyp(times, k) hyps.append(" ".join([vocab.index2word[word.item()] for word in hyp if word.item() not in [constant.eou_idx, constant.pad_idx]])) preds.append(hyps[0]) return preds
def __getitem__(self, idx): img_name = os.path.join( os.path.join(self.data_dir, 'train_images/'), self.data.loc[idx, 'image_id'] + '.' + self.image_format) data_provider = self.data.loc[idx, 'data_provider'] gleason_score = self.data.loc[idx, 'gleason_score'] isup_grade = label = self.data.loc[idx, 'isup_grade'] if self.image_format == 'tiff': image = skimage.io.MultiImage(img_name)[self.layer] elif self.image_format == 'png': image = cv2.imread(img_name) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) if self.tile == 1: try: image = crop_tile(image) except ZeroDivisionError: print(img_name) elif self.tile == 2: image = tile(image, sz=512, N=16) #image = np.random.shuffle(image)) image = cv2.hconcat([ cv2.vconcat([image[0], image[1], image[2], image[3]]), cv2.vconcat([image[4], image[5], image[6], image[7]]), cv2.vconcat([image[8], image[9], image[10], image[11]]), cv2.vconcat([image[12], image[13], image[14], image[15]]) ]) if self.transform: image = self.transform(image=image) image = torch.from_numpy(image['image'].transpose(2, 0, 1)) return image, isup_grade
def rpn_loss_regr(y_true, y_pred, y_is_box_label, lambda_rpn_regr=1.0, epsilon=1e-6, device='cpu'): # Smooth L1 loss function # 0.5*x*x (if x_abs < 1) # x_abx - 0.5 (otherwise) # y_true [: , : , : , 36]: 4 values per 9 anchor boxes # y_is_box_label [: , : , : , 9] tilled on the last dimension 4 times. label 1 propogated through all 4 values , # similarly other labels replicated 4 times b = y_true.size(0) x_abs = y_true - y_pred x_abs = torch.abs(x_abs) index_small = torch.where(x_abs <= 1) x_abs[index_small] = torch.pow(x_abs[index_small], 2) / 2 + 0.5 x_abs = x_abs - 0.5 # label 1 means positive box, label 0 means neutral and -1 means negative box # clamp min= 0, removes negative box error y_is_box_label = tile(y_is_box_label, -1, 4, device=device).clamp(min=0) loss = (y_is_box_label * x_abs).view( b, -1).sum(1) / (epsilon + y_is_box_label.view(b, -1).sum(1)) # loss = (y_is_box_label * x_abs).sum() / (epsilon + y_is_box_label.sum() ) return lambda_rpn_regr * loss.mean()
def forward(self, x, action, with_encode=False, hidden=None, cell=None, training=True, action_var=None): output_dict = dict() if not with_encode: x, hidden, output_dict['seg_current'] = self.get_feature(x) if torch.cuda.is_available(): action_var = action_var.cuda() x = tile_first(x, action_var) x[-1] = tile(x[-1], action) hx = self.feature_map_predictor(x) rx, output_dict['seg_pred'] = self.dlaseg.infer(hx) nx_feature_enc = x[1:] + [hx] hidden = torch.cat([hidden[:, self.args.classes:, :, :], rx], dim=1) output_dict['coll_prob'] = self.coll_layer(rx.detach()) output_dict['offroad_prob'] = self.off_layer(rx.detach()) output_dict['speed'] = self.speed_layer(hidden.detach()) return output_dict, nx_feature_enc, hidden, None
def _get_mask_and_degrees(cls, in_degrees, out_features, autoregressive_features, random_mask, is_output): if is_output: out_degrees = utils.tile( _get_input_degrees(autoregressive_features), out_features // autoregressive_features, ) mask = (out_degrees[..., None] > in_degrees).float() else: if random_mask: min_in_degree = torch.min(in_degrees).item() min_in_degree = min(min_in_degree, autoregressive_features - 1) out_degrees = torch.randint( low=min_in_degree, high=autoregressive_features, size=[out_features], dtype=torch.long, ) else: max_ = max(1, autoregressive_features - 1) min_ = min(1, autoregressive_features - 1) out_degrees = torch.arange(out_features) % max_ + min_ mask = (out_degrees[..., None] >= in_degrees).float() return mask, out_degrees
def initialize(self, memory_bank, src_lengths, field_signals, device=None): """Initialize search state for each batch input""" # Repeat state in beam_size def fn_map_state(state, dim): return tile(state, self.beam_size, dim=dim) src_max_len = memory_bank.size(1) memory_bank = tile(memory_bank, self.beam_size) memory_pad_mask = tile(~sequence_mask(src_lengths, src_max_len), self.beam_size) self.memory_lengths = tile(src_lengths, self.beam_size) mb_device = memory_bank.device if device is None: self.device = mb_device self.field_signals = field_signals self.alive_seq = field_signals.repeat_interleave(self.beam_size)\ .unsqueeze(-1).to(self.device) self.is_finished = torch.zeros([self.batch_size, self.beam_size], dtype=torch.uint8, device=self.device) self.best_scores = torch.full([self.batch_size], -1e10, dtype=torch.float, device=self.device) self._beam_offset = torch.arange(0, self.batch_size * self.beam_size, step=self.beam_size, dtype=torch.long, device=self.device) # Give full probability to the first beam on the first step; with no # prior information, choose any (the first beam) self.topk_log_probs = torch.tensor( [0.0] + [float("-inf")] * (self.beam_size - 1), device=self.device).repeat(self.batch_size) # buffers for the topk scores and 'backpointer' self.topk_scores = torch.empty((self.batch_size, self.beam_size), dtype=torch.float, device=self.device) self.topk_ids = torch.empty((self.batch_size, self.beam_size), dtype=torch.long, device=self.device) self._batch_index = torch.empty([self.batch_size, self.beam_size], dtype=torch.long, device=self.device) return fn_map_state, memory_bank, memory_pad_mask
def do_tile(input_task): sample, img_path, cm_path = input_task if ATM_PATH: atm_file = open(ATM_PATH, "r") atm = atm_file.read().split(" ") else: atm = None img = Image.open(img_path) # img normalization img_uncast = remove_colour_cast(img) img_std = LuminosityStandardizer.standardize(np.array(img_uncast)) transformed = normalizer.transform(img_std) img = Image.fromarray(transformed) cm = pd.read_csv(cm_path, header=0, sep='\t', index_col=0) cm = cm.transpose() spots_center_gen = spot_gen(cm) tile_out = os.path.join(TILE_PATH, sample) mkdirs(tile_out) tile(img, spots_center_gen, tile_out, atm)
def __getitem__(self, idx): file_name = self.df['image_id'].values[idx] file_path = f'{self.data_dir}/{file_name}.tiff' image = skimage.io.MultiImage(file_path)[-1] image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # split image image = utils.tile(image, tile_size=128, num_tiles=12) image = torch.from_numpy(1.0 - image / 255.0).float() image = (image - mean) / std image = image.permute(0, 3, 1, 2) return image
def output_examples(self): cols = self.output_cols rows = self.output_rows nimgs = cols * rows zfeed = self.example_noise.eval( ) # need to eval to get value since it's a tf variable imgs = self.sess.run(self.Gz, feed_dict={ self.Z: zfeed, self.is_training: False }) imgs = imgs[:nimgs] # conver [-1,1] back to [0,1] before saving imgs = pixels01(imgs) path = os.path.join(self.dirs['output'], '%06d.jpg' % self.output_img_idx) tiled = tile(imgs, (rows, cols)) as_ints = (tiled * 255.0).astype('uint8') Image.fromarray(as_ints).save(path) self.output_img_idx += 1
def forward_next_step(self, fms_seq, action, with_encode=False, hidden=None, cell=None, training=True, action_var=None): # given the predicted feature maps for the next frame, do: # 1. detect vehicles on the feature maps # 2. infer semantic segmentation on the feature maps # 3. infer feature maps for the following frame # 4. predct events on the feature maps output_dict = dict() fms_seq[-1] = tile(fms_seq[-1], action) pred_fms = self.feature_map_predictor(fms_seq) output_dict['seg_pred'], rx, output_dict['depth_pred'] = self.fm_infer( pred_fms) if self.args.use_detection: output_dict['loc_pred'], output_dict['cls_pred'], output_dict[ 'colls_with_prob'], output_dict["residual_pred"], output_dict[ "conf_pred"], output_dict["dim_pred"], output_dict[ "center_pred"] = self.detector(pred_fms) nx_feature_enc = fms_seq[1:] + [pred_fms] hidden = torch.cat([hidden[:, self.args.classes:, :, :], rx], dim=1) if self.args.use_collision: output_dict['coll_prob'] = self.coll_layer(rx.detach()) # output_dict['coll_other_prob'] = self.coll_other_layer(rx.detach()) # output_dict['coll_vehicles_prob'] = self.coll_vehicle_layer(rx.detach()) if self.args.use_offroad: output_dict['offroad_prob'] = self.offroad_layer(rx.detach()) if self.args.use_offlane: output_dict['offlane_prob'] = self.offlane_layer(rx.detach()) if self.args.use_speed: output_dict['speed'] = self.speed_layer(hidden.detach()) return output_dict, nx_feature_enc, hidden, None
def _beam_search_decoding(self, imgs, beam_size): B = imgs.size(0) # use batch_size*beam_size as new Batch imgs = tile(imgs, beam_size, dim=0) enc_outs, hiddens = self.model.encode(imgs) dec_states, O_t = self.model.init_decoder(enc_outs, hiddens) new_B = imgs.size(0) # first decoding step's input tgt = torch.ones(new_B, 1).long() * START_TOKEN beam = BeamSearch(beam_size, B) for t in range(self.max_len): tgt = beam.current_predictions.unsqueeze(1) dec_states, O_t, probs = self.step_decoding( dec_states, O_t, enc_outs, tgt) log_probs = torch.log(probs) beam.advance(log_probs) any_beam_is_finished = beam.is_finished.any() if any_beam_is_finished: beam.update_finished() if beam.done: break select_indices = beam.current_origin if any_beam_is_finished: # Reorder states h, c = dec_states h = h.index_select(0, select_indices) c = c.index_select(0, select_indices) dec_states = (h, c) O_t = O_t.index_select(0, select_indices) # get results formulas_idx = torch.stack([hyps[1] for hyps in beam.hypotheses], dim=0) results = self._idx2formulas(formulas_idx) return results
def get_mask(in_features, out_features, autoregressive_features, mask_type=None): max_ = max(1, autoregressive_features - 1) min_ = min(1, autoregressive_features - 1) if mask_type == 'input': in_degrees = torch.arange(1, autoregressive_features + 1) out_degrees = torch.arange(out_features) % max_ + min_ mask = (out_degrees[..., None] >= in_degrees).float() elif mask_type == 'output': in_degrees = torch.arange(in_features) % max_ + min_ out_degrees = utils.tile(torch.arange(1, autoregressive_features + 1), out_features // autoregressive_features) mask = (out_degrees[..., None] > in_degrees).float() else: in_degrees = torch.arange(in_features) % max_ + min_ out_degrees = torch.arange(out_features) % max_ + min_ mask = (out_degrees[..., None] >= in_degrees).float() return mask
import numpy as np import pandas as pd import cv2 import matplotlib.pyplot as plt from utils import tile, get_HOG_image from skimage.feature import hog from feature_expansion import feature_threshold, feature_sobel X_tr_orig = np.load("../other/X_tr_orig.npy") X_te_orig = np.load("../other/X_te_orig.npy") y_tr_orig = np.load("../other/y_tr_orig.npy") labels_string = np.load("../other/labels_string.npy") sorted_files_tr_orig = np.load("../other/sorted_files_tr_orig.npy") sorted_files_te_orig = np.load("../other/sorted_files_te_orig.npy") out = tile(300, 600, 3, 10, "../data/train", y_tr_orig, labels_string, 1, 42, 1) cv2.imwrite("../other/figures/visual_small.png", out) img = cv2.imread("../data/train/1.Bmp", 0) h, h_img = hog(img, orientations=8, pixels_per_cell=(15, 15), cells_per_block=(2, 2), visualise=True, normalise=True) a = h_img.min() b = h_img.max() h_img = (h_img - a) / (b - a) * 255 h_img_1 = h_img.astype("uint8") cv2.imwrite("../other/figures/hog_full.png", h_img_1) img = cv2.resize(img, (img.shape[1] / 2, img.shape[0] / 2), interpolation=cv2.INTER_CUBIC) h, h_img = hog(img, orientations=8, pixels_per_cell=(15, 15), cells_per_block=(2, 2), visualise=True, normalise=True) a = h_img.min()
def fn_map_state(state, dim): return tile(state, self.beam_size, dim=dim)
def adapt_with_jigsaw(self, x): # input data if self.n_support == 1: self.repeat_time = 5 # repeat support data if shot =1 x_support = x[:, :self.n_support] x_support = tile(x_support, dim=1, n_tile=self.repeat_time) x_support = x_support.contiguous().view( self.n_way * self.n_support * self.repeat_time, *x.size()[2:]) y_support = torch.from_numpy( np.repeat(range(self.n_way), self.n_support * self.repeat_time)).long().cuda() x_query = x[:, self.n_support:(self.n_support + self.n_query)] x_query = x_query.contiguous().view(self.n_way * self.n_query, *x.size()[2:]) x_unlabeled = x[:, (self.n_support + self.n_query):] x_unlabeled = x_unlabeled.contiguous().view( self.n_way * self.n_unlabeled, *x.size()[2:]) # calculate feature before hand since backbone won't be updated self.eval() with torch.no_grad(): z_query = self.feature(x_query) z_unlabeled = self.feature(x_unlabeled) # classifier + opt classifier = nn.Linear(self.feature_dim, self.n_way).cuda() optimizer = torch.optim.Adam(classifier.parameters()) batch_size = 4 support_size = y_support.size(0) x_support_aug = x_support for epoch in range(100): rand_id = np.random.permutation(support_size) # rand_id = np.array([i for i in range(support_size)]) for i in range(0, support_size, batch_size): selected_id = torch.from_numpy( rand_id[i:min(i + batch_size, support_size)]).long().cuda() x_batch = x_support_aug[selected_id] y_batch = y_support[selected_id] with torch.no_grad(): z = self.feature(x_batch) # backbone is fixed logits = classifier(z) loss = self.ceLoss(logits, y_batch) optimizer.zero_grad() loss.backward() optimizer.step() if epoch < 99: # no aug in last epoch # different data selection strategies for ablation study label2idx, topk_labels = self.selected_by_pseudo_labels( classifier, z_unlabeled) selected_idx = torch.cat(label2idx, dim=0) selected_unlabel_img = x_unlabeled[selected_idx] # local block replacement x_support_aug = self.jigsaw_aug( x_support, selected_unlabel_img, min_replace_block_num=self.jig_replace_min_num, max_replace_block_num=self.jig_replace_max_num) #################### # test on query set after adaptation scores = classifier(z_query) """Get the accuracy""" # query labels y_query = np.repeat(range(self.n_way), self.n_query) topk_scores, topk_labels = scores.data.topk(1, 1, True, True) topk_ind = topk_labels.cpu().numpy() correct = np.sum(topk_ind[:, 0] == y_query) count = len(y_query) return correct, count
def collate_fn(batch): """This function takes list of samples and assembles a batch. It is intended to used in PyTorch DataLoader.""" mfccs, ivectors, embeddings, transcripts, accents = list(zip(*batch)) def exists(list_): """Checks if we are not getting a list of None""" return list_[0] is not None ## Lens if exists(mfccs): inputs_lens = torch.IntTensor([len(m) for m in mfccs]) elif exists(ivectors): inputs_lens = torch.IntTensor([len(i) for i in ivectors]) else: inputs_lens = torch.IntTensor([1] * len(batch)) # Sorting order (needs to be descending in lens for the padder) inputs_lens, sorted_idx = inputs_lens.sort(descending=True) if exists(transcripts): transcripts_lens = torch.IntTensor([len(t) for t in transcripts]) transcripts_lens = transcripts_lens[sorted_idx] else: transcripts_lens = None ## Inputs inputs = [] if exists(mfccs): inputs.append(nn.utils.rnn.pad_sequence(mfccs, batch_first=True)) if exists(ivectors): ivect = nn.utils.rnn.pad_sequence(ivectors, batch_first=True) if exists( mfccs ): # The ivector resolution is 10 times lower than the mfccs', so we expand them. ivect = tile(ivect, 1, 10) ivect = ivect[:, :inputs[0].size(1), :] inputs.append(ivect) if exists(embeddings): emb = torch.cat(embeddings) emb = emb.view(emb.size(0), 1, emb.size(1)) if exists(mfccs) or exists(ivectors): # tile embeddings to fit either mfccs or ivectors size if they are present emb = tile(emb, 1, inputs[0].size(1)) inputs.append(emb) inputs = torch.cat(inputs, dim=2) inputs = inputs[sorted_idx] ## Outputs if exists(transcripts): if inputs.size(0) == 1: # bugfix for when only one sample transcripts = [transcripts] transcripts = np.asarray( transcripts )[sorted_idx] # dtype=object because some transcripts were loaded with wrong type (Int64). TODO fix. transcripts = torch.IntTensor([t for trs in transcripts for t in trs]) # we need text targets as one concatenated vector if exists(accents): accents = torch.cat(accents)[sorted_idx] else: accents = None return inputs, inputs_lens, transcripts, transcripts_lens, accents
def _fast_translate_batch(self, batch, max_length, min_length=0): # TODO: faster code path for beam_size == 1. # TODO: support these blacklisted features. assert not self.dump_beam beam_size = self.beam_size batch_size = batch.batch_size src = batch.src segs = batch.segs mask_src = batch.mask_src # pdb.set_trace() tgt = batch.tgt src_features = self.model.bert_model(input_ids=src, attention_mask=mask_src, token_type_ids=segs) dec_states = self.model.decoder.init_decoder_state(src, src_features, with_cache=True) device = src_features.device # Tile states and memory beam_size times. dec_states.map_batch_fn( lambda state, dim: tile(state, beam_size, dim=dim)) src_features = tile(src_features, beam_size, dim=0) batch_offset = torch.arange(batch_size, dtype=torch.long, device=device) beam_offset = torch.arange(0, batch_size * beam_size, step=beam_size, dtype=torch.long, device=device) alive_seq = torch.full([batch_size * beam_size, 1], self.start_token, dtype=torch.long, device=device) # Give full probability to the first beam on the first step. topk_log_probs = (torch.tensor([0.0] + [float("-inf")] * (beam_size - 1), device=device).repeat(batch_size)) # Structure that holds finished hypotheses. hypotheses = [[] for _ in range(batch_size)] # noqa: F812 results = {} results["predictions"] = [[] for _ in range(batch_size)] # noqa: F812 results["scores"] = [[] for _ in range(batch_size)] # noqa: F812 results["gold_score"] = [0] * batch_size results["batch"] = batch for step in range(max_length): # pdb.set_trace() decoder_input = alive_seq[:, -1].view(1, -1) # Decoder forward. decoder_input = decoder_input.transpose(0, 1) # pdb.set_trace() decoder_outputs = self.decoder( tgt=output.view(output.shape[1], output.shape[0], -1), memory=top_vec[0].view(top_vec[0].shape[1], top_vec[0].shape[0], -1), tgt_mask=tgt_mask, memory_mask=None, tgt_key_padding_mask=tgt_pad_mask, memory_key_padding_mask=src_pad_mask) dec_out, dec_states = self.model.decoder(decoder_input, src_features, dec_states, step=step) #, edit_vec=z) # pdb.set_trace() # Generator forward. log_probs = self.generator.forward( dec_out.transpose(0, 1).squeeze(0)) vocab_size = log_probs.size(-1) if step < min_length: log_probs[:, self.end_token] = -1e20 # Multiply probs by the beam probability. log_probs += topk_log_probs.view(-1).unsqueeze(1) alpha = 0.6 # TODO: change if necessary - self.global_scorer.alpha length_penalty = ((5.0 + (step + 1)) / 6.0)**alpha # Flatten probs into a list of possibilities. curr_scores = log_probs / length_penalty if self.args.block_trigram: cur_len = alive_seq.size(1) if (cur_len > 3): for i in range(alive_seq.size(0)): fail = False words = [int(w) for w in alive_seq[i]] words = [self.vocab.ids_to_tokens[w] for w in words] words = ' '.join(words).replace(' ##', '').split() if (len(words) <= 3): continue trigrams = [(words[i - 1], words[i], words[i + 1]) for i in range(1, len(words) - 1)] trigram = tuple(trigrams[-1]) if trigram in trigrams[:-1]: fail = True if fail: curr_scores[i] = -10e20 curr_scores = curr_scores.reshape(-1, beam_size * vocab_size) topk_scores, topk_ids = curr_scores.topk(beam_size, dim=-1) # Recover log probs. topk_log_probs = topk_scores * length_penalty # Resolve beam origin and true word ids. topk_beam_index = topk_ids.div(vocab_size) topk_ids = topk_ids.fmod(vocab_size) # Map beam_index to batch_index in the flat representation. batch_index = (topk_beam_index + beam_offset[:topk_beam_index.size(0)].unsqueeze(1)) select_indices = batch_index.view(-1) # Append last prediction. alive_seq = torch.cat([ alive_seq.index_select(0, select_indices), topk_ids.view(-1, 1) ], -1) is_finished = topk_ids.eq(self.end_token) if step + 1 == max_length: is_finished.fill_(1) # End condition is top beam is finished. end_condition = is_finished[:, 0].eq(1) # Save finished hypotheses. if is_finished.any(): predictions = alive_seq.view(-1, beam_size, alive_seq.size(-1)) for i in range(is_finished.size(0)): b = batch_offset[i] if end_condition[i]: is_finished[i].fill_(1) finished_hyp = is_finished[i].nonzero().view(-1) # Store finished hypotheses for this batch. for j in finished_hyp: hypotheses[b].append( (topk_scores[i, j], predictions[i, j, 1:])) # If the batch reached the end, save the n_best hypotheses. if end_condition[i]: best_hyp = sorted(hypotheses[b], key=lambda x: x[0], reverse=True) score, pred = best_hyp[0] results["scores"][b].append(score) results["predictions"][b].append(pred) non_finished = end_condition.eq(0).nonzero().view(-1) # If all sentences are translated, no need to go further. if len(non_finished) == 0: break # Remove finished batches for the next step. topk_log_probs = topk_log_probs.index_select(0, non_finished) batch_index = batch_index.index_select(0, non_finished) batch_offset = batch_offset.index_select(0, non_finished) alive_seq = predictions.index_select(0, non_finished) \ .view(-1, alive_seq.size(-1)) # Reorder states. select_indices = batch_index.view(-1) src_features = src_features.index_select(0, select_indices) dec_states.map_batch_fn( lambda state, dim: state.index_select(dim, select_indices)) return results
def train_rl(model, dataloaders): train_dataloader, dev_dataloader, test_dataloader = dataloaders clf_criterion = nn.BCEWithLogitsLoss() mle_criterion = nn.CrossEntropyLoss(ignore_index=constant.pad_idx) baseline_criterion = nn.MSELoss() if constant.optim == 'Adam': opt = torch.optim.Adam(model.parameters(), lr=constant.lr) elif constant.optim == 'SGD': opt = torch.optim.SGD(model.parameters(), lr=constant.lr) else: print("Optim is not defined") exit(1) start_epoch = 1 if constant.restore: model, opt, start_epoch = load_ckpt(model, opt, constant.restore_path) if constant.USE_CUDA: model.cuda() best_dev = 0 best_path = '' patience = 3 scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(opt, 'max', factor=0.5, patience=0, min_lr=1e-6) tau = constant.tau tau_min = 0.2 tau_dec = 0.2 pretrain_curiosity = constant.lambda_aux if constant.pretrain_curiosity: pretrain_curiosity = 0.0 try: for e in range(start_epoch, constant.epochs): model.train() reward_log = [] ori_reward_log = [] aux_reward_log = [] # for sentiment agreement / curiosity inv_loss_log = [] # for curiosity f1_log = [] # pretrain curiosity only for first epoch if e > start_epoch: pretrain_curiosity = constant.lambda_aux # temperature annealing if constant.use_tau_anneal and e > start_epoch and constant.tau > tau_min: constant.tau -= tau_dec if constant.grid_search: pbar = enumerate(train_dataloader) else: pbar = tqdm(enumerate(train_dataloader), total=len(train_dataloader)) for b, (dialogs, lens, targets, _, _, sentiments, sentiments_b, _, _) in pbar: if len(train_dataloader) % (b + 1) == 10: torch.cuda.empty_cache() opt.zero_grad() try: B, T = targets.shape if constant.use_self_critical: step_loss, dec_lens_var, R_g, R, greedy_sents, sampled_sents = model( dialogs, lens, targets) # (R_s - R_g) * step_loss rl_loss = torch.mean( torch.sum((R.detach() - R_g.detach()) * step_loss, dim=1) / dec_lens_var.float()) elif constant.use_arl: step_loss, dec_lens_var, rs, R, arl, sampled_sents = model( dialogs, lens, targets) rs = rs.transpose(0, 1).contiguous() rl_loss = (R.detach() - rs.detach()) * step_loss rl_loss = torch.mean( torch.sum(rl_loss * arl, dim=1) / dec_lens_var.float()) else: # probs: (B, T, V), xs: (B, T), R: (B, 1), rs: (B, T) if constant.use_sentiment and constant.aux_reward_model != '': step_loss, dec_lens_var, rs, R_l, R_s, sampled_sents, clf_logits = model( dialogs, lens, targets, sentiments=sentiments) R = constant.lambda_aux * R_l + R_s clf_loss = clf_criterion(clf_logits, sentiments_b) preds = torch.sigmoid(clf_logits.squeeze()) > 0.5 f1 = f1_score(sentiments_b.cpu().numpy(), preds.detach().cpu().numpy(), average='weighted') f1_log.append(f1) elif constant.use_sentiment and constant.use_sentiment_agreement: step_loss, dec_lens_var, rs, R, sampled_sents, clf_logits = model( dialogs, lens, targets, sentiments=sentiments) clf_loss = clf_criterion(clf_logits, sentiments_b) preds = torch.sigmoid(clf_logits.squeeze()) > 0.5 f1 = f1_score(sentiments_b.cpu().numpy(), preds.detach().cpu().numpy(), average='weighted') f1_log.append(f1) elif constant.use_sentiment_agreement: step_loss, dec_lens_var, rs, R, sampled_sents = model( dialogs, lens, targets, sentiments=sentiments) elif constant.use_sentiment: step_loss, dec_lens_var, rs, R, sampled_sents, clf_logits = model( dialogs, lens, targets, sentiments=sentiments) clf_loss = clf_criterion(clf_logits, sentiments_b) preds = torch.sigmoid(clf_logits.squeeze()) > 0.5 f1 = f1_score(sentiments_b.cpu().numpy(), preds.detach().cpu().numpy(), average='weighted') f1_log.append(f1) elif constant.use_curiosity: step_loss, dec_lens_var, rs, R, R_i, L_i, sampled_sents = model( dialogs, lens, targets) rs = rs.transpose(0, 1).contiguous() R_i = R_i.transpose(0, 1).contiguous() baseline_target = R.detach() * R_i.detach() rl_loss = torch.mean( torch.sum( (R.detach() * R_i.detach() - rs.detach()) * step_loss, dim=1) / dec_lens_var.float()) R_i = torch.mean( torch.sum(R_i, dim=1) / dec_lens_var.float()) else: step_loss, dec_lens_var, rs, R, sampled_sents = model( dialogs, lens, targets) if not constant.use_curiosity: # probs = probs.transpose(0, 1).cntiguous() # xs = xs.transpose(0, 1).contiguous() # # (B, T, V) => (B, T) => (B,) # probs = torch.gather(probs, dim=2, index=xs.unsqueeze(2)).squeeze() # probs = -torch.log(probs) rs = rs.transpose(0, 1).contiguous() rl_loss = torch.mean( torch.sum( (R.detach() - rs.detach()) * step_loss, dim=1) / dec_lens_var.float()) if constant.use_hybrid: probs, _ = model(dialogs, lens, targets, use_mle=True) mle_loss = mle_criterion( probs.transpose(0, 1).contiguous().view(B * T, -1), targets.contiguous().view(B * T)) loss = constant.lambda_mle * rl_loss + ( 1 - constant.lambda_mle) * mle_loss elif constant.use_arl: probs, _ = model(dialogs, lens, targets, use_mle=True) arl_c = torch.ones(arl.size()).to(arl.device) - arl mle_criterion.reduction = 'none' mle_loss = mle_criterion( probs.transpose(0, 1).contiguous().view(B * T, -1), targets.contiguous().view(B * T)) mle_loss = torch.mean( torch.sum(mle_loss * arl_c, dim=1)) loss = rl_loss + mle_loss else: loss = rl_loss if constant.use_sentiment: loss = constant.lambda_emo * clf_loss + ( 1 - constant.lambda_emo) * loss if constant.use_curiosity: loss = pretrain_curiosity * loss + ( 1 - constant.beta) * L_i + constant.beta * R_i loss.backward() opt.step() if constant.use_baseline: if constant.use_curiosity: baseline_loss = baseline_criterion( rs, baseline_target) else: # rs (32, T) <==> R (32, 1) baseline_loss = baseline_criterion( rs, tile(R, T, dim=1)) baseline_loss.backward() opt.step() ## logging reward_log.append(torch.mean(R).item()) if constant.use_sentiment and constant.aux_reward_model != '': ori_reward_log.append(torch.mean(R_l).item()) aux_reward_log.append(torch.mean(R_s).item()) if constant.use_curiosity: aux_reward_log.append(torch.mean(R_i).item()) inv_loss_log.append(L_i.item()) if not constant.grid_search: if constant.use_sentiment: if constant.aux_reward_model != '': pbar.set_description( "(Epoch {}) TRAIN R: {:.3f} R_l: {:.3f} R_s: {:.3f} F1: {:.3f}" .format(e, np.mean(reward_log), np.mean(ori_reward_log), np.mean(aux_reward_log), np.mean(f1_log))) else: pbar.set_description( "(Epoch {}) TRAIN REWARD: {:.4f} TRAIN F1: {:.4f}" .format(e, np.mean(reward_log), np.mean(f1_log))) elif constant.use_curiosity: pbar.set_description( "(Epoch {}) TRAIN R: {:.3f} R_i: {:.3f} L_i: {:.3f}" .format(e, np.mean(reward_log), np.mean(aux_reward_log), np.mean(inv_loss_log))) else: pbar.set_description( "(Epoch {}) TRAIN REWARD: {:.4f}".format( e, np.mean(reward_log))) if b % 100 == 0 and b > 0: # if not constant.use_self_critical: # _, greedy_sents = model(dialogs, lens, targets, test=True, use_mle=True) corrects = [ " ".join([ train_dataloader.dataset.lang.index2word[x_t] for x_t in iter(lambda x=iter(gens): next(x), constant.eou_idx) ]) for gens in targets.cpu().data.numpy() ] contexts = [ " ".join([ train_dataloader.dataset.lang.index2word[x_t] for x_t in iter(lambda x=iter(gens): next(x), constant.pad_idx) ]) for gens in dialogs.cpu().data.numpy() ] for d, c, s, r in zip(contexts, corrects, sampled_sents, R.detach().cpu().numpy()): print('reward: ', r) print('dialog: ', d) print('sample: ', s) print('golden: ', c) print() except RuntimeError as err: if 'out of memory' in str(err): print('| WARNING: ran out of memory, skipping batch') torch.cuda.empty_cache() else: print(err) traceback.print_exc() raise err ## LOG if constant.use_sentiment and not constant.use_sentiment_agreement: dev_reward, dev_f1 = eval_rl(model, dev_dataloader, bleu=False) print("(Epoch {}) DEV REWARD: {:.4f}".format(e, dev_reward)) elif constant.use_curiosity: dev_reward, dev_Ri, dev_Li = eval_rl(model, dev_dataloader, bleu=False) print("(Epoch {}) DEV REWARD: {:.3f} R_i: {:.3f} L_i: {:.3f}". format(e, dev_reward, dev_Ri, dev_Li)) else: dev_reward = eval_rl(model, dev_dataloader, bleu=False) print("(Epoch {}) DEV REWARD: {:.4f}".format(e, dev_reward)) scheduler.step(dev_reward) if (dev_reward > best_dev): best_dev = dev_reward # save best model path = 'trained/data-{}.task-rlseq.lr-{}.tau-{}.lambda-{}.reward-{}.{}' path = path.format(constant.data, constant.lr, tau, constant.lambda_mle, best_dev, constant.reward_model.split('/')[1]) if constant.use_curiosity: path += '.curiosity' if constant.aux_reward_model != '': path += '.' + constant.aux_reward_model.split('/')[1] path += '.lambda_aux-{}'.format(constant.lambda_aux) if constant.use_tau_anneal: path += '.tau_anneal' if constant.use_self_critical: path += '.self_critical' if constant.use_current: path += '.current' if constant.use_sentiment: path += '.sentiment' if constant.use_sentiment_agreement: path += '.agreement' if constant.use_context: path += '.context' if constant.topk: path += '.topk-{}'.format(constant.topk_size) if constant.use_arl: path += '.arl' if constant.grid_search: path += '.grid' best_path = save_model(model, 'reward', best_dev, path) patience = 3 else: patience -= 1 if patience == 0: break if constant.aux_reward_model == '' and best_dev == 0.0: break except KeyboardInterrupt: if not constant.grid_search: print("KEYBOARD INTERRUPT: Save CKPT and Eval") save = True if input('Save ckpt? (y/n)\t') in [ 'y', 'Y', 'yes', 'Yes' ] else False if save: save_path = save_ckpt(model, opt, e) print("Saved CKPT path: ", save_path) # ask if eval do_eval = True if input('Proceed with eval? (y/n)\t') in [ 'y', 'Y', 'yes', 'Yes' ] else False if do_eval: if constant.use_sentiment: if constant.aux_reward_model != '': dev_rewards, dev_f1, dev_bleu, dev_bleus = eval_rl( model, dev_dataloader, bleu=True) print( "DEV R: {:.3f} R_l: {:.3f} R_s: {:.3f} DEV F1: {:.3f} DEV B: {:.3f}" .format(dev_rewards[0], dev_rewards[1], dev_rewards[2], dev_f1, dev_bleu)) else: dev_reward, dev_f1, dev_bleu, dev_bleus = eval_rl( model, dev_dataloader, bleu=True) print( "DEV REWARD: {:.4f}, DEV F1: {:.4f}, DEV BLEU: {:.4f}" .format(dev_reward, dev_f1, dev_bleu)) elif constant.use_curiosity: dev_reward, dev_Ri, dev_Li, dev_bleu, dev_bleus = eval_rl( model, dev_dataloader, bleu=True) print( "BEST DEV REWARD: {:.4f} R_i: {:.3f} L_i: {:.3f} BLEU: {:.4f}" .format(dev_reward, dev_Ri, dev_Li, dev_bleu)) else: dev_reward, dev_bleu, dev_bleus = eval_rl(model, dev_dataloader, bleu=True) print("DEV REWARD: {:.4f}, DEV BLEU: {:.4f}".format( dev_reward, dev_bleu)) print( "BLEU 1: {:.4f}, BLEU 2: {:.4f}, BLEU 3: {:.4f}, BLEU 4: {:.4f}" .format(dev_bleus[0], dev_bleus[1], dev_bleus[2], dev_bleus[3])) exit(1) # load and report best model on test torch.cuda.empty_cache() model = load_model(model, best_path) if constant.USE_CUDA: model.cuda() if constant.use_sentiment and not constant.use_sentiment_agreement: if constant.aux_reward_model != '': dev_rewards, dev_f1, dev_bleu, dev_bleus = eval_rl(model, dev_dataloader, bleu=True) test_rewards, test_f1, test_bleu, test_bleus = eval_rl( model, test_dataloader, bleu=True) print( "DEV R: {:.3f} R_l: {:.3f} R_s: {:.3f} DEV F1: {:.3f} DEV B: {:.3f}" .format(dev_rewards[0], dev_rewards[1], dev_rewards[2], dev_f1, dev_bleu)) print( "BLEU 1: {:.4f}, BLEU 2: {:.4f}, BLEU 3: {:.4f}, BLEU 4: {:.4f}" .format(dev_bleus[0], dev_bleus[1], dev_bleus[2], dev_bleus[3])) print( "TEST R: {:.3f} R_l: {:.3f} R_s: {:.3f} TEST F1: {:.3f} TEST B: {:.3f}" .format(test_rewards[0], test_rewards[1], test_rewards[2], test_f1, test_bleu)) print( "BLEU 1: {:.4f}, BLEU 2: {:.4f}, BLEU 3: {:.4f}, BLEU 4: {:.4f}" .format(test_bleus[0], test_bleus[1], test_bleus[2], test_bleus[3])) else: dev_reward, dev_f1, dev_bleu, dev_bleus = eval_rl(model, dev_dataloader, bleu=True) test_reward, test_f1, test_bleu, test_bleus = eval_rl( model, test_dataloader, bleu=True) print( "DEV REWARD: {:.4f}, DEV F1: {:.4f}, DEV BLEU: {:.4f}".format( dev_reward, dev_f1, dev_bleu)) print( "BLEU 1: {:.4f}, BLEU 2: {:.4f}, BLEU 3: {:.4f}, BLEU 4: {:.4f}" .format(dev_bleus[0], dev_bleus[1], dev_bleus[2], dev_bleus[3])) print("TEST REWARD: {:.4f}, TEST F1: {:.4f}, TEST BLEU: {:.4f}". format(test_reward, test_f1, test_bleu)) print( "BLEU 1: {:.4f}, BLEU 2: {:.4f}, BLEU 3: {:.4f}, BLEU 4: {:.4f}" .format(test_bleus[0], test_bleus[1], test_bleus[2], test_bleus[3])) elif constant.use_curiosity: dev_reward, dev_Ri, dev_Li, dev_bleu, dev_bleus = eval_rl( model, dev_dataloader, bleu=True) test_reward, test_Ri, test_Li, test_bleu, test_bleus = eval_rl( model, test_dataloader, bleu=True) print("BEST DEV REWARD: {:.4f} R_i: {:.3f} L_i: {:.3f} BLEU: {:.4f}". format(dev_reward, dev_Ri, dev_Li, dev_bleu)) print("BLEU 1: {:.4f}, BLEU 2: {:.4f}, BLEU 3: {:.4f}, BLEU 4: {:.4f}". format(dev_bleus[0], dev_bleus[1], dev_bleus[2], dev_bleus[3])) print("BEST TEST REWARD: {:.4f} R_i: {:.3f} L_i: {:.3f} BLEU: {:.4f}". format(test_reward, test_Ri, test_Li, test_bleu)) print("BLEU 1: {:.4f}, BLEU 2: {:.4f}, BLEU 3: {:.4f}, BLEU 4: {:.4f}". format(test_bleus[0], test_bleus[1], test_bleus[2], test_bleus[3])) else: dev_reward, dev_bleu, dev_bleus = eval_rl(model, dev_dataloader, bleu=True) test_reward, test_bleu, test_bleus = eval_rl(model, test_dataloader, bleu=True) print("BEST DEV REWARD: {:.4f}, BLEU: {:.4f}".format( dev_reward, dev_bleu)) print("BLEU 1: {:.4f}, BLEU 2: {:.4f}, BLEU 3: {:.4f}, BLEU 4: {:.4f}". format(dev_bleus[0], dev_bleus[1], dev_bleus[2], dev_bleus[3])) print("BEST TEST REWARD: {:.4f}, BLEU: {:.4f}".format( test_reward, test_bleu)) print("BLEU 1: {:.4f}, BLEU 2: {:.4f}, BLEU 3: {:.4f}, BLEU 4: {:.4f}". format(test_bleus[0], test_bleus[1], test_bleus[2], test_bleus[3]))