def __init__(self, name, inputs, targets, tower_setup, merge_type): super(CompleteSiameseMerge, self).__init__() curr, n_features_inp = prepare_input(inputs) batch_size = smart_shape(curr)[0] curr1 = curr[:,tf.newaxis,:] curr2 = curr[tf.newaxis,:,:] if merge_type == "concat": # curr1_big = tf.reshape(tf.tile(curr1, [batch_size]), [batch_size, -1]) # curr2_big = tf.reshape(tf.tile(curr2, [batch_size]), [batch_size, -1]) curr1 = tf.transpose(curr1, perm=[1, 0, 2]) curr1_big = tf.tile(curr1, [batch_size,1,1]) curr1_big = tf.transpose(curr1_big, perm=[1, 0, 2]) curr2_big = tf.tile(curr2, [batch_size,1,1]) whole_mat = tf.concat((curr1_big,curr2_big),2) elif merge_type == "add": whole_mat = curr1 + curr2 elif merge_type == "subtract": whole_mat = curr1 - curr2 elif merge_type == "abs_subtract": whole_mat = tf.abs(curr1 - curr2) else: raise ValueError("No correct merge type") targets1 = targets[:,tf.newaxis] targets2 = targets[tf.newaxis,:] whole_targets = tf.cast(tf.equal(targets1,targets2),tf.int32) boolean_target = tf.cast(tf.ones([batch_size,batch_size]),tf.bool) #### Following extracts one sided + diagonal, but for now we are using both sided as concat is non-symmetric #### In future may want to remove the diagonal # boolean_target = tf.matrix_band_part(boolean_target, -1, 0),tf.bool targets_list = tf.boolean_mask(whole_targets,boolean_target) vectors_list = tf.boolean_mask(whole_mat,boolean_target) debug = 0 if debug: # Print - debug example code def test(a): print(a) return numpy.array([5], dtype="int32") t, = tf.py_func(test, [smart_shape(targets_list)], [tf.int32]) with tf.control_dependencies([t]): targets_list = tf.identity(targets_list) t, = tf.py_func(test, [smart_shape(vectors_list)], [tf.int32]) with tf.control_dependencies([t]): targets_list = tf.identity(targets_list) self.outputs = [vectors_list] self.out_labels = targets_list
def Expand(idx): anchor = curr[idx, :] anchor_class = targets[idx] classes,classes_ids = tf.unique(targets) anchor_class_id = classes_ids[idx] class_division = tf.cast(tf.equal(targets, anchor_class), tf.int32) - tf.cast(tf.equal(list(range(0,size)),idx),tf.int32) partitioned_output = tf.dynamic_partition(curr, class_division, 2) #partitioned_targets = tf.dynamic_partition(targets, class_division, 2) # Positives positives = partitioned_output[1] size_positives = smart_shape(positives)[0] anchor_positive_repmat = tf.reshape(tf.tile(anchor,[size_positives]),[size_positives,-1]) positives_combined = tf.concat((anchor_positive_repmat,positives),1) new_targets_positive = tf.ones([smart_shape(positives_combined)[0]],dtype=tf.int32) # Negatives negative_size = smart_shape(classes)[0] def Get_negatives(neg_idx): curr_neg_class = classes[neg_idx] neg_class_division = tf.cast(tf.equal(targets, curr_neg_class), tf.int32) neg_partitioned_output = tf.dynamic_partition(curr, neg_class_division, 2) negative_set = neg_partitioned_output[1] size_negative_set = smart_shape(negative_set)[0] random_negative_idx = tf.random_shuffle(tf.range(1, size_negative_set))[0] random_negative = negative_set[random_negative_idx,:] return random_negative looper = tf.range(0, anchor_class_id) iter_val = tf.minimum(anchor_class_id+1,negative_size) # looper = tf.range(0, idx) # iter_val = tf.minimum(idx + 1, negative_size) looper = tf.concat([looper,tf.range(iter_val,negative_size)],0) negatives = tf.map_fn(Get_negatives, looper, dtype=tf.float32) size_negatives = smart_shape(negatives)[0] anchor_negative_repmat = tf.reshape(tf.tile(anchor, [size_negatives]), [size_negatives, -1]) negatives_combined = tf.concat((anchor_negative_repmat,negatives),1) new_targets_negative = tf.zeros([smart_shape(negatives_combined)[0]],dtype=tf.int32) all_combined = tf.concat((positives_combined,negatives_combined),0) new_targets_combined = tf.concat((new_targets_positive,new_targets_negative),0) return all_combined, new_targets_combined
def Get_negatives(neg_idx): curr_neg_class = classes[neg_idx] neg_class_division = tf.cast(tf.equal(targets, curr_neg_class), tf.int32) neg_partitioned_output = tf.dynamic_partition(curr, neg_class_division, 2) negative_set = neg_partitioned_output[1] size_negative_set = smart_shape(negative_set)[0] random_negative_idx = tf.random_shuffle(tf.range(1, size_negative_set))[0] random_negative = negative_set[random_negative_idx,:] return random_negative
def create_tensor_dict(unnormalized_img, label, tag, raw_label=None, old_label=None, flow_past=None, flow_future=None, use_index_img=False, u0=None, u1=None, bboxes=None, ids=None, classes=None, img_id=None, ignore_regions=None, scene_infos=None, old_label_as_dt=None): tensors = {"unnormalized_img": unnormalized_img, "tag": tag} #note that "label" is a bit a misnomer, since it's actually a mask. better rename it at some point if label is not None: tensors["label"] = label if raw_label is None: if label is not None: tensors["raw_label"] = label else: tensors["raw_label"] = raw_label if old_label is not None: tensors["old_label"] = old_label if flow_past is not None: tensors["flow_past"] = flow_past if flow_future is not None: tensors["flow_future"] = flow_future if bboxes is not None: tensors[Constants.BBOXES] = bboxes if ids is not None: tensors[Constants.IDS] = ids if classes is not None: tensors[Constants.CLASSES] = classes if u0 is not None: tensors[Constants.DT_NEG] = u0 if u1 is not None: tensors[Constants.DT_POS] = u1 if img_id is not None: tensors[Constants.IMG_IDS] = img_id if ignore_regions is not None: tensors[Constants.IGNORE_REGIONS] = ignore_regions if scene_infos is not None: tensors[Constants.SCENE_INFOS] = scene_infos if old_label_as_dt is not None: tensors[Constants.OLD_LABEL_AS_DT] = old_label_as_dt if use_index_img: shape = smart_shape(unnormalized_img) index_img = create_index_image(shape[0], shape[1]) tensors["index_img"] = index_img return tensors
def embed(image, offset, pad_mode): """ Embeds the image and performs reflection padding. :param image: The tensor to translate. :param offset: The offset by which we translate. :param pad_mode: The padding mode, or a constant :return: The augmented image. """ # Compute offsets and sizes #shape = image.get_shape().as_list() shape = smart_shape(image) start = [tf.maximum(-offset[0], 0), tf.maximum(-offset[1], 0)] size = [shape[0] - tf.abs(offset[0]), shape[1] - tf.abs(offset[1])] # Pad the image on the opposite side padding = [[tf.maximum(0, offset[0]), tf.maximum(0, -offset[0])], [tf.maximum(0, offset[1]), tf.maximum(0, -offset[1])]] # no padding on channel dimension for images if len(image.get_shape().as_list()) == 3: start.append(0) size.append(shape[2]) padding.append([0, 0]) # Extract the image region that is defined by the offset region = tf.slice(image, start, size) # region = image[max(-offset[0], 0):shape[0]-max(0, offset[0]), # max(-offset[1], 0):shape[1]-max(0, offset[1])] if isinstance(pad_mode, str): region = tf.pad(region, padding, mode=pad_mode) return region else: const = pad_mode dtype = region.dtype region = tf.cast(region, tf.int32) - const region = tf.pad(region, padding, mode='CONSTANT') region = region + const return tf.cast(region, dtype)
def apply(self, tensors, scale=None): if scale is None: # atm minval 1.0 to only zoom in, later also allow smaller values scale = tf.random_uniform([1], minval=1.0, maxval=1.25, dtype=tf.float32, seed=None) img = tensors["unnormalized_img"] h, w = smart_shape(img)[:2] crop_size = (h, w) h_scaled = tf.to_int32(tf.ceil(tf.cast(h, scale.dtype) * scale)) w_scaled = tf.to_int32(tf.ceil(tf.cast(w, scale.dtype) * scale)) scaled_size = tf.concat([h_scaled, w_scaled], axis=0) offset = None aug_tensors = tensors.copy() def _scale(key, bilinear, offset_, force_key=False): if force_key: assert key in tensors if key in tensors: im = tensors[key] aug_im = resize_image(im, scaled_size, bilinear) aug_im, offset_ = random_crop_image(aug_im, crop_size, offset_) aug_tensors[key] = aug_im return offset_ offset = _scale("unnormalized_img", True, offset, True) _scale("label", False, offset, False) _scale("old_label", False, offset) _scale("index_img", False, offset) _scale("flow_past", True, offset) _scale("flow_future", True, offset) #attention: when we zoom in, the shift in number of pixels (i.e. optical flow) gets larger if "flow_past" in aug_tensors: aug_tensors["flow_past"] *= scale if "flow_future" in aug_tensors: aug_tensors["flow_future"] *= scale return aug_tensors
def clustering_features_extractor(engine, output_layer): outputs = output_layer.outputs[0] features = output_layer.y_class_features det_boxes, det_scores, reid, det_classes, num_detections = outputs det_boxes = tf.squeeze(det_boxes, axis=2) #conceptual problem: the features before the softmax are shared across anchors #let's just ignore that for now and replicate the features for each anchor n_anchors = 9 shape = smart_shape(features) features = tf.tile(tf.expand_dims(features, axis=2), multiples=[1, 1, n_anchors, 1]) features = tf.reshape(features, tf.stack([shape[0], -1, shape[-1]], axis=0)) def extract(filename, extract_boxes): data = engine.valid_data feed_dict = { data.img_filename_placeholder: filename, data.bboxes_placeholder: extract_boxes } det_boxes_val, det_features_val, det_scores_val = engine.session.run( [det_boxes, features, det_scores], feed_dict=feed_dict) #remove batch dimension batch_size = det_boxes_val.shape[0] assert batch_size == 1 det_boxes_val = det_boxes_val[0] det_features_val = det_features_val[0] det_scores_val = det_scores_val[0] #compute IOUs and select most overlapping, for convenience let's do this with numpy instead of tensorflow ious = compute_ious(det_boxes_val, extract_boxes) indices = ious.argmax(axis=1) det_features_out = det_features_val[indices] det_scores_out = det_scores_val[indices] return det_features_out, det_scores_out return extract
def reshape_group(self, x, batch_size): shape = smart_shape(x) shape2 = shape[1:] shape2[0] = self.group_size * batch_size x = tf.reshape(x, shape2) return x
def __init__(self, name, inputs, targets, tower_setup, merge_type): super(ExpandedSiameseMerge, self).__init__() curr, n_features_inp = prepare_input(inputs) size = smart_shape(curr)[0] def Expand(idx): anchor = curr[idx, :] anchor_class = targets[idx] classes,classes_ids = tf.unique(targets) anchor_class_id = classes_ids[idx] class_division = tf.cast(tf.equal(targets, anchor_class), tf.int32) - tf.cast(tf.equal(list(range(0,size)),idx),tf.int32) partitioned_output = tf.dynamic_partition(curr, class_division, 2) #partitioned_targets = tf.dynamic_partition(targets, class_division, 2) # Positives positives = partitioned_output[1] size_positives = smart_shape(positives)[0] anchor_positive_repmat = tf.reshape(tf.tile(anchor,[size_positives]),[size_positives,-1]) positives_combined = tf.concat((anchor_positive_repmat,positives),1) new_targets_positive = tf.ones([smart_shape(positives_combined)[0]],dtype=tf.int32) # Negatives negative_size = smart_shape(classes)[0] def Get_negatives(neg_idx): curr_neg_class = classes[neg_idx] neg_class_division = tf.cast(tf.equal(targets, curr_neg_class), tf.int32) neg_partitioned_output = tf.dynamic_partition(curr, neg_class_division, 2) negative_set = neg_partitioned_output[1] size_negative_set = smart_shape(negative_set)[0] random_negative_idx = tf.random_shuffle(tf.range(1, size_negative_set))[0] random_negative = negative_set[random_negative_idx,:] return random_negative looper = tf.range(0, anchor_class_id) iter_val = tf.minimum(anchor_class_id+1,negative_size) # looper = tf.range(0, idx) # iter_val = tf.minimum(idx + 1, negative_size) looper = tf.concat([looper,tf.range(iter_val,negative_size)],0) negatives = tf.map_fn(Get_negatives, looper, dtype=tf.float32) size_negatives = smart_shape(negatives)[0] anchor_negative_repmat = tf.reshape(tf.tile(anchor, [size_negatives]), [size_negatives, -1]) negatives_combined = tf.concat((anchor_negative_repmat,negatives),1) new_targets_negative = tf.zeros([smart_shape(negatives_combined)[0]],dtype=tf.int32) all_combined = tf.concat((positives_combined,negatives_combined),0) new_targets_combined = tf.concat((new_targets_positive,new_targets_negative),0) return all_combined, new_targets_combined expanded, new_targets = tf.map_fn(Expand, tf.range(0, size), dtype=(tf.float32, tf.int32)) if merge_type == "concat": expanded = tf.reshape(expanded, [-1, n_features_inp * 2]) elif merge_type == "add": part1 = expanded[::2, :] part2 = expanded[1::2, :] expanded = part1 + part2 elif merge_type == "subtract": part1 = expanded[::2, :] part2 = expanded[1::2, :] expanded = part1 - part2 elif merge_type == "abs_subtract": part1 = expanded[::2, :] part2 = expanded[1::2, :] expanded = tf.abs(part1 - part2) else: expanded = expanded new_targets = tf.reshape(new_targets, [-1]) debug = 0 if debug: # Print - debug example code def test(a): print(a) return numpy.array([5], dtype="int32") t, = tf.py_func(test, [smart_shape(new_targets)], [tf.int32]) with tf.control_dependencies([t]): expanded = tf.identity(expanded) self.outputs = [expanded] self.out_labels = new_targets
def resize_detection_fixed_size(tensors, input_size, for_testing=False): tensors_out = tensors.copy() #ignore_regions are currently not supported in this resize mode if Constants.IGNORE_REGIONS in tensors_out: del tensors_out[Constants.IGNORE_REGIONS] img = tensors[Constants.UNNORMALIZED_IMG] original_img = img bboxes = tensors[Constants.BBOXES] # remove the padding n_real_detections = tf.reduce_sum( tf.cast(tensors[Constants.IDS] > 0, tf.int32)) bboxes = bboxes[:n_real_detections] classes = tensors[Constants.CLASSES][:n_real_detections] # permute y1, y2, x1, x2 -> y1, x1, y2, x1 bboxes = tf.stack( [bboxes[..., 0], bboxes[..., 2], bboxes[..., 1], bboxes[..., 3]], axis=-1) # normalize bboxes to [0..1] height = tf.shape(img)[0] width = tf.shape(img)[1] bboxes = tf.cast(bboxes, tf.float32) / tf.cast( tf.stack([height, width, height, width], axis=0), tf.float32) import object_detection.core.preprocessor as preproc if not for_testing: #crop (ssd style) img, bboxes, classes = preproc.ssd_random_crop(img, bboxes, classes) #alternative #img, bboxes, classes = preproc.random_crop_image(img, real_boxes, real_boxes) # include random horizontal flip augmentation here img, bboxes = preproc.random_horizontal_flip(img, bboxes) #resize image, note: boxes don't need resizing as they are in relative coordinates img = preproc.resize_image(img, new_height=input_size[0], new_width=input_size[1]) if for_testing: _, bboxes = preproc.scale_boxes_to_pixel_coordinates( original_img, bboxes) else: _, bboxes = preproc.scale_boxes_to_pixel_coordinates(img, bboxes) #permute back y1, x1, y2, x1 -> y1, y2, x1, x2 bboxes = tf.stack( [bboxes[..., 0], bboxes[..., 2], bboxes[..., 1], bboxes[..., 3]], axis=-1) #pad the stuff needs to be padded back to the maximum size padded_size = smart_shape(tensors[Constants.CLASSES])[0] n_real_detections_after_crop = smart_shape(bboxes)[0] pad_size = padded_size - n_real_detections_after_crop paddings_bboxes = [[0, pad_size], [0, 0]] bboxes = tf.pad(bboxes, paddings=paddings_bboxes) paddings_classes_ids = [[0, pad_size]] classes = tf.pad(classes, paddings=paddings_classes_ids) ids = tf.pad(tf.range(n_real_detections_after_crop) + 1, paddings=paddings_classes_ids) if isinstance(padded_size, int): bboxes.set_shape((padded_size, 4)) classes.set_shape((padded_size, )) ids.set_shape((padded_size, )) else: bboxes.set_shape((None, 4)) #note that we do not retain the original ids, but it does not matter since this resize_mode is only meant for #isolated frames tensors_out[Constants.UNNORMALIZED_IMG] = img tensors_out[Constants.BBOXES] = bboxes tensors_out[Constants.CLASSES] = classes tensors_out[Constants.IDS] = ids tensors_out[Constants.RESIZED_SIZES] = tf.shape(img)[:2] if for_testing: tensors_out[Constants.ORIGINAL_SIZES] = tf.shape(original_img)[:2] return tensors_out
def add_mask_summary(self, mask, name): from ReID_net.datasets.Util.Util import smart_shape assert len(smart_shape(mask)) == 2 im = tf.tile(tf.cast(mask, tf.float32)[tf.newaxis, :, :, tf.newaxis], multiples=[1, 1, 1, 3]) summary = tf.summary.image(name, im) self.summaries.append(summary)
def __init__(self, name, inputs, targets, n_classes, n_clusters, tower_setup, use_complete_batch, use_SPN, exclude_zeros_from_loss, original_labels=None, margin=2.0, dropout=0.0, l2=L2_DEFAULT): super(Clustering, self).__init__() self.measures = {} inp, n_features_inp = prepare_collapsed_input_and_dropout( inputs, dropout) with tf.variable_scope(name): W = self.create_weight_variable("W", [n_features_inp, n_clusters], l2, tower_setup) b = self.create_bias_variable("b", [n_clusters], tower_setup) y_pred = tf.matmul(inp, W) + b y_pred = tf.nn.softmax(y_pred, -1, 'softmax') self.outputs = [y_pred] summ = tf.summary.histogram("softmax", y_pred) self.summaries.append(summ) if use_complete_batch: #original_labels = targets curr = y_pred batch_size = smart_shape(curr)[0] curr1 = curr[:, tf.newaxis, :] curr2 = curr[tf.newaxis, :, :] curr1 = tf.transpose(curr1, perm=[1, 0, 2]) curr1_big = tf.tile(curr1, [batch_size, 1, 1]) curr1_big = tf.transpose(curr1_big, perm=[1, 0, 2]) curr2_big = tf.tile(curr2, [batch_size, 1, 1]) boolean_target = tf.cast(tf.ones([batch_size, batch_size]), tf.bool) #### Following extracts one sided + diagonal, but for now we are using both sided as concat is non-symmetric #### In future may want to remove the diagonal # boolean_target = tf.matrix_band_part(boolean_target, -1, 0),tf.bool y_pred0 = tf.boolean_mask(curr1_big, boolean_target) y_pred1 = tf.boolean_mask(curr2_big, boolean_target) if not use_SPN: targets1 = targets[:, tf.newaxis] targets2 = targets[tf.newaxis, :] whole_targets = tf.cast(tf.equal(targets1, targets2), tf.int32) targets = tf.boolean_mask(whole_targets, boolean_target) else: y_pred0 = y_pred[0::2] y_pred1 = y_pred[1::2] targets = targets[::2] if original_labels is not None: cluster_ids = tf.argmax(y_pred, axis=-1) self.measures[Constants.CLUSTER_IDS] = [cluster_ids] self.measures[Constants.ORIGINAL_LABELS] = [original_labels] #y_pred0_stopped = tf.stop_gradient(y_pred0) #y_pred1_stopped = tf.stop_gradient(y_pred1) def kl(x, y): epsilon = tf.constant(1e-8, tf.float32) x += epsilon y += epsilon return tf.reduce_sum(x * tf.log(x / y), axis=-1) kl1 = kl(y_pred0, y_pred1) kl2 = kl(y_pred1, y_pred0) #kl1 = kl(y_pred0_stopped, y_pred1) #kl2 = kl(y_pred1_stopped, y_pred0) def Lh(x): return tf.nn.relu(margin - x) # return tf.nn.softplus(-x) pos_loss = kl1 + kl2 neg_loss = Lh(kl1) + Lh(kl2) loss = tf.where(tf.cast(targets, tf.bool), pos_loss, neg_loss) if exclude_zeros_from_loss: norm_factor = tf.maximum( tf.count_nonzero(loss, dtype=tf.float32), 1.0) loss /= norm_factor loss *= tf.cast(smart_shape(inp)[0], tf.float32) elif use_complete_batch: loss /= tf.cast(smart_shape(inp)[0], tf.float32) self.loss = tf.reduce_sum(loss) self.add_scalar_summary(self.loss, "loss")
def __init__(self, name, inputs, targets, n_classes, n_features, tower_setup, imgs_raw=None, original_labels=None, activation="linear", dropout=0.0, batch_norm=False, batch_norm_decay=BATCH_NORM_DECAY_DEFAULT, l2=L2_DEFAULT, negative_weighting_factor=1): super(FullyConnectedWithTripletLoss, self).__init__() self.measures = {} inp, n_features_inp = prepare_collapsed_input_and_dropout( inputs, dropout) with tf.variable_scope(name): if batch_norm: inp = tf.expand_dims(inp, axis=0) inp = tf.expand_dims(inp, axis=0) inp = self.create_and_apply_batch_norm(inp, n_features_inp, batch_norm_decay, tower_setup) inp = tf.squeeze(inp, axis=[0, 1]) W = self.create_weight_variable("W", [n_features_inp, n_features], l2, tower_setup) b = self.create_bias_variable("b", [n_features], tower_setup) z = tf.matmul(inp, W) + b h = get_activation(activation)(z) self.outputs = [h] if original_labels is not None: self.measures[Constants.EMBEDDING] = [h] self.measures[Constants.ORIGINAL_LABELS] = [original_labels] self.add_scalar_summary(tf.norm(h[0]), "embedding_norm") self.summaries.append(tf.summary.histogram("embedding", h)) size = smart_shape(h)[0] eps = 1e-10 # New print debug example def my_print(x, name): with tf.control_dependencies([ tf.assert_equal( tf.reduce_all(tf.greater(tf.shape(x), 0)), True) ]): if x.dtype in (tf.float32, tf.float64): with tf.control_dependencies([ tf.assert_equal(tf.reduce_all(tf.is_finite(x)), True) ]): return tf.Print(x, [ tf.shape(x), tf.reduce_all(tf.is_finite(x)), x ], name, summarize=200) else: return tf.Print(x, [tf.shape(x), x], name) def get_loss(idx): anchor = h[idx, :] anchor_class = targets[idx] ###### New code ###### class_division = tf.equal(targets, anchor_class) not_self_mask = tf.logical_not( tf.cast(tf.one_hot(idx, depth=size), tf.bool)) positive_output = tf.boolean_mask( h, tf.logical_and(class_division, not_self_mask)) negative_output = tf.boolean_mask( h, tf.logical_not(class_division)) # negative_output = tf.boolean_mask(h, tf.logical_and(tf.logical_not(class_division),not_self_mask)) # positive_output = my_print(positive_output,"positive_output") # negative_output = my_print(negative_output, "negative_output") positive_distances = tf.abs(anchor - positive_output) pos_dis_val = tf.norm(positive_distances + eps, axis=1) hardest_positive, hardest_positive_idx = tf.nn.top_k( pos_dis_val, 1) negative_distances = tf.abs(anchor - negative_output) neg_dis_val = tf.norm(negative_distances + eps, axis=1) minus_neg_dis_val = tf.negative(neg_dis_val) # minus_neg_dis_val = tf.Print(minus_neg_dis_val,[minus_neg_dis_val]) # minus_neg_dis_val = tf.Print(minus_neg_dis_val, [minus_neg_dis_val.shape]) minus_hardest_negative, hardest_negative_idx = tf.nn.top_k( minus_neg_dis_val, 1) hardest_negative = tf.negative(minus_hardest_negative) # minus_hardest_negative, hardest_negative_idx = tf.nn.top_k(minus_neg_dis_val, negative_weighting_factor) # hardest_negative = tf.negative(minus_hardest_negative) # hardest_negative = tf.reduce_sum(hardest_negative,-1) ###### Old code with dynamic partition ###### # class_division = tf.cast(tf.equal(targets, anchor_class), tf.int32) # not_self_mask = tf.logical_not(tf.cast(tf.one_hot(idx, depth=size), tf.bool)) # partitioned_output = tf.dynamic_partition(h, class_division, 2) # positive_output = partitioned_output[1] # negative_output = partitioned_output[0] # class_division = tf.equal(targets, anchor_class) # not_self_mask = tf.logical_not(tf.cast(tf.one_hot(idx, depth=size),tf.bool)) # positive_output = tf.boolean_mask(h, tf.logical_and(class_division, not_self_mask)) # negative_output = tf.boolean_mask(h, tf.logical_not(class_division)) # # # positive_distances = tf.abs(anchor - positive_output) # pos_dis_val = tf.norm(positive_distances+eps, axis=1) # hardest_positive_idx = tf.argmax(pos_dis_val,0) # pos_div_size = smart_shape(positive_output)[0] # pos_divider = tf.one_hot(hardest_positive_idx,pos_div_size,dtype=tf.int32) # hardest_positive = tf.dynamic_partition(positive_distances,pos_divider,2)[1] # hardest_positive_class = tf.gather(targets, hardest_positive_idx) # hardest_positive = tf.norm(hardest_positive+eps, axis=1) # # negative_distances = tf.abs(anchor - negative_output) # neg_dis_val = tf.norm(negative_distances+eps, axis=1) # hardest_negative_idx = tf.argmin(neg_dis_val,0) # neg_div_size = smart_shape(negative_output)[0] # neg_divider = tf.one_hot(hardest_negative_idx,neg_div_size,dtype=tf.int32) # hardest_negative = tf.dynamic_partition(negative_distances,neg_divider,2)[1] # hardest_negative_class = tf.gather(targets,hardest_negative_idx) # hardest_negative = tf.norm(hardest_negative+eps, axis=1) # hardest_positive = my_print(hardest_positive,"hardest_positive") # hardest_negative = my_print(hardest_negative,"hardest_negative") #### Next two lines should be the same loss = tf.nn.softplus(hardest_positive - hardest_negative) # loss = tf.nn.softplus(hardest_positive - negative_weighting_factor*hardest_negative) # loss = tf.log1p(tf.exp(hardest_positive - hardest_negative)) #### Code for using a hard margin rather than a softmargin # margin = 1 # loss = tf.maximum(0., margin + hardest_positive - hardest_negative) anchor_img = tf.zeros([], tf.float32) hard_pos_img = tf.zeros([], tf.float32) hard_neg_img = tf.zeros([], tf.float32) if imgs_raw is not None: positive_images = tf.boolean_mask( imgs_raw, tf.logical_and(class_division, not_self_mask)) negative_images = tf.boolean_mask( imgs_raw, tf.logical_not(class_division)) anchor_img = imgs_raw[idx] hard_pos_img = positive_images[tf.squeeze( hardest_positive_idx)] hard_neg_img = negative_images[tf.squeeze( hardest_negative_idx)] # self.summaries.append(tf.summary.image("anchor_image", imgs_raw[idx])) # positive_images = tf.squeeze(tf.boolean_mask(imgs_raw, tf.logical_and(class_division, not_self_mask))) # negative_images = tf.squeeze(tf.boolean_mask(imgs_raw, tf.logical_not(class_division))) # self.summaries.append(tf.summary.image("hardest_postive_image",positive_images[hardest_positive_idx])) # self.summaries.append(tf.summary.image("hardest_negative_image", negative_images[hardest_negative_idx])) return loss, hardest_positive, hardest_negative, anchor_img, hard_pos_img, hard_neg_img #### Next two lines should be the same loss, hardest_positive, hardest_negative, anchor_imgs, hard_pos_imgs, hard_neg_imgs = \ tf.map_fn(get_loss, tf.range(0, size), dtype=(tf.float32,tf.float32,tf.float32, tf.float32, tf.float32, tf.float32)) # loss, hardest_positive, hardest_negative = [get_loss(idx) for idx in xrange(size)] self.loss = tf.reduce_sum(loss) hardest_positive = tf.reduce_sum(hardest_positive) hardest_negative = tf.reduce_sum(hardest_negative) self.add_scalar_summary(self.loss, "loss") self.add_scalar_summary(hardest_positive, "hardest_positive") self.add_scalar_summary(hardest_negative, "hardest_negative") # tf.summary.image() self.n_features = n_features if imgs_raw is not None: self.summaries.append( tf.summary.image("anchor_image", anchor_imgs)) self.summaries.append( tf.summary.image("hardest_postive_image", hard_pos_imgs)) self.summaries.append( tf.summary.image("hardest_negative_image", hard_neg_imgs))