11import numpy as np
2+ import pickle
23import tensorflow as tf
34
5+ from tensorflow .python .framework import ops
6+ from tensorflow .python .ops import math_ops
7+ from tensorflow .python .ops import nn_ops
8+
49DEFAULT_PADDING = 'SAME'
510
611
@@ -41,9 +46,9 @@ def __init__(self, inputs, trainable=True):
4146 # If true, the resulting variables are set as trainable
4247 self .trainable = trainable
4348 # Switch variable for dropout
44- self .use_dropout = tf .placeholder_with_default (tf .constant (1.0 ),
45- shape = [],
46- name = 'use_dropout' )
49+ self .use_dropout = tf .compat . v1 . placeholder_with_default (tf .constant (1.0 ),
50+ shape = [],
51+ name = 'use_dropout' )
4752 self .setup ()
4853
4954 def setup (self ):
@@ -56,16 +61,26 @@ def load(self, data_path, session, ignore_missing=False):
5661 session: The current TensorFlow session
5762 ignore_missing: If true, serialized weights for missing layers are ignored.
5863 '''
59- data_dict = np .load (data_path ).item ()
64+ with open (data_path , 'rb' ) as handle :
65+ data_dict = pickle .load (handle )
6066 for op_name in data_dict :
61- with tf .variable_scope (op_name , reuse = True ):
62- for param_name , data in data_dict [op_name ].items ():
67+ with tf .compat .v1 .variable_scope (op_name , reuse = True ):
68+ # TODO not sure why name mapping does not work
69+ if 'relu' in op_name :
6370 try :
64- var = tf .get_variable (param_name )
65- session .run (var .assign (data ))
71+ var = tf .compat . v1 . get_variable (op_name )
72+ session .run (var .assign (data_dict [ op_name ][ 0 ] ))
6673 except ValueError :
6774 if not ignore_missing :
6875 raise
76+ else :
77+ for param_name , data in data_dict [op_name ].iteritems ():
78+ try :
79+ var = tf .compat .v1 .get_variable (param_name )
80+ session .run (var .assign (data ))
81+ except ValueError :
82+ if not ignore_missing :
83+ raise
6984
7085 def feed (self , * args ):
7186 '''Set the input(s) for the next operation by replacing the terminal nodes.
@@ -74,7 +89,7 @@ def feed(self, *args):
7489 assert len (args ) != 0
7590 self .terminals = []
7691 for fed_layer in args :
77- if isinstance (fed_layer , str ):
92+ if isinstance (fed_layer , basestring ):
7893 try :
7994 fed_layer = self .layers [fed_layer ]
8095 except KeyError :
@@ -95,42 +110,62 @@ def get_unique_name(self, prefix):
95110
96111 def make_var (self , name , shape ):
97112 '''Creates a new TensorFlow variable.'''
98- return tf .get_variable (name , shape , trainable = self .trainable )
113+ return tf .compat . v1 . get_variable (name , shape , trainable = self .trainable )
99114
100115 def validate_padding (self , padding ):
101116 '''Verifies that the padding is one of the supported ones.'''
102117 assert padding in ('SAME' , 'VALID' )
103118
119+ def prelu_layer (self , x , weights , biases , name = None ):
120+ """Computes PRelu(x * weight + biases).
121+ Args:
122+ x: a 2D tensor. Dimensions typically: batch, in_units
123+ weights: a 2D tensor. Dimensions typically: in_units, out_units
124+ biases: a 1D tensor. Dimensions: out_units
125+ name: A name for the operation (optional). If not specified
126+ "nn_prelu_layer" is used.
127+ Returns:
128+ A 2-D Tensor computing prelu(matmul(x, weights) + biases).
129+ Dimensions typically: batch, out_units.
130+ """
131+ with ops .name_scope (name , "prelu_layer" , [x , weights , biases ]) as name :
132+ x = ops .convert_to_tensor (x , name = "x" )
133+ weights = ops .convert_to_tensor (weights , name = "weights" )
134+ biases = ops .convert_to_tensor (biases , name = "biases" )
135+ xw_plus_b = nn_ops .bias_add (math_ops .matmul (x , weights ), biases )
136+ return self .parametric_relu (xw_plus_b , name = name )
137+
104138 @layer
105139 def conv (self ,
106- input ,
140+ inputs ,
107141 k_h ,
108142 k_w ,
109143 c_o ,
110144 s_h ,
111145 s_w ,
112146 name ,
113147 relu = True ,
148+ prelu = False ,
114149 padding = DEFAULT_PADDING ,
115150 group = 1 ,
116151 biased = True ):
117152 # Verify that the padding is acceptable
118153 self .validate_padding (padding )
119154 # Get the number of channels in the input
120- c_i = input .get_shape ()[- 1 ]
155+ c_i = inputs .get_shape ()[- 1 ]
121156 # Verify that the grouping parameter is valid
122157 assert c_i % group == 0
123158 assert c_o % group == 0
124159 # Convolution for a given input and kernel
125160 convolve = lambda i , k : tf .nn .conv2d (i , k , [1 , s_h , s_w , 1 ], padding = padding )
126- with tf .variable_scope (name ) as scope :
127- kernel = self .make_var ('weights' , shape = [k_h , k_w , int ( c_i ) / group , c_o ])
161+ with tf .compat . v1 . variable_scope (name ) as scope :
162+ kernel = self .make_var ('weights' , shape = [k_h , k_w , c_i / group , c_o ])
128163 if group == 1 :
129164 # This is the common-case. Convolve the input without any further complications.
130- output = convolve (input , kernel )
165+ output = convolve (inputs , kernel )
131166 else :
132167 # Split the input into groups and then convolve each of them independently
133- input_groups = tf .split (3 , group , input )
168+ input_groups = tf .split (3 , group , inputs )
134169 kernel_groups = tf .split (3 , group , kernel )
135170 output_groups = [convolve (i , k ) for i , k in zip (input_groups , kernel_groups )]
136171 # Concatenate the groups
@@ -142,33 +177,65 @@ def conv(self,
142177 if relu :
143178 # ReLU non-linearity
144179 output = tf .nn .relu (output , name = scope .name )
180+ elif prelu :
181+ output = self .parametric_relu (output , scope = scope )
145182 return output
146183
147184 @layer
148- def relu (self , input , name ):
149- return tf .nn .relu (input , name = name )
185+ def relu (self , x , name ):
186+ return tf .nn .relu (x , name = name )
187+
188+ @layer
189+ def prelu (self , x , name ):
190+ return self .parametric_relu (x , name = name )
191+
192+ def parametric_relu (self , x , scope = None , name = "PReLU" ):
193+ """ PReLU.
194+
195+ Parametric Rectified Linear Unit. Base on:
196+ https://github.com/tflearn/tflearn/blob/5c23566de6e614a36252a5828d107d001a0d0482/tflearn/activations.py#L188
197+
198+ Arguments:
199+ x: A `Tensor` with type `float`, `double`, `int32`, `int64`, `uint8`,
200+ `int16`, or `int8`.
201+ name: A name for this activation op (optional).
202+ Returns:
203+ A `Tensor` with the same type as `x`.
204+ """
205+ # tf.zeros(x.shape, dtype=dtype)
206+ with tf .compat .v1 .variable_scope (scope , default_name = name , values = [x ]) as scope :
207+ # W_init=tf.constant_initializer(0.0)
208+ # alphas = tf.compat.v1.get_variable(name="alphas", shape=x.get_shape()[-1],
209+ # initializer=W_init,
210+ # dtype=tf.float32)
211+ alphas = self .make_var (name , x .get_shape ()[- 1 ])
212+ x = tf .nn .relu (x ) + tf .multiply (alphas , (x - tf .abs (x ))) * 0.5
213+
214+ x .scope = scope
215+ x .alphas = alphas
216+ return x
150217
151218 @layer
152- def max_pool (self , input , k_h , k_w , s_h , s_w , name , padding = DEFAULT_PADDING ):
219+ def max_pool (self , x , k_h , k_w , s_h , s_w , name , padding = DEFAULT_PADDING ):
153220 self .validate_padding (padding )
154- return tf .nn .max_pool ( input ,
155- ksize = [1 , k_h , k_w , 1 ],
156- strides = [1 , s_h , s_w , 1 ],
157- padding = padding ,
158- name = name )
221+ return tf .nn .max_pool2d ( x ,
222+ ksize = [1 , k_h , k_w , 1 ],
223+ strides = [1 , s_h , s_w , 1 ],
224+ padding = padding ,
225+ name = name )
159226
160227 @layer
161- def avg_pool (self , input , k_h , k_w , s_h , s_w , name , padding = DEFAULT_PADDING ):
228+ def avg_pool (self , x , k_h , k_w , s_h , s_w , name , padding = DEFAULT_PADDING ):
162229 self .validate_padding (padding )
163- return tf .nn .avg_pool (input ,
230+ return tf .nn .avg_pool (x ,
164231 ksize = [1 , k_h , k_w , 1 ],
165232 strides = [1 , s_h , s_w , 1 ],
166233 padding = padding ,
167234 name = name )
168235
169236 @layer
170- def lrn (self , input , radius , alpha , beta , name , bias = 1.0 ):
171- return tf .nn .local_response_normalization (input ,
237+ def lrn (self , x , radius , alpha , beta , name , bias = 1.0 ):
238+ return tf .nn .local_response_normalization (x ,
172239 depth_radius = radius ,
173240 alpha = alpha ,
174241 beta = beta ,
@@ -184,48 +251,53 @@ def add(self, inputs, name):
184251 return tf .add_n (inputs , name = name )
185252
186253 @layer
187- def fc (self , input , num_out , name , relu = True ):
188- with tf .variable_scope (name ) as scope :
189- input_shape = input .get_shape ()
254+ def fc (self , x , num_out , name , relu = True , prelu = False ):
255+ with tf .compat . v1 . variable_scope (name ) as scope :
256+ input_shape = x .get_shape ()
190257 if input_shape .ndims == 4 :
191258 # The input is spatial. Vectorize it first.
192259 dim = 1
193260 for d in input_shape [1 :].as_list ():
194261 dim *= d
195- feed_in = tf .reshape (input , [- 1 , dim ])
262+ feed_in = tf .reshape (x , [- 1 , dim ])
196263 else :
197- feed_in , dim = (input , input_shape [- 1 ].value )
264+ feed_in , dim = (x , input_shape [- 1 ].value )
198265 weights = self .make_var ('weights' , shape = [dim , num_out ])
199266 biases = self .make_var ('biases' , [num_out ])
200- op = tf .nn .relu_layer if relu else tf .nn .xw_plus_b
267+ if relu :
268+ op = tf .nn .relu_layer
269+ elif prelu :
270+ op = self .prelu_layer
271+ else :
272+ op = tf .compat .v1 .nn .xw_plus_b
201273 fc = op (feed_in , weights , biases , name = scope .name )
202274 return fc
203275
204276 @layer
205- def softmax (self , input , name ):
206- input_shape = [ v .value for v in input .get_shape ()]
277+ def softmax (self , x , name ):
278+ input_shape = map ( lambda v : v .value , x .get_shape ())
207279 if len (input_shape ) > 2 :
208280 # For certain models (like NiN), the singleton spatial dimensions
209281 # need to be explicitly squeezed, since they're not broadcast-able
210282 # in TensorFlow's NHWC ordering (unlike Caffe's NCHW).
211283 if input_shape [1 ] == 1 and input_shape [2 ] == 1 :
212- input = tf .squeeze (input , squeeze_dims = [1 , 2 ])
284+ x = tf .squeeze (x , squeeze_dims = [1 , 2 ])
213285 else :
214286 raise ValueError ('Rank 2 tensor input expected for softmax!' )
215- return tf .nn .softmax (input , name = name )
287+ return tf .nn .softmax (x , name = name )
216288
217289 @layer
218- def batch_normalization (self , input , name , scale_offset = True , relu = False ):
290+ def batch_normalization (self , x , name , scale_offset = True , relu = False , prelu = False ):
219291 # NOTE: Currently, only inference is supported
220- with tf .variable_scope (name ) as scope :
221- shape = [input .get_shape ()[- 1 ]]
292+ with tf .compat . v1 . variable_scope (name ) as scope :
293+ shape = [x .get_shape ()[- 1 ]]
222294 if scale_offset :
223295 scale = self .make_var ('scale' , shape = shape )
224296 offset = self .make_var ('offset' , shape = shape )
225297 else :
226298 scale , offset = (None , None )
227299 output = tf .nn .batch_normalization (
228- input ,
300+ x ,
229301 mean = self .make_var ('mean' , shape = shape ),
230302 variance = self .make_var ('variance' , shape = shape ),
231303 offset = offset ,
@@ -236,9 +308,11 @@ def batch_normalization(self, input, name, scale_offset=True, relu=False):
236308 name = name )
237309 if relu :
238310 output = tf .nn .relu (output )
311+ elif prelu :
312+ output = self .parametric_relu (output , name = scope .name )
239313 return output
240314
241315 @layer
242- def dropout (self , input , keep_prob , name ):
316+ def dropout (self , x , keep_prob , name ):
243317 keep = 1 - self .use_dropout + (self .use_dropout * keep_prob )
244- return tf .nn .dropout (input , keep , name = name )
318+ return tf .nn .dropout (x , keep , name = name )
0 commit comments