This tutorial will guide through the steps to create a simple custom layer for Caffe using python. By the end of it, there are some examples of custom layers.
###- Why would I want to do that? Usually you would create a custom layer to implement a funcionality that isn't available in Caffe, tuning it for your requirements.
###- What will I need? Python and Caffe instaled and a sample layer template (provided bellow) so you can customize it.
##Layer Template
import caffe
class My_Custom_Layer(caffe.Layer):
def setup(self, bottom, top):
pass
def forward(self, bottom, top):
pass
def reshape(self, bottom, top):
pass
def backward(self, bottom, top):
passSo important things to remember:
- Your custom layer has to inherit from caffe.Layer (so don't forget to import caffe);
- You must define the four following methods: setup, forward, reshape and backward;
- All methods have a top and a bottom parameters, which are the blobs that store the input and the output passed to your layer. You can access it using top[i].data or bottom[i].data, where i is the index of the blob in case you have more than one upper or lower blob.
###- Setup method The Setup method is called once during the lifetime of the execution, when Caffe is instantiating all layers. This is where you will read parameters, instantiate fixed-size buffers.
###- Reshape method Use the reshape method for initialization/setup that depends on the bottom blob (layer input) size. It is called once for each batch.
###- Forward method The Forward method is called for each input batch and is where most of your logic will be.
###- Backward method The Backward method is called during the backward pass of the network. For example, in a convolution-like layer, this would be where you would calculate the gradients. This is optional (a layer can be forward-only).
##Prototxt Template Ok, so now you have your layer designed! This is how you define it in your .prototxt file:
layer {
name: "LayerName"
type: "Python"
top: "TopBlobName"
bottom: "BottomBlobName"
python_param {
module: "My_Custom_Layer_File"
layer: "My_Custom_Layer_Class"
param_str: '{"param1": 1,"param2":True, "param3":"some string"}'
}
include{
phase: TRAIN
}
}
Important remarks:
- type must be Python;
- You must have a python_param dictionary with at least the module and layer parameters;
- module refers to the file where you implemented your layer;
- layer refers to the name of your class;
- You can pass parameters to the layer using param_str (more on accessing them bellow);
- Just like any other layer, you can define in which phase you want it to be active (see the examples to see how you can check the current phase);
##Passing Parameters to the layer You can define the layer parameters in the prototxt by using param_str. Once you've done it, here is an example on how you access these paremeters inside the layer class:
def setup(self, bottom, top):
params = eval(self.param_str)
param1 = params["param1"]
param2 = params.get('param2', False) #I usually use this when fetching a bool
param3 = params["param3"]
#Continue with the setup
# ...