- Advanced Deep Learning with Keras
- Rowel Atienza
- 457字
- 2025-02-26 16:55:06
ResNet v2
After the release of the second paper on ResNet [4], the original model presented in the previous section has been known as ResNet v1. The improved ResNet is commonly called ResNet v2. The improvement is mainly found in the arrangement of layers in the residual block as shown in following figure.
The prominent changes in ResNet v2 are:
- The use of a stack of 1 × 1 - 3 × 3 - 1 × 1
BN-ReLU-Conv2D
- Batch normalization and ReLU activation come before 2D convolution

Figure 2.3.1: A comparison of residual blocks between ResNet v1 and ResNet v2
ResNet v2 is also implemented in the same code as resnet-cifar10-2.2.1.py
:
def resnet_v2(input_shape, depth, num_classes=10): if (depth - 2) % 9 != 0: raise ValueError('depth should be 9n+2 (eg 56 or 110 in [b])') # Start model definition. num_filters_in = 16 num_res_blocks = int((depth - 2) / 9) inputs = Input(shape=input_shape) # v2 performs Conv2D with BN-ReLU on input # before splitting into 2 paths x = resnet_layer(inputs=inputs, num_filters=num_filters_in, conv_first=True) # Instantiate the stack of residual units for stage in range(3): for res_block in range(num_res_blocks): activation = 'relu' batch_normalization = True strides = 1 if stage == 0: num_filters_out = num_filters_in * 4 if res_block == 0: # first layer and first stage activation = None batch_normalization = False else: num_filters_out = num_filters_in * 2 if res_block == 0: # 1st layer but not 1st stage strides = 2 # downsample # bottleneck residual unit y = resnet_layer(inputs=x, num_filters=num_filters_in, kernel_size=1, strides=strides, activation=activation, batch_normalization=batch_normalization, conv_first=False) y = resnet_layer(inputs=y, num_filters=num_filters_in, conv_first=False) y = resnet_layer(inputs=y, num_filters=num_filters_out, kernel_size=1, conv_first=False) if res_block == 0: # linear projection residual shortcut connection # to match changed dims x = resnet_layer(inputs=x, num_filters=num_filters_out, kernel_size=1, strides=strides, activation=None, batch_normalization=False) x = add([x, y]) num_filters_in = num_filters_out # add classifier on top. # v2 has BN-ReLU before Pooling x = BatchNormalization()(x) x = Activation('relu')(x) x = AveragePooling2D(pool_size=8)(x) y = Flatten()(x) outputs = Dense(num_classes, activation='softmax', kernel_initializer='he_normal')(y) # instantiate model. model = Model(inputs=inputs, outputs=outputs) return model
ResNet v2's model builder is shown in the following code. For example, to build ResNet110 v2, we'll use n = 12
:
n = 12 # model version # orig paper: version = 1 (ResNet v1), Improved ResNet: version = 2 (ResNet v2) version = 2 # computed depth from supplied model parameter n if version == 1: depth = n * 6 + 2 elif version == 2: depth = n * 9 + 2 … if version == 2: model = resnet_v2(input_shape=input_shape, depth=depth) else: model = resnet_v1(input_shape=input_shape, depth=depth)
The accuracy of ResNet v2 is shown in following table:

In the Keras applications package, ResNet50 has been implemented as well with the corresponding checkpoint for reuse. This is an alternative implementation but tied to the 50-layer ResNet v1.