2 Based on https://github.com/raghakot/keras-resnet/blob/master/resnet.py 5 from __future__
import division
8 from keras.models
import Model
9 from keras.layers
import (
22 from keras.layers.convolutional
import (
27 from keras.layers.merge
import add
28 from keras.layers.normalization
import BatchNormalization
29 from keras.regularizers
import l2
30 from keras
import backend
as K
34 """Helper to build a BN -> relu block 36 norm = BatchNormalization(axis=CHANNEL_AXIS)(input)
37 return Activation(
"relu")(norm)
41 """Helper to build a conv -> BN -> relu block 43 filters = conv_params[
"filters"]
44 kernel_size = conv_params[
"kernel_size"]
45 strides = conv_params.setdefault(
"strides", (1, 1))
46 kernel_initializer = conv_params.setdefault(
"kernel_initializer",
"he_normal")
47 padding = conv_params.setdefault(
"padding",
"same")
48 kernel_regularizer = conv_params.setdefault(
"kernel_regularizer", l2(1.e-4))
51 conv = Conv2D(filters=filters, kernel_size=kernel_size,
52 strides=strides, padding=padding,
53 kernel_initializer=kernel_initializer,
54 kernel_regularizer=kernel_regularizer)(input)
61 """Helper to build a BN -> relu -> conv block. 62 This is an improved scheme proposed in http://arxiv.org/pdf/1603.05027v2.pdf 64 filters = conv_params[
"filters"]
65 kernel_size = conv_params[
"kernel_size"]
66 strides = conv_params.setdefault(
"strides", (1, 1))
67 kernel_initializer = conv_params.setdefault(
"kernel_initializer",
"he_normal")
68 padding = conv_params.setdefault(
"padding",
"same")
69 kernel_regularizer = conv_params.setdefault(
"kernel_regularizer", l2(1.e-4))
73 return Conv2D(filters=filters, kernel_size=kernel_size,
74 strides=strides, padding=padding,
75 kernel_initializer=kernel_initializer,
76 kernel_regularizer=kernel_regularizer)(activation)
82 """Adds a shortcut between input and residual block and merges them with "sum" 87 input_shape = K.int_shape(input)
88 residual_shape = K.int_shape(residual)
89 stride_width =
int(round(input_shape[ROW_AXIS] / residual_shape[ROW_AXIS]))
90 stride_height =
int(round(input_shape[COL_AXIS] / residual_shape[COL_AXIS]))
91 equal_channels = input_shape[CHANNEL_AXIS] == residual_shape[CHANNEL_AXIS]
95 if stride_width > 1
or stride_height > 1
or not equal_channels:
96 shortcut = Conv2D(filters=residual_shape[CHANNEL_AXIS],
98 strides=(stride_width, stride_height),
100 kernel_initializer=
"he_normal",
101 kernel_regularizer=l2(0.0001))(input)
103 return add([shortcut, residual])
107 """Builds a residual block with repeating bottleneck blocks. 110 for i
in range(repetitions):
111 init_strides = (1, 1)
112 if i == 0
and not is_first_layer:
113 init_strides = (2, 2)
114 input = block_function(filters=filters, init_strides=init_strides,
115 is_first_block_of_first_layer=(is_first_layer
and i == 0))(input)
121 def basic_block(filters, init_strides=(1, 1), is_first_block_of_first_layer=
False):
122 """Basic 3 X 3 convolution blocks for use on resnets with layers <= 34. 123 Follows improved proposed scheme in http://arxiv.org/pdf/1603.05027v2.pdf 127 if is_first_block_of_first_layer:
129 conv1 = Conv2D(filters=filters, kernel_size=(3, 3),
130 strides=init_strides,
132 kernel_initializer=
"he_normal",
133 kernel_regularizer=l2(1e-4))(input)
136 strides=init_strides)(input)
138 residual =
_bn_relu_conv(filters=filters, kernel_size=(3, 3))(conv1)
144 def bottleneck(filters, init_strides=(1, 1), is_first_block_of_first_layer=
False):
145 """Bottleneck architecture for > 34 layer resnet. 146 Follows improved proposed scheme in http://arxiv.org/pdf/1603.05027v2.pdf 149 A final conv layer of filters * 4 153 if is_first_block_of_first_layer:
155 conv_1_1 = Conv2D(filters=filters, kernel_size=(1, 1),
156 strides=init_strides,
158 kernel_initializer=
"he_normal",
159 kernel_regularizer=l2(1e-4))(input)
161 conv_1_1 =
_bn_relu_conv(filters=filters, kernel_size=(1, 1),
162 strides=init_strides)(input)
164 conv_3_3 =
_bn_relu_conv(filters=filters, kernel_size=(3, 3))(conv_1_1)
165 residual =
_bn_relu_conv(filters=filters * 4, kernel_size=(1, 1))(conv_3_3)
175 if K.image_dim_ordering() ==
'tf':
186 if isinstance(identifier, six.string_types):
187 res = globals().
get(identifier)
189 raise ValueError(
'Invalid {}'.
format(identifier))
196 def build(input_shape, num_outputs, block_fn, repetitions, branches=False):
197 """Builds a custom ResNet like architecture. 200 input_shape: The input shape in the form (nb_channels, nb_rows, nb_cols) 201 num_outputs: The number of outputs at final softmax layer 202 block_fn: The block function to use. This is either `basic_block` or `bottleneck`. 203 The original paper used basic_block for layers < 50 204 repetitions: Number of repetitions of various block units. 205 At each block unit, the number of filters are doubled and the input size is halved 211 if len(input_shape) != 3:
212 raise Exception(
"Input shape should be a tuple (nb_channels, nb_rows, nb_cols)")
215 # Permute dimension order if necessary 216 if K.image_dim_ordering() == 'tf': 217 input_shape = (input_shape[1], input_shape[2], input_shape[0]) 223 input =
Input(shape=input_shape)
224 conv1 =
_conv_bn_relu(filters=64, kernel_size=(7, 7), strides=(2, 2))(input)
225 pool1 = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding=
"same")(conv1)
230 block =
_residual_block(block_fn, filters=filters, repetitions=r, is_first_layer=(i == 0))(block)
237 block_shape = K.int_shape(block)
238 pool2 = AveragePooling2D(pool_size=(block_shape[ROW_AXIS], block_shape[COL_AXIS]),
239 strides=(1, 1))(block)
240 flatten1 = Flatten()(pool2)
246 model = Model(inputs=input, outputs=flatten1)
252 dense = Dense(units=num_outputs, kernel_initializer=
"he_normal",
253 activation=
"softmax")(flatten1)
254 model = Model(inputs=input, outputs=dense)
261 branches = input_shape[2]
265 branches_outputs = []
267 for branch
in range(branches):
271 branch_model = ResnetBuilder.build(input_shape, num_outputs, basic_block, [2, 2, 2, 2], branches=
True)
272 branches_inputs.append(branch_model.input)
273 branches_outputs.append(branch_model.output)
277 if merge_type ==
'add':
279 merged = Add()(branches_outputs)
281 elif merge_type ==
'sub':
283 merged = Substract()(branches_outputs)
285 elif merge_type ==
'mul':
287 merged = Multiply()(branches_outputs)
289 elif merge_type ==
'avg':
291 merged = Average()(branches_outputs)
293 elif merge_type ==
'max':
295 merged = Maximum()(branches_outputs)
297 elif merge_type ==
'dot':
299 merged = Dot()(branches_outputs)
303 merged = Concatenate()(branches_outputs)
307 dense = Dense(units=num_outputs, kernel_initializer=
"he_normal", activation=
"softmax")(merged)
311 model = Model(branches_inputs, dense)
318 return ResnetBuilder.build(input_shape, num_outputs, basic_block, [2, 2, 2, 2])
322 return ResnetBuilder.build(input_shape, num_outputs, basic_block, [3, 4, 6, 3])
326 return ResnetBuilder.build(input_shape, num_outputs, bottleneck, [3, 4, 6, 3])
330 return ResnetBuilder.build(input_shape, num_outputs, bottleneck, [3, 4, 23, 3])
334 return ResnetBuilder.build(input_shape, num_outputs, bottleneck, [3, 8, 36, 3])
def _bn_relu_conv(conv_params)
static bool format(QChar::Decomposition tag, QString &str, int index, int len)
Coord add(Coord c1, Coord c2)
def build_resnet_50(input_shape, num_outputs)
def _conv_bn_relu(conv_params)
def basic_block(filters, init_strides=(1, 1), is_first_block_of_first_layer=False)
def _get_block(identifier)
def _shortcut(input, residual)
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
def build_resnet_18(input_shape, num_outputs)
def _residual_block(block_function, filters, repetitions, is_first_layer=False)
def build_resnet_152(input_shape, num_outputs)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
def build_resnet_34(input_shape, num_outputs)
def bottleneck(filters, init_strides=(1, 1), is_first_block_of_first_layer=False)
auto const & get(AssnsNode< L, R, D > const &r)
def build_resnet_18_merged(input_shape, num_outputs, merge_type='concat')
def build(input_shape, num_outputs, block_fn, repetitions, branches=False)
def build_resnet_101(input_shape, num_outputs)
def _handle_dim_ordering()