Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to train Siamese network in Keras?

I have a pandas dataframe containing filenames of positive and negative examples as below

img1        img2      y
001.jpg     002.jpg   1 
003.jpg     004.jpg   0 
003.jpg     002.jpg   1  

I want to train my Siamese network using Keras ImageDataGenerator and flow_from_dataframe. How do I set up my training so that the code inputs 2 images with 1 label simultaneously.

Below is the code for my model

def siamese_model(input_shape) :
    left = Input(input_shape)
    right = Input(input_shape)
    model = Sequential()
    model.add(Conv2D(32, (3,3), activation='relu', input_shape=input_shape))
    model.add(BatchNormalization())
    model.add(Conv2D(64, (3,3), activation='relu'))
    model.add(BatchNormalization())
    model.add(Conv2D(128, (3,3), activation='relu'))
    model.add(BatchNormalization())
    model.add(Conv2D(256, (3,3), activation='relu')
    model.add(BatchNormalization())
    model.add(Conv2D(256, (3,3), activation='relu')
    model.add(MaxPooling2D())
    model.add(BatchNormalization())
    model.add(Flatten())
    model.add(Dense(512, activation='sigmoid'))

    left_encoded = model(left)
    right_encoded = model(right)
    L1_layer = Lambda(lambda tensors:K.abs(tensors[0] - tensors[1]))
    L1_distance = L1_layer([left_encoded, right_encoded])
    prediction = Dense(1,activation='sigmoid')(L1_distance)
    siamese_net = Model(inputs=[left,right],outputs=prediction)
    return siamese_net

model = siamese_model((224,224,3))
model.compile(loss="binary_crossentropy",optimizer="adam", metrics=['accuracy'])

datagen_left = ImageDataGenerator(rotation_range=10,
                    width_shift_range=0.2,
                    height_shift_range=0.2,
                    shear_range=0.2,
                    zoom_range=0.2,
                    vertical_flip = True)
datagen_right = ImageDataGenerator(rotation_range=10,
                    width_shift_range=0.2,
                    height_shift_range=0.2,
                    shear_range=0.2,
                    zoom_range=0.2,
                    vertical_flip = True)

like image 654
sougata saha Avatar asked Feb 11 '19 18:02

sougata saha


1 Answers

Join the generators in a custom generator.

Make one of them output the desired labels, discard the label of the other.

class DoubleGenerator(Sequence):
    def __init__(self, gen1, gen2):
       self.gen1 = gen1
       self.gen2 = gen2

    def __len__(self):
       return len(self.gen1)

    def __getitem__(self, i):
       x1,y = self.gen1[i]
       x2,y2 = self.gen2[i]
       return (x1,x2), y

Use it:

double_gen = DoubleGenerator(datagen_left.flow_from_directory(...),
                             datagen_right.flow_from_directory(...))
like image 130
Daniel Möller Avatar answered Sep 19 '22 02:09

Daniel Möller