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

前端 未结 5 698
野性不改
野性不改 2020-12-03 23:00

I want to set up a caffe CNN with python, using caffe.NetSpec() interface. Although I saw we can put test net in solver.prototxt, I would like to w

相关标签:
5条回答
  • 2020-12-03 23:19

    If your network is like:

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

    Create a train net ns, Create a test net ns_test
    Now you basically have two strings str(ns.to_proto()) and str(ns_test.to_proto())
    Merge those two using python regex taking into account the required layer order.

    0 讨论(0)
  • 2020-12-03 23:36

    I found another way.
    I could solve this problem returning the proto string.
    Basically, you can add strings with the layers that are going 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())
    
    0 讨论(0)
  • 2020-12-03 23:37

    Although several answers have been given, none covers a more real-world scenario where you don't even know (at the moment of writing code) the names of your layers. For example when you're assembling a network from smaller blocks, you can't write:

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

    Because every next instantiation of the block would overwrite data and test_data (or batchnorm, which is more likely to be put in blocks).

    Fortunately, you can assign to the NetSpec object via __getitem__, like so:

    layer_name = 'norm{}'.format(i) #for example
    n[layer_name + '_train'] = L.Data(#...
    n[layer_name + '_test']  = L.Data(#...
    
    0 讨论(0)
  • 2020-12-03 23:41

    I assume you mean how to define phase when writing a prototxt 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 train and test layers in the same prototxt, what I usually do is making one ns for train with ALL layers and another ns_test with only the test version of the duplicate layers only. Then, when writing the actual prototxt 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'll have BOTH phases in the same prototxt. A bit hacky, I know.

    0 讨论(0)
  • 2020-12-03 23:43

    I find an useful method.

    You can add a key named name for your test phase layer, and modify the keys ntop and top 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)
    
    0 讨论(0)
提交回复
热议问题