2
votes

I would like to be able to extract all of the kernel sizes and strides for each of the pooling and convolutional layers in a pycaffe network. This seems to be possible since I see it being used in the drawing function (see line 94 here https://github.com/BVLC/caffe/blob/daf013931b31ed9c95250a89d09b7220badbcefe/python/caffe/draw.py)

Unfortunately when I attempt to use this syntax in this way:

net = caffe.Net(model_def,      # defines the structure of the model
                model_weights,  # contains the trained weights
                caffe.TEST)     # use test mode (e.g., don't perform dropout)
# For each layer
for layer_name, layer in net.layer_dict.iteritems():
    if layer.type == 'Convolution':
          print layer.type
          print layer.convolution_param.kernel_size[0] if len(layer.convolution_param.kernel_size) else 1

I receive the following error:

Convolution
AttributeError: 'Layer' object has no attribute 'convolution_param'

This is strange because I clearly am partially right as layer.type is working correctly since I am able to successfully make the check and only attempt to extract convolutional parameters for a convolutional layer. What is going wrong? When I attempt to see what kind of an object "layer" is I see this:

<caffe._caffe.Layer object at 0x7fe3a2fad050>

So this means it is in fact a PyCaffe layer object. I've looked everywhere for a PyCaffe Layer class reference but haven't come up with anything. Does anyone know of a good reference or how to properly extract kernel and stride information?

1
In draw.py I see a loop over the layer attribute and not layer_dict (line 153: for layer in caffe_net.layer). Have you tried doing it this way? - kostek
Thank you for your suggestion. I attempted the following: for layer in net.layer: print layer.type But received the following error: AttributeError: 'Net' object has no attribute 'layer' - Kantthpel
OK. You cannot access these attributes because the object that you have with caffe.Net() call is not caffe.proto.caffe_pb2.NetParameter that is used in drawp.py. You should probably get this info from blobs. Check this blogpost: christopher5106.github.io/deep/learning/2015/09/04/… - kostek
Hmmm, I see. Unfortunatly I can't get the stride or padding information from blobs as blob dimensions only provide me with the number of outputs and the number of channels. Is there a way to get the caffe.proto.caffe_pb2.NetParameter that is used in draw.py? - Kantthpel
Ah, I see how the net.params['conv'][0] contains the weight parameters which enables the ability to get the kernel size. Now the issue is just how to get convolutional stride and both the kernel size and stride for pooling layers... - Kantthpel

1 Answers

3
votes

Following kostek's guidance, I was able to extract my desired parameters by reading in the prototxt separately as a caffe.proto.caffe_pb2.NetParameter. The code to do so can be found below:

from caffe.proto import caffe_pb2
from google.protobuf import text_format

new_format_model_def = '/models/vgg16-caffe/new_format_VGG_ILSVRC_16_layers_deploy.prototxt'
parsible_net = caffe_pb2.NetParameter()
text_format.Merge(open(new_format_model_def).read(), parsible_net)
print parsible_net.layer

print '[kernel, stride, pad]'
for layer in parsible_net.layer:
    if layer.type == 'Convolution':
          print '======='
          print layer.name
          kernel = layer.convolution_param.kernel_size[0] if len(layer.convolution_param.kernel_size) else 1
          stride = layer.convolution_param.stride[0] if len(layer.convolution_param.stride) else 1
          pad    = layer.convolution_param.pad[0] if len(layer.convolution_param.pad) else 0
          print '['+str(kernel)+str(stride)+str(pad)+']'
    if layer.type == 'Pooling':
          print '======='
          print layer.name
          kernel = layer.pooling_param.kernel_size
          stride = layer.pooling_param.stride
          pad    = layer.pooling_param.pad
          print '['+str(kernel)+str(stride)+str(pad)+']'