, Xp_train = build_positive_pairs(range(0, num_classes))

# Gather the ids of all network traces that are used for training
# This just union of two sets set(A) | set(B)
all_traces_train_idx = list(set(Xa_train) | set(Xp_train))
print "X_train Anchor: ", Xa_train.shape
print "X_train Positive: ", Xp_train.shape

# Build a loss which doesn't take into account the y_true, as# Build
# we'll be passing only 0
def identity_loss(y_true, y_pred):
    return K.mean(y_pred - 0 * y_true)

# The real loss is here
def cosine_triplet_loss(X):
    _alpha = alpha_value
    positive_sim, negative_sim = X

    losses = K.maximum(0.0, negative_sim - positive_sim + _alpha)
    return K.mean(losses)

# ------------------- Hard Triplet Mining -----------
# Naive way to compute all similarities between all network traces.

def build_similarities(conv, all_imgs):
    embs = conv.predict(all_imgs)
    embs = embs / np.linalg.norm(embs, axis=-1, keepdims=True)
    all_sims = np.dot(embs, embs.T)
    return all_sims

def intersect(a, b):
    return list(set(a) & set(b))

def build_negatives(anc_idxs, pos_idxs, similarities, neg_imgs_idx, num_retries=50):
    # If no similarities were computed, return a random negative
    if similarities is None:
        return random.sample(neg_imgs_idx,len(anc_idxs))
    final_neg = []
    # for each positive pair
    for (anc_idx, pos_idx) in zip(anc_idxs, pos_idxs):
        anchor_class = id_to_classid[anc_idx]
        #positive similarity
        sim = similarities[anc_idx, pos_idx]
        # find all negatives which are semi(hard)
        possible_ids = np.where((similarities[anc_idx] + alpha_value) > sim)[0]
        possible_ids = intersect(neg_imgs_idx, possible_ids)
        appended = False
        for iteration in range(num_retries):
            if len(possible_ids) == 0:
                break
            idx_neg = random.choice(possible_ids)
            if id_to_classid[idx_neg]!= anchor_class:
                final_neg.append(idx_neg)
                appended = True
                break
        if not appended:
            final_neg.append(random.choice(neg_imgs_idx))
    return final_neg


class SemiHardTripletGenerator():
    def __init__(self, Xa_train, Xp_train, batch_size, all_traces, neg_traces_idx, conv):
        self.batch_size = batch_size

        self.traces = all_traces
        self.Xa = Xa_train
        self.Xp = Xp_train
        self.cur_train_index = 0
        self.num_samples = Xa_train.shape[0]
        self.neg_traces_idx = neg_traces_idx
        self.all_anchors = list(set(Xa_train))
        self.mapping_pos = {v: k for k, v in enumerate(self.all_anchors)}
        self.mapping_neg = {k: v for k, v in enumerate(self.neg_traces_idx)}
        if conv:
            self.similarities = build_similarities(conv, self.traces)
        else:
            self.similarities = None

    def next_train(self):
        while 1:
            self.cur_train_index += self.batch_size
            if self.cur_train_index >= self.num_samples:
                self.cur_train_index = 0

            # fill one batch
            traces_a = self.Xa[self.cur_train_index:self.cur_train_index + self.batch_size]
            traces_p = self.Xp[self.cur_train_index:self.cur_train_index + self.batch_size]
            traces_n = build_negatives(traces_a, traces_p, self.similarities, self.neg_traces_idx)

            yield ([self.traces[traces_a],
                    self.traces[traces_p],
                    self.traces[traces_n]],
                   np.zeros(shape=(traces_a.shape[0]))
                   )

# Training the Triplet Model
from DF_model import DF
shared_conv2 = DF(input_shape=(5000,1), emb_size=emb_size)

anchor = Input((5000, 1), name='anchor')
positive = Input((5000, 1), name='positive')
negative = Input((5000, 1), name='negative')

a = shared_conv2(anchor)
p = shared_conv2(positive)
n = shared_conv2(negative)

# The Dot layer in Keras now supports built-in Cosine similarity using the normalize = True parameter.
# From the Keras Docs:
# keras.layers.Dot(axes, normalize=True)
# normalize: Whether to L2-normalize samples along the dot product axis before taking the dot product.
#  If set to True, then the output of the dot product is the cosine proximity between the two samples.
pos_sim = Dot(axes=-1, normalize=True)([a,p])
neg_sim = Dot(axes=-1, normalize=True)([a,n])

# customized loss
loss = Lambda(cosine_triplet_loss,
              output_shape=(1,))(
             [pos_sim,neg_sim])

model_triplet = Model(
    inputs=[anchor, positive, negative],
    outputs=loss)
print model_triplet.summary()

opt = optimizers.SGD(lr=0.001, decay=1e-6, momentum=0.9, nesterov=True)

model_triplet.compile(loss=identity_loss, optimizer=opt)

batch_size = batch_size_value
# At first epoch we don't generate hard triplets
gen_hard = SemiHardTripletGenerator(Xa_train, Xp_train, batch_size, all_traces, all_traces_train_idx, None)
nb_epochs = number_epoch
csv_logger = CSVLogger('log/Training_Log_%s.csv'%description, append=True, separator=';')
for epoch in range(nb_epochs):
    print("built new hard generator for epoch "+str(epoch))
    model_triplet.fit_generator(generator=gen_hard.next_train(),
                    steps_per_epoch=Xa_train.shape[0] // batch_size,
                    epochs=1, verbose=1, callbacks=[csv_logger])
    gen_hard = SemiHardTripletGenerator(Xa_train, Xp_train, batch_size, all_traces, all_traces_train_idx, shared_conv2)
    #For no semi-hard_triplet
    #gen_hard = HardTripletGenerator(Xa_train, Xp_train, batch_size, all_traces, all_traces_train_idx, None)
shared_conv2.save('trained_model/%s.h5'%description)
Stampin’ Up! is donating $2 from the sale of each I (heart) hearts stamp set from the Occasions minicatalog. Contact me or purchase at www.kwstamps.stampinup.net for the lowest shipping price.
Not only that, but SU purchased supplies for 5000 hygiene kits and staff packed them in our distribution center in Riverton, Utah. Here is our President, Dale Filmore. Our CEO Shelli missed the packing because they got it done so quickly!I’m not going to lie to you, it’s difficult to write for a sports section when a large amount of sports-related things have been put on hold indefinitely. There are fewer events to write about, fewer playing athletes to interview, and we can only write so many articles about policy changes and season cancellations. Any “normal” organization had to be tossed out the window, and it’