I need some help to create a CaffeDB for siamese CNN out of a plain directory with images and label-text-file. Best would be a python-way to do it.
The problem is not to walk through the directory and making pairs of images. My problem is more of making a CaffeDB out of those pairs.
So far I only used convert_imageset
to create a CaffeDB out of an image directory.
Thanks for help!
The objective of the Siamese network is to discriminate between the two inputs X1 and X2 . The output of the network is a probability between 0 and 1 , where a value closer to 0 indicates a prediction that the images are dissimilar, and a value closer to 1 that the images are similar.
For same class input pairs, target output is 1 and for different classes input pairs, the output is 0. Remember, both networks have same the parameters and weights. If not, then they are not Siamese.
Why don't you simply make two datasets using good old convert_imagest
?
layer {
name: "data_a"
top: "data_a"
top: "label_a"
type: "Data"
data_param { source: "/path/to/first/data_lmdb" }
...
}
layer {
name: "data_b"
top: "data_b"
top: "label_b"
type: "Data"
data_param { source: "/path/to/second/data_lmdb" }
...
}
As for the loss, since every example has a class label you need to convert label_a
and label_b
into a same_not_same_label
. I suggest you do this "on-the-fly" using a python layer. In the prototxt
add the call to python layer:
layer {
name: "a_b_to_same_not_same_label"
type: "Python"
bottom: "label_a"
bottom: "label_b"
top: "same_not_same_label"
python_param {
# the module name -- usually the filename -- that needs to be in $PYTHONPATH
module: "siamese"
# the layer name -- the class name in the module
layer: "SiameseLabels"
}
propagate_down: false
}
Create siamese.py
(make sure it is in your $PYTHONPATH
). In siamese.py
you should have the layer class:
import sys, os
sys.path.insert(0,os.environ['CAFFE_ROOT'] + '/python')
import caffe
class SiameseLabels(caffe.Layer):
def setup(self, bottom, top):
if len(bottom) != 2:
raise Exception('must have exactly two inputs')
if len(top) != 1:
raise Exception('must have exactly one output')
def reshape(self,bottom,top):
top[0].reshape( *bottom[0].shape )
def forward(self,bottom,top):
top[0].data[...] = (bottom[0].data == bottom[1].data).astype('f4')
def backward(self,top,propagate_down,bottom):
# no back prop
pass
Make sure you shuffle the examples in the two sets in a different manner, so you get non-trivial pairs. Moreover, if you construct the first and second data sets with different number of examples, then you will see different pairs at each epoch ;)
Make sure you construct the network to share the weights of the duplicated layers, see this tutorial for more information.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With