11"""Makes .caffemodel files readable for sklearn-theano"""
2+ # Authors: Michael Eickenberg
3+ # Kyle Kastner
4+ # Erfan Noury
5+ # Li Yao
6+ # License: BSD 3 Clause
27from __future__ import print_function
38import os
49import numpy as np
510from collections import OrderedDict
6- import theano
711import theano .tensor as T
812from ...datasets import get_dataset_dir , download
13+ from sklearn_theano .base import Convolution , Relu , LRN , Feedforward , ZeroPad
14+ from sklearn_theano .base import CaffePool
15+ import warnings
916
1017
1118def _get_caffe_dir ():
@@ -23,8 +30,8 @@ def _get_caffe_dir():
2330
2431
2532def _compile_caffe_protobuf (caffe_proto = None ,
26- proto_src_dir = None ,
27- python_out_dir = None ):
33+ proto_src_dir = None ,
34+ python_out_dir = None ):
2835 """Compiles protocol buffer to python_out_dir"""
2936
3037 if caffe_proto is None :
@@ -50,7 +57,7 @@ def _compile_caffe_protobuf(caffe_proto=None,
5057 # "/home/user/caffe/src/caffe/proto/caffe.proto")
5158 else :
5259 caffe_proto = os .path .join (caffe_dir , "src" , "caffe" , "proto" ,
53- "caffe.proto" )
60+ "caffe.proto" )
5461 if not os .path .exists (caffe_proto ):
5562 raise ValueError (
5663 ("Could not find {pf}. Please specify the correct"
@@ -135,6 +142,7 @@ def _blob_to_ndarray(blob):
135142 CONCAT = (('concat_param' , 'concat_dim' ),),
136143 INNER_PRODUCT = ('blobs' ,),
137144 SOFTMAX_LOSS = None ,
145+ SOFTMAX = None ,
138146 DROPOUT = None
139147)
140148
@@ -152,7 +160,7 @@ def _get_property(obj, property_path):
152160
153161
154162def _parse_caffe_model (caffe_model ):
155-
163+ warnings . warn ( "Caching parse for caffemodel, this may take some time" )
156164 caffe_pb2 = _get_caffe_pb2 () # need to remove this dependence on pb here
157165 try :
158166 _layer_types = caffe_pb2 .LayerParameter .LayerType .items ()
@@ -167,11 +175,22 @@ def _parse_caffe_model(caffe_model):
167175 if not hasattr (caffe_model , "layers" ):
168176 # Consider it a filename
169177 caffe_model = _open_caffe_model (caffe_model )
178+
170179 layers_raw = caffe_model .layers
171180 parsed = []
172- for layer in layers_raw :
181+
182+ for n , layer in enumerate (layers_raw ):
173183 # standard properties
174184 ltype = layer_types [layer .type ]
185+ if n == 0 and ltype != 'DATA' :
186+ warnings .warn ("Caffemodel doesn't start with DATA - adding" )
187+ first_layer_descriptor = dict (
188+ type = 'DATA' ,
189+ name = 'data' ,
190+ top_blobs = ('data' ,),
191+ bottom_blobs = tuple ())
192+ parsed .append (first_layer_descriptor )
193+
175194 layer_descriptor = dict (type = ltype ,
176195 name = layer .name ,
177196 top_blobs = tuple (layer .top ),
@@ -192,22 +211,17 @@ def _parse_caffe_model(caffe_model):
192211 return parsed
193212
194213
195- from sklearn_theano .base import (Convolution , Relu , MaxPool , FancyMaxPool ,
196- LRN , Feedforward , ZeroPad ,
197- CaffePool )
198-
199-
200- def parse_caffe_model (caffe_model , float_dtype = 'float32' , verbose = 0 ):
201-
214+ def parse_caffe_model (caffe_model , convert_fc_to_conv = True ,
215+ float_dtype = 'float32' , verbose = 0 ):
202216 if isinstance (caffe_model , str ) or not isinstance (caffe_model , list ):
203217 parsed_caffe_model = _parse_caffe_model (caffe_model )
204218 else :
205219 parsed_caffe_model = caffe_model
206220
207-
208221 layers = OrderedDict ()
209222 inputs = OrderedDict ()
210223 blobs = OrderedDict ()
224+ params = OrderedDict ()
211225
212226 for i , layer in enumerate (parsed_caffe_model ):
213227 layer_type = layer ['type' ]
@@ -267,6 +281,10 @@ def parse_caffe_model(caffe_model, float_dtype='float32', verbose=0):
267281 # ::subsample[1]]
268282
269283 blobs [top_blobs [0 ]] = expression
284+
285+ params [layer_name + '_conv_W' ] = convolution .convolution_filter_
286+ params [layer_name + '_conv_b' ] = convolution .biases_
287+
270288 elif layer_type == "RELU" :
271289 # RELU layers take input from bottom_blobs, set everything
272290 # negative to zero and write the result to top_blobs
@@ -306,7 +324,7 @@ def parse_caffe_model(caffe_model, float_dtype='float32', verbose=0):
306324 # DROPOUT may figure in some networks, but it is only relevant
307325 # at the learning stage, not at the prediction stage.
308326 pass
309- elif layer_type == "SOFTMAX_LOSS" :
327+ elif layer_type in [ "SOFTMAX_LOSS" , "SOFTMAX" ] :
310328 softmax_input = blobs [bottom_blobs [0 ]]
311329 # have to write our own softmax expression, because of shape
312330 # issues
@@ -329,7 +347,7 @@ def parse_caffe_model(caffe_model, float_dtype='float32', verbose=0):
329347 lrn_input = blobs [bottom_blobs [0 ]]
330348 lrn_factor = layer ['lrn_param__alpha' ]
331349 lrn_exponent = layer ['lrn_param__beta' ]
332- axis = {0 :'channels' }[layer ['lrn_param__norm_region' ]]
350+ axis = {0 : 'channels' }[layer ['lrn_param__norm_region' ]]
333351 nsize = layer ['lrn_param__local_size' ]
334352 lrn = LRN (nsize , lrn_factor , lrn_exponent , axis = axis )
335353 lrn ._build_expression (lrn_input )
@@ -346,15 +364,26 @@ def parse_caffe_model(caffe_model, float_dtype='float32', verbose=0):
346364 weights = layer_blobs [0 ].astype (float_dtype )
347365 biases = layer_blobs [1 ].astype (float_dtype ).squeeze ()
348366 fully_connected_input = blobs [bottom_blobs [0 ]]
349- # fc_layer = Feedforward(weights, biases, activation=None)
350- fc_layer = Convolution (weights .transpose ((2 , 3 , 0 , 1 )), biases ,
351- activation = None )
367+ if not convert_fc_to_conv :
368+ if fully_connected_input .ndim == 4 :
369+ m_ , t_ , x_ , y_ = fully_connected_input .shape
370+ fully_connected_input = fully_connected_input .reshape (
371+ (m_ , t_ * x_ * y_ ))
372+ fc_layer = Feedforward (weights .squeeze ().T , biases ,
373+ activation = None )
374+ params [layer_name + '_fc_W' ] = fc_layer .weights
375+ if fc_layer .biases is not None :
376+ params [layer_name + '_fc_b' ] = fc_layer .biases
377+ else :
378+ fc_layer = Convolution (weights .transpose ((2 , 3 , 0 , 1 )), biases ,
379+ activation = None )
380+ params [layer_name + '_conv_W' ] = convolution .convolution_filter_
381+ params [layer_name + '_conv_b' ] = convolution .biases_
382+
352383 fc_layer ._build_expression (fully_connected_input )
353384 layers [layer_name ] = fc_layer
354385 blobs [top_blobs [0 ]] = fc_layer .expression_
355386 else :
356387 raise ValueError ('layer type %s is not known to sklearn-theano'
357388 % layer_type )
358- return layers , blobs , inputs
359-
360-
389+ return layers , blobs , inputs , params
0 commit comments