Caffe: model definition: write the same layer with a different phase using caffe.NetSpec ()

I want to configure CNN caffe using python using the caffe.NetSpec() interface. Although I saw that we can put the test network in solver.prototxt , I would like to write it in model.prototxt with a different phase. For example, a prototype caffe model implements two levels of data with different phases:

 layer { name: "data" type: "Data" top: "data" top: "label" include { phase: TRAIN } .... } layer { name: "data" type: "Data" top: "data" top: "label" include { phase: TEST } .... } 

How should I do in python to get such an implementation?

+6
source share
5 answers

I assume that you mean how to determine the phase when writing a prototype using caffe.NetSpec ?

 from caffe import layers as L, params as P, to_proto import caffe ns = caffe.NetSpec() ns.data = L.Data(name="data", data_param={'source':'/path/to/lmdb','batch_size':32}, include={'phase':caffe.TEST}) 

If you want to have BOTH trains and test layers in one prototype, then what I usually do is do one ns for a train with all layers and another ns_test with a test version only for duplicates. Then, when you write the actual prototype file:

 with open('model.prototxt', 'w') as W: W.write('%s\n' % ns_test.to_proto()) W.write('%s\n' % ns.to_proto()) 

This way you will have BOTH phases in one prototype. I know a little hacks.

+5
source

I find a useful method.

You can add a key with the name name to the test stage layer and change the ntop and top keys just like this:

 net.data = L.Data(name='data', include=dict(phase=caffe_pb2.Phase.Value('TRAIN')), ntop=1) net.test_data = L.Data(name='data', include=dict(phase=caffe_pb2.Phase.Value('TEST')), top='data', ntop=0) 
+3
source

If your network is similar:

 layer {phase: TRAIN} layer {phase: TEST} layer {} layer {phase: TRAIN} layer {} layer {phase: TEST} layer {} layer {} layer {phase: TEST} 

Create ns train network, Create ns_test test network
Now you basically have two lines str(ns.to_proto()) and str(ns_test.to_proto())
Combine the two using python regex, given the required layer order.

+1
source

I found another way.
I could solve this problem by returning the string proto.
Basically, you can add lines with layers to be replaced (in my case, the first layer).

 def lenet(path_to_lmdb_train, path_to_lmdb_test, batch_size_train, batch_size_test ): n = caffe.NetSpec() n.data, n.label = L.Data(batch_size=batch_size_train, backend=P.Data.LMDB, source=path_to_lmdb_train, include=dict(phase=caffe.TRAIN), transform_param=dict(scale=1./255), ntop=2) first_layer = str(n.to_proto()) n.data, n.label = L.Data(batch_size=batch_size_test, backend=P.Data.LMDB, source=path_to_lmdb_test, include=dict(phase=caffe.TEST), transform_param=dict(scale=1./255), ntop=2) n.conv1 = L.Convolution(n.data, kernel_size=5, num_output=20, weight_filler=dict(type='xavier')) n.pool1 = L.Pooling(n.conv1, kernel_size=2, stride=2, pool=P.Pooling.MAX) n.conv2 = L.Convolution(n.pool1, kernel_size=5, num_output=50, weight_filler=dict(type='xavier')) n.pool2 = L.Pooling(n.conv2, kernel_size=2, stride=2, pool=P.Pooling.MAX) n.ip1 = L.InnerProduct(n.pool2, num_output=500, weight_filler=dict(type='xavier')) n.relu1 = L.ReLU(n.ip1, in_place=True) n.ip2 = L.InnerProduct(n.relu1, num_output=10, weight_filler=dict(type='xavier')) n.loss = L.SoftmaxWithLoss( n.ip2, n.label ) n.accuracy = L.Accuracy( n.ip2, n.label, include=dict(phase=caffe.TEST) ) return first_layer + str(n.to_proto()) 
+1
source

Although several answers have been given, none of them describe a more realistic scenario when you do not even know (at the time of writing the code) the names of your layers. For example, when you assemble a network from smaller blocks, you cannot write:

 n.data = L.Data(#... n.test_data = L.Data(#... 

Since each subsequent block creation will overwrite data and test_data (or batchnorm , which is most likely to be placed in blocks).

Fortunately, you can assign an __getitem__ object via __getitem__ , for example:

 layer_name = 'norm{}'.format(i) #for example n[layer_name + '_train'] = L.Data(#... n[layer_name + '_test'] = L.Data(#... 
+1
source

All Articles