def build(self, inputs, targets): """ Args: inputs (torch.Tensor): feature matrix with shape (batch_size, feat_dim). targets (torch.LongTensor): ground truth labels with shape (num_classes). """ n = inputs.shape[0] dist = math.reduce_sum(math.pow( inputs, flow.constant_like(inputs, 2, dtype=flow.float32)), axis=1) shape_tensor = flow.constant(value=0.0, dtype=flow.float32, shape=(n, n)) dist = flow.broadcast_like(dist, like=shape_tensor, broadcast_axes=[1]) dist = math.add( dist, flow.transpose(dist, perm=(1, 0), batch_axis_non_change=True)) temp1 = math.multiply( -2, flow.matmul( inputs, flow.transpose(inputs, perm=(1, 0), batch_axis_non_change=True))) dist = math.add(dist, temp1) dist = math.sqrt(flow.clamp(dist, min_value=1e-12)) mask = math.equal( flow.broadcast_like(targets, like=shape_tensor, broadcast_axes=[1]), flow.transpose(flow.broadcast_like(targets, like=shape_tensor, broadcast_axes=[1]), perm=(1, 0), batch_axis_non_change=True)) mask_rev = math.not_equal( flow.broadcast_like(targets, like=shape_tensor, broadcast_axes=[1]), flow.transpose(flow.broadcast_like(targets, like=shape_tensor, broadcast_axes=[1]), perm=(1, 0), batch_axis_non_change=True)) dist_ap, dist_an = [], [] for i in range(n): temp_dist = flow.slice_v2(dist, [(i, i + 1, 1)]) temp_mask = flow.slice_v2(mask, [(i, i + 1, 1)]) temp_mask_rev = flow.slice_v2(mask_rev, [(i, i + 1, 1)]) dist_ap.append( math.reduce_max( flow.gather_nd(temp_dist, flow.where(temp_mask)))) dist_an.append( math.reduce_min( flow.gather_nd(temp_dist, flow.where(temp_mask_rev)))) dist_ap = flow.concat(dist_ap, 0) dist_an = flow.concat(dist_an, 0) y = flow.ones_like(dist_an) # return dist_an, dist_ap, y return self._MarginRankingLoss(dist_an, dist_ap, y)
def slice(input_blob: oft.Numpy.Placeholder(shape=(2, 5, 4), dtype=flow.float)): x = flow.get_variable( shape=(2, 5, 4), dtype=flow.float, initializer=flow.random_uniform_initializer(0, 2), name="variable", ) x = flow.identity(x) flow.watch_diff(x, slice_grad_cb) y = flow.slice_v2(x, [(None, None, None), (2, -2, None)]) flow.losses.add_loss(y) return y
def slice(input_blob: oft.Numpy.Placeholder(shape=(2, 5, 4), dtype=flow.float)): x = flow.get_variable( shape=(2, 5, 4), dtype=flow.float, initializer=flow.random_uniform_initializer(0, 2), name="variable", ) x = flow.identity(x) flow.watch_diff(x, slice_grad_cb) y = flow.slice_v2(x, [(None, None, None), (2, -2, None)]) flow.optimizer.SGD(flow.optimizer.PiecewiseConstantScheduler([], [1e-3]), momentum=0).minimize(y) return y
def slice_with_grad_job(x: otp.Numpy.Placeholder( shape=input_shape, dtype=dtype)) -> otp.Numpy: var = flow.get_variable( shape=input_shape, dtype=dtype, initializer=flow.constant_initializer(0.0), name="variable", ) x = x + var if callable(watch_diff_cb): flow.watch_diff(x, watch_diff_cb) y = flow.slice_v2(x, slice_tup_list, name="SliceWithGrad") flow.optimizer.SGD(flow.optimizer.PiecewiseConstantScheduler([], [1e-3]), momentum=0).minimize(y) return y
def do_slice(x, indices): outputs = [] for slice_tup_list in indices: output = flow.slice_v2(x, slice_tup_list) outputs.append(output) return outputs
def _do_slice(input, args, name=None): outputs = [] for slice_tup_list in args: output = flow.slice_v2(input, slice_tup_list, name) outputs.append(output) return outputs
def forward(self, inputs, targets): n = inputs.shape[0] # Compute pairwise distance, replace by the official when merged tempname = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S.%f') shape_tensor = flow.constant(value=0.0, dtype=flow.float32, shape=(n, n)) if self.distance == 'euclidean': blob_2 = flow.get_variable( "blob_2_" + tempname, shape=inputs.shape, initializer=flow.constant_initializer(2), dtype=inputs.dtype) dist = flow.math.pow(inputs, blob_2) dist = flow.math.reduce_sum(dist, axis=1, keepdims=True) dist = flow.broadcast_like(dist, shape_tensor) tempdist = flow.transpose(dist) dist = dist + tempdist inputs_t = flow.transpose(inputs) dist = addmm(dist, inputs, inputs_t, beta=1, alpha=-2) dist = flow.clamp(dist, min_value=1e-12) dist = flow.math.sqrt(dist) elif self.distance == 'cosine': #fnorm=flow.math.l2_normalize(inputs, axis=1) fnorm = flow.math.reduce_mean(flow.math.divide( inputs, flow.math.l2_normalize(inputs, axis=1)), axis=1, keepdims=True) expand_fnorm = flow.broadcast_like(fnorm, like=inputs, broadcast_axes=[1]) l2norm = flow.math.divide(inputs, expand_fnorm) l2norm_t = flow.transpose(l2norm, perm=(1, 0)) dist = flow.math.negative(flow.matmul(l2norm, l2norm_t)) # For each anchor, find the hardest positive and negative mask = math.equal( flow.broadcast_like(targets, like=shape_tensor, broadcast_axes=[1]), flow.transpose(flow.broadcast_like(targets, like=shape_tensor, broadcast_axes=[1]), perm=(1, 0), batch_axis_non_change=True)) mask_rev = math.not_equal( flow.broadcast_like(targets, like=shape_tensor, broadcast_axes=[1]), flow.transpose(flow.broadcast_like(targets, like=shape_tensor, broadcast_axes=[1]), perm=(1, 0), batch_axis_non_change=True)) dist_ap, dist_an = [], [] for i in range(n): temp_dist = flow.slice_v2(dist, [(i, i + 1, 1)]) temp_mask = flow.slice_v2(mask, [(i, i + 1, 1)]) temp_mask_rev = flow.slice_v2(mask_rev, [(i, i + 1, 1)]) temp_dist_ap = flow.expand_dims( math.reduce_max( flow.gather_nd(temp_dist, flow.where(temp_mask))), 0) temp_dist_an = flow.expand_dims( math.reduce_min( flow.gather_nd(temp_dist, flow.where(temp_mask_rev))), 0) dist_ap.append(temp_dist_ap) dist_an.append(temp_dist_an) dist_ap = flow.concat(dist_ap, 0) dist_an = flow.concat(dist_an, 0) y = flow.ones_like(dist_an) return self._MarginRankingLoss(dist_an, dist_ap, y)