def _shake_shake_skip_connection(x, output_filters, stride): """Adds a residual connection to the filter x for the shake-shake model.""" curr_filters = int(x.shape[3]) if curr_filters == output_filters: return x stride_spec = ops.stride_arr(stride, stride) # Skip path 1 path1 = tf.nn.avg_pool(x, [1, 1, 1, 1], stride_spec, 'VALID', data_format='NHWC') path1 = ops.conv2d(path1, int(output_filters / 2), 1, scope='path1_conv') # Skip path 2 # First pad with 0's then crop pad_arr = [[0, 0], [0, 1], [0, 1], [0, 0]] path2 = tf.pad(x, pad_arr)[:, 1:, 1:, :] concat_axis = 3 path2 = tf.nn.avg_pool(path2, [1, 1, 1, 1], stride_spec, 'VALID', data_format='NHWC') path2 = ops.conv2d(path2, int(output_filters / 2), 1, scope='path2_conv') # Concat and apply BN final_path = tf.concat(values=[path1, path2], axis=concat_axis) final_path = ops.batch_norm(final_path, scope='final_path_bn') return final_path
def _shake_shake_skip_connection(x, output_filters, stride): """Adds a residual connection to the filter x for the shake-shake model.""" curr_filters = int(x.shape[3]) if curr_filters == output_filters: return x stride_spec = ops.stride_arr(stride, stride) # Skip path 1 path1 = tf.nn.avg_pool( x, [1, 1, 1, 1], stride_spec, 'VALID', data_format='NHWC') path1 = ops.conv2d(path1, int(output_filters / 2), 1, scope='path1_conv') # Skip path 2 # First pad with 0's then crop pad_arr = [[0, 0], [0, 1], [0, 1], [0, 0]] path2 = tf.pad(x, pad_arr)[:, 1:, 1:, :] concat_axis = 3 path2 = tf.nn.avg_pool( path2, [1, 1, 1, 1], stride_spec, 'VALID', data_format='NHWC') path2 = ops.conv2d(path2, int(output_filters / 2), 1, scope='path2_conv') # Concat and apply BN final_path = tf.concat(values=[path1, path2], axis=concat_axis) final_path = ops.batch_norm(final_path, scope='final_path_bn') return final_path