def map_bb_outputs_to_pred_bbs(outputs, anchors, grids, log=False): if log: print("map_bb_outputs_to_pred_bbs") print("outputs :", outputs) print("anchors :", anchors) print("grids :", grids) # The first two values in the output represent a translation of the anchor box's center. # Grid size is the width and height of the receptive field # delta_center is bounded on the range (-grid_size, grid_size); # that is, the center remains within the original receptive field. delta_center = outputs[:, :2] * (util.to_gpu(grids[:, :2])) if log: print("delta_center :", delta_center) # The last two values in the output represent the width and height of the bounding box. # These values are interpreted as a precentage of the original anchor box's width and height. # percent_sizes is on the range (.5, 1.5). We add 1 since actn_bbs is on the range (-1, 1) percent_sizes = outputs[:, 2:] + 1 if log: print("percent_sizes :", percent_sizes) actn_centers = delta_center + util.to_gpu( anchors)[:, :2] # Calculate predicted center_x and center_y actn_wh = percent_sizes * util.to_gpu( anchors)[:, 2:] # Calculate predicted width and height if log: print("returns :", torch.cat([actn_centers, actn_wh], dim=1)) return torch.cat([actn_centers, actn_wh], dim=1)
def map_label_to_ground_truth(raw_label_bbs, raw_label_classes, anchors, grids, imsize, log=False): label_bbs, label_classes = format_label(raw_label_bbs, raw_label_classes, imsize) if log: print("map_label_to_ground_truth") print("label_bbs: ", label_bbs) print("label_classes: ", label_classes) distances = jaccard(label_bbs, anchors) if log: print("distances: ", distances) prior_overlap, prior_idx = distances.max(1) #if log: print("prior_distances: ", prior_overlap); print("prior_idx: ", prior_idx) gt_overlap, gt_idx = distances.max(0) #if log: print("gt_distances: ", gt_overlap); print("gt_idx: ", gt_idx) gt_overlap[prior_idx] = 1.99 for i, o in enumerate(prior_idx): gt_idx[o] = i #if log: print("gt_distances: ", gt_overlap); print("gt_idx: ", gt_idx) gt_classes = label_classes[gt_idx] #if log: print("gt_classes: ", gt_classes) matches = gt_overlap >= 0.5 #if log: print("matches: ", matches) matching_idxs = torch.nonzero(matches)[:, 0] cls_matches = torch.nonzero(matches + (gt_overlap < .4))[:, 0] if log: print("matching_idxs: ", matching_idxs) gt_classes[matches != 1] = 0 gt_bbs = label_bbs[gt_idx] if log: print("gt_classes: ", gt_classes[matching_idxs]) print("gt_bbs: ", gt_bbs[matching_idxs]) return util.to_gpu(gt_bbs), gt_classes, util.to_gpu( matching_idxs), cls_matches
def __init__(self, model, criterion, optim_fn, lrs=1e-3): self.model = util.to_gpu(model) self.criterion = criterion self.optim_fn = optim_fn param_arr = [{'params':layer.parameters(), 'lr':0} for layer in self.model.children()] self.optimizer = self.optim_fn(param_arr) # Initialize with learning rate of 0 self.set_lr(lrs) # Update learning rate from passed lrs self.running = False
def step(self, input, label): self.optimizer.zero_grad() # Clear past gradent outputs = self.forward(input) # Forward pass loss = self.criterion(outputs, Variable(util.to_gpu(label))) # Calculate loss loss.backward() # Calculate new gradient self.optimizer.step() # Update model parameters return loss.data.tolist()[0] # Return loss value
def __init__(self, model, criterion, optim_fn, lrs=1e-3): self.model = util.to_gpu(model) self.criterion = criterion self.optim_fn = optim_fn param_arr = [{ 'params': layer.parameters(), 'lr': 0 } for layer in self.model.children()] self.optimizer = self.optim_fn(param_arr) self.set_lr(lrs) self.running = False
def forward(self, outputs, label): target = one_hot_embedding(label, self.num_classes + 1) # +1 for background target = util.to_gpu(Variable( target[:, 1:].contiguous())) # Ignore background and send to GPU pred = outputs[:, 1:] # Get the models predictions (no background) weight = self.get_weight(pred, target) return F.binary_cross_entropy_with_logits(pred, target, weight, size_average=False)
def step(self, input, label): self.optimizer.zero_grad() # Clear past gradient outputs = self.forward(input) if isinstance(label, dict): label = {key: Variable(value) for key, value in label.items()} else: label = Variable(util.to_gpu(label)) loss = self.criterion(outputs, label) loss.backward() # Calculate new gradient self.optimizer.step() # Update model parameters return loss.data, outputs # Return loss valur
def on_epoch_end(self, session, lossMeter): self.accuracy_meter.reset() valLoss = sess.LossMeter() with sess.EvalModel(session.model): for input, label, *_ in tqdm(self.val_data, desc="Validating", leave=False): label = Variable(util.to_gpu(label)) output = session.forward(input) step_loss = session.criterion(output, label).data.tolist()[0] valLoss.update(step_loss, label.shape[0]) if self.accuracy_meter is not None: self.accuracy_meter.update(output, label) val_accuracy = self.accuracy_meter.accuracy() if self.accuracy_meter is not None else 0 print("Training Loss: %f Validaton Loss: %f Validation Accuracy: %f" % (lossMeter.debias, valLoss.raw_avg, val_accuracy))
def _get_anchor_positive_triplet_mask(labels): """Return a 2D mask where mask[a, p] is True iff a and p are distinct and have same label. Args: labels: tf.int32 `Tensor` with shape [batch_size] Returns: mask: tf.bool `Tensor` with shape [batch_size, batch_size] """ # Check that i and j are distinct indices_equal = util.to_gpu(torch.eye(labels.size(0))) indices_not_equal = indices_equal != 1 # Check if labels[i] == labels[j] # Uses broadcasting where the 1st argument has shape (1, batch_size) and the 2nd (batch_size, 1) labels_equal = labels.unsqueeze(0) == labels.unsqueeze(1) return labels_equal & indices_not_equal
def on_batch_end(self, session, lossMeter, output, label): label = Variable(util.to_gpu(label)) batch_accuracy = self.train_accuracy_meter.update(output, label) self.batch_train_accuracies.append(batch_accuracy) self.batch_train_losses.append(lossMeter.loss.data.cpu().item()) self.train_raw_loss_meter.update( F.multi_margin_loss(output[-1][0], label).data.cpu(), label.shape[0]) for layer, loss_meter in zip(output[:-1], self.train_embedding_loss_meters): if layer[1] in self.select: loss_meter.update( batch_all_triplet_loss(layer[0].view(layer[0].size(0), -1), label, 1).data.cpu().item()) self.num_batches += 1
def run(self, session, lossMeter=None): self.val_accuracy_meter.reset() val_loss = LossMeter() val_raw_loss = LossMeter() embedding_losses = [LossMeter() for x in range(len(self.select) - 1)] with EvalModel(session.model): for input, label, *_ in tqdm(self.val_data, desc="Validating", leave=False): label = Variable(util.to_gpu(label)) output = session.forward(input) step_loss = session.criterion(output, label).data.cpu() val_loss.update(step_loss, input.shape[0]) val_raw_loss.update( F.multi_margin_loss(output[-1][0], label).data.cpu(), input.shape[0]) self.val_accuracy_meter.update(output, label) for idx, (layer, embedding_loss) in enumerate( zip(output[:-1], embedding_losses)): if layer[1] in self.select: self.names[idx] = layer[1] embedding_loss.update( batch_all_triplet_loss( layer[0].view(layer[0].size(0), -1), label, 1).data.cpu()) self.val_losses.append(val_loss.raw_avg.item()) self.val_raw_losses.append(val_raw_loss.raw_avg.item()) accuracy = self.val_accuracy_meter.accuracy() if self.model_file != None and accuracy > self.best_accuracy: session.save(self.model_file) self.best_accuracy = accuracy self.val_accuracies.append(accuracy) for meter, loss in zip(embedding_losses, self.val_embedding_losses): loss.append(meter.raw_avg)
def load_params(self, file_name=None): if file_name is None: file_name = self.__class__.__name__ + '.pkl' if '/' in file_name: file_name = file_name.replace('/', os.sep) if not os.path.exists(file_name): raise IOError('No file: ' + file_name) with open(file_name, 'rb') as f: params = pickle.load(f) params = [p.astype('f') for p in params] if GPU: params = [to_gpu(p) for p in params] for i, param in enumerate(self.params): param[...] = params[i]
def run(self, session, lossMeter=None): self.batch += 1 if self.accuracy_meter is not None: self.accuracy_meter.reset() valLoss = sess.LossMeter() with sess.EvalModel(session.model): for input, label, *_ in tqdm(self.val_data, desc="Validating", leave=False): if isinstance(label, dict): label = { key: Variable(value) for key, value in label.items() } else: label = Variable(util.to_gpu(label)) output = session.forward(input) step_loss = session.criterion(output, label).data valLoss.update(step_loss, input.shape[0]) if self.accuracy_meter is not None: self.accuracy_meter.update(output, label) val_accuracy = self.accuracy_meter.accuracy( ) if self.accuracy_meter is not None else 0 if self.save_best and val_accuracy > self.best_accuracy: self.best_accuracy = val_accuracy session.save( f'{self.model_dir}/best-{self.batch}-{round(self.best_accuracy.item(), 6)}' ) elif val_accuracy > self.best_accuracy: self.best_accuracy = val_accuracy if lossMeter is not None: tqdm.write( f"Training Loss: {lossMeter.debias} Validaton Loss: {valLoss.raw_avg} Validation Accuracy: {val_accuracy}" ) else: tqdm.write( f"Validaton Loss: {valLoss.raw_avg} Validation Accuracy: {val_accuracy}" )
def tensorboard_embeddings(model, select, dataloader, targets, images, board='./runs'): old_select = model._to_select model._to_select = select writer = SummaryWriter(board) outputs = {name: [] for name in select} with EvalModel(model): for input, label in dataloader: output = model.forward(Variable(util.to_gpu(input))) for layer in output: outputs[layer[1]].append(layer[0].data.cpu().view( layer[0].size(0), -1)) for name, output in outputs.items(): cat = torch.cat(output) writer.add_embedding(cat, tag=name, metadata=targets, label_img=images)
def single_example_loss(self, pred_classes, bb_outputs, label_classes, label_bbs, log=False): gt_bbs, gt_classes, matching_idxs, cls_matches = map_label_to_ground_truth( label_bbs, label_classes, self.anchors, self.grids, self.imsize) if (log): print("gt_classes: ", gt_classes) print("pred_classes: ", pred_classes) pred_bbs = map_bb_outputs_to_pred_bbs(bb_outputs, self.anchors, self.grids) loc_loss = F.smooth_l1_loss(pred_bbs[matching_idxs].float(), gt_bbs[matching_idxs].float(), size_average=False) clas_loss = self.loss_f(pred_classes[util.to_gpu(cls_matches)], gt_classes[cls_matches]) return loc_loss, clas_loss / max(len(matching_idxs), 1)
def _get_triplet_mask(labels): """Return a 3D mask where mask[a, p, n] is True iff the triplet (a, p, n) is valid. A triplet (i, j, k) is valid if: - i, j, k are distinct - labels[i] == labels[j] and labels[i] != labels[k] Args: labels: tf.int32 `Tensor` with shape [batch_size] """ # Check that i, j and k are distinct indices_equal = util.to_gpu(torch.eye(labels.size(0))) indices_not_equal = indices_equal != 1 i_not_equal_j = indices_not_equal.unsqueeze(2) i_not_equal_k = indices_not_equal.unsqueeze(1) j_not_equal_k = indices_not_equal.unsqueeze(0) distinct_indices = (i_not_equal_j & i_not_equal_k) & j_not_equal_k label_equal = labels.unsqueeze(0) == labels.unsqueeze(1) i_equal_j = label_equal.unsqueeze(2) i_equal_k = label_equal.unsqueeze(1) valid_labels = ~i_equal_k & i_equal_j return valid_labels & distinct_indices
def forward(self, input): return self.model(Variable(util.to_gpu(input)))
from trainer import Trainer import pickle import datetime from fashion_mnist import load_fashion_mnist from util import to_cpu, to_gpu from config import GPU from memory_free import memfree start = datetime.datetime.today() data_file = "fashion_mnist" (x_train, t_train), (x_test, t_test) = load_fashion_mnist(flatten=False) x_train_shape = x_train.shape if GPU: x_train = to_gpu(x_train) t_train = to_gpu(t_train) x_test = to_gpu(x_test) t_test = to_gpu(t_test) epoch = 20 mini_batch = 32 n_res_blocks = 3 filters = 32 batchnorm = True params_load = False params_file = "result/201904140553/params.pkl" network = ResidualNetwork(input_dim=x_train_shape[1:], filters=filters, n_res_blocks=n_res_blocks,