<p>Finding triplets to train a Siamese neural network with the triplet loss function can be done in several ways. The original <a href="https://arxiv.org/abs/1503.03832" rel="nofollow noreferrer">FaceNet</a> paper describes the importance of hard triplets (hard positives, <em>positives</em> such that <code>argmax||f(anchor)-f(positive)||^2</code> and hard negatives, <em>negatives</em> such that <code>argmin||f(anchor)-f(negative)||^2</code> where f is the embedding from the neural network. </p>

<p>However, in one of my Siamese networks, I selected (anchor,positive,negative) triplets randomly and it turns out to have a good classification accuracy. So you could try random triplet selection first, as hard-triplet selection is generally computationally expensive and requires a CPU cluster.</p>

<p>I hope you have labelled all the images in the dataset and label should reflect which person that particular image refers to. For an example, if you have 5 images of person A, the labels should look like <code>(A_1.jpg, A_2.jpg,...A_5.jpg)</code> or you should have a separate directory for each person. You could select an image from one directory randomly as the anchor, select an image from the same directory as the positive and an image from a different directory as the negative. Bundle this images in triplet format <code>(anchor,positive,negative)</code> and repeat the process to create a batch. And there you have a training batch of images.</p>

<p>I just covered the basic procedure of doing it, however, if you're looking for an example code, <a href="https://towardsdatascience.com/one-shot-learning-with-siamese-networks-using-keras-17f34e75bb3d" rel="nofollow noreferrer">this</a> tutorial may help you to create batches of triplets to a train the network.</p>
How to create anchor-positive and anchor-negative pairs from dataset for training the model?
<p>I am trying to apply one-shot learning for face-recognition.
I have several pictures of different people in my dataset directory and want to train my model but the problem is I can't figure out how to provide anchor-positive and anchor-negative pairs from directory of dataset.</p>

<p>I have build a custom convNet model and defined triplet-loss(as described in deeplearning.ai course). </p>

<p>My model</p>

<pre class="lang-py prettyprint-override"><code>model = models.Sequential()

model.add(layers.Conv2D(16, (3,3), (3,3), activation='relu', input_shape=(384, 384, 1)))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.BatchNormalization())

for t in range(2):
  model.add(layers.Conv2D(32, (1,1), (1,1), activation='relu'))
  model.add(layers.Conv2D(32, (3,3), (1,1), padding='same', activation='relu'))
  model.add(layers.Conv2D(64, (1,1), (1,1), activation='relu'))
  model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2,2)))

for t in range(3):
  model.add(layers.Conv2D(64, (1,1), (1,1), activation='relu'))
  model.add(layers.Conv2D(64, (3,3), (1,1), padding='same', activation='relu'))
  model.add(layers.Conv2D(128, (1,1), (1,1), activation='relu'))
  model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2,2)))

for t in range(4):
  model.add(layers.Conv2D(128, (1,1), (1,1), activation='relu'))
  model.add(layers.Conv2D(128, (3,3), (1,1), padding='same', activation='relu'))
  model.add(layers.Conv2D(256, (1,1), (1,1), activation='relu'))
  model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2,2)))

for t in range(3):
  model.add(layers.Conv2D(256, (1,1), (1,1), activation='relu'))
  model.add(layers.Conv2D(256, (3,3), (1,1), padding='same', activation='relu'))
  model.add(layers.Conv2D(512, (1,1), (1,1), activation='relu'))
  model.add(layers.BatchNormalization())
model.add(layers.AveragePooling2D((4,4)))

model.add(layers.Flatten())
model.add(layers.Dense(128))

model.add(layers.Lambda(lambda x: backend.l2_normalize(x,axis=1)))
</code></pre>

<p>Triplet_loss</p>

<pre class="lang-py prettyprint-override"><code>def triplet_loss(y_true, y_pred, alpha = 0.3):
    """
    Implementation of the triplet loss as defined by formula (3)

    Arguments:
    y_pred -- python list containing three objects:
            anchor -- the encodings for the anchor images, of shape (None, 128)
            positive -- the encodings for the positive images, of shape (None, 128)
            negative -- the encodings for the negative images, of shape (None, 128)

    Returns:
    loss -- real number, value of the loss
    """

    anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2]

    # Step 1: Compute the (encoding) distance between the anchor and the positive, you will need to sum over axis=-1
    pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), axis=-1)
    # Step 2: Compute the (encoding) distance between the anchor and the negative, you will need to sum over axis=-1
    neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, negative)), axis=-1)
    # Step 3: subtract the two previous distances and add alpha.
    basic_loss = tf.add(tf.subtract(pos_dist, neg_dist), alpha)
    # Step 4: Take the maximum of basic_loss and 0.0. Sum over the training examples.
    loss = tf.reduce_sum(tf.maximum(basic_loss, 0.0))

    return loss
</code></pre>

<p>Model Compilation</p>

<pre class="lang-py prettyprint-override"><code>model.compile(optimizer='adam',loss='triplet_loss',metrics=['accuracy'])
</code></pre>

<p>Please help me in making anchor-positive and anchor-negative pairs for training. I don't have any idea how to handle dataset directory in this regard!</p>