Source code for tensorlayer.models.resnet

#! /usr/bin/python
# -*- coding: utf-8 -*-
"""ResNet for ImageNet.

# Reference:
- [Deep Residual Learning for Image Recognition](
    https://arxiv.org/abs/1512.03385) (CVPR 2016 Best Paper Award)

"""

import os

import tensorflow as tf
from tensorlayer import logging
from tensorlayer.files import (assign_weights, load_npz, maybe_download_and_extract)
from tensorlayer.layers import (BatchNorm, Conv2d, Elementwise, GlobalMeanPool2d, MaxPool2d, Input, Dense)
from tensorlayer.models import Model

__all__ = [
    'ResNet50',
]


def identity_block(input, kernel_size, n_filters, stage, block):
    """The identity block where there is no conv layer at shortcut.

    Parameters
    ----------
    input : tf tensor
        Input tensor from above layer.
    kernel_size : int
        The kernel size of middle conv layer at main path.
    n_filters : list of integers
        The numbers of filters for 3 conv layer at main path.
    stage : int
        Current stage label.
    block : str
        Current block label.

    Returns
    -------
        Output tensor of this block.

    """
    filters1, filters2, filters3 = n_filters
    conv_name_base = 'res' + str(stage) + block + '_branch'
    bn_name_base = 'bn' + str(stage) + block + '_branch'

    x = Conv2d(filters1, (1, 1), W_init=tf.initializers.he_normal(), name=conv_name_base + '2a')(input)
    x = BatchNorm(name=bn_name_base + '2a', act='relu')(x)

    ks = (kernel_size, kernel_size)
    x = Conv2d(filters2, ks, padding='SAME', W_init=tf.initializers.he_normal(), name=conv_name_base + '2b')(x)
    x = BatchNorm(name=bn_name_base + '2b', act='relu')(x)

    x = Conv2d(filters3, (1, 1), W_init=tf.initializers.he_normal(), name=conv_name_base + '2c')(x)
    x = BatchNorm(name=bn_name_base + '2c')(x)

    x = Elementwise(tf.add, act='relu')([x, input])
    return x


def conv_block(input, kernel_size, n_filters, stage, block, strides=(2, 2)):
    """The conv block where there is a conv layer at shortcut.

    Parameters
    ----------
    input : tf tensor
        Input tensor from above layer.
    kernel_size : int
        The kernel size of middle conv layer at main path.
    n_filters : list of integers
        The numbers of filters for 3 conv layer at main path.
    stage : int
        Current stage label.
    block : str
        Current block label.
    strides : tuple
        Strides for the first conv layer in the block.

    Returns
    -------
        Output tensor of this block.

    """
    filters1, filters2, filters3 = n_filters
    conv_name_base = 'res' + str(stage) + block + '_branch'
    bn_name_base = 'bn' + str(stage) + block + '_branch'

    x = Conv2d(filters1, (1, 1), strides=strides, W_init=tf.initializers.he_normal(), name=conv_name_base + '2a')(input)
    x = BatchNorm(name=bn_name_base + '2a', act='relu')(x)

    ks = (kernel_size, kernel_size)
    x = Conv2d(filters2, ks, padding='SAME', W_init=tf.initializers.he_normal(), name=conv_name_base + '2b')(x)
    x = BatchNorm(name=bn_name_base + '2b', act='relu')(x)

    x = Conv2d(filters3, (1, 1), W_init=tf.initializers.he_normal(), name=conv_name_base + '2c')(x)
    x = BatchNorm(name=bn_name_base + '2c')(x)

    shortcut = Conv2d(filters3, (1, 1), strides=strides, W_init=tf.initializers.he_normal(),
                      name=conv_name_base + '1')(input)
    shortcut = BatchNorm(name=bn_name_base + '1')(shortcut)

    x = Elementwise(tf.add, act='relu')([x, shortcut])
    return x


block_names = ['2a', '2b', '2c', '3a', '3b', '3c', '3d', '4a', '4b', '4c', '4d', '4e', '4f', '5a', '5b', '5c'
              ] + ['avg_pool', 'fc1000']
block_filters = [[64, 64, 256], [128, 128, 512], [256, 256, 1024], [512, 512, 2048]]


[docs]def ResNet50(pretrained=False, end_with='fc1000', n_classes=1000, name=None): """Pre-trained MobileNetV1 model (static mode). Input shape [?, 224, 224, 3]. To use pretrained model, input should be in BGR format and subtracted from ImageNet mean [103.939, 116.779, 123.68]. Parameters ---------- pretrained : boolean Whether to load pretrained weights. Default False. end_with : str The end point of the model [conv, depth1, depth2 ... depth13, globalmeanpool, out]. Default ``out`` i.e. the whole model. n_classes : int Number of classes in final prediction. name : None or str Name for this model. Examples --------- Classify ImageNet classes, see `tutorial_models_resnet50.py` >>> # get the whole model with pretrained weights >>> resnet = tl.models.ResNet50(pretrained=True) >>> # use for inferencing >>> output = resnet(img1, is_train=False) >>> prob = tf.nn.softmax(output)[0].numpy() Extract the features before fc layer >>> resnet = tl.models.ResNet50(pretrained=True, end_with='5c') >>> output = resnet(img1, is_train=False) Returns ------- ResNet50 model. """ ni = Input([None, 224, 224, 3], name="input") n = Conv2d(64, (7, 7), strides=(2, 2), padding='SAME', W_init=tf.initializers.he_normal(), name='conv1')(ni) n = BatchNorm(name='bn_conv1', act='relu')(n) n = MaxPool2d((3, 3), strides=(2, 2), name='max_pool1')(n) for i, block_name in enumerate(block_names): if len(block_name) == 2: stage = int(block_name[0]) block = block_name[1] if block == 'a': strides = (1, 1) if stage == 2 else (2, 2) n = conv_block(n, 3, block_filters[stage - 2], stage=stage, block=block, strides=strides) else: n = identity_block(n, 3, block_filters[stage - 2], stage=stage, block=block) elif block_name == 'avg_pool': n = GlobalMeanPool2d(name='avg_pool')(n) elif block_name == 'fc1000': n = Dense(n_classes, name='fc1000')(n) if block_name == end_with: break network = Model(inputs=ni, outputs=n, name=name) if pretrained: restore_params(network) return network
def restore_params(network, path='models'): logging.info("Restore pre-trained parameters") maybe_download_and_extract( 'resnet50_weights_tf_dim_ordering_tf_kernels.h5', path, 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/', ) # ls -al try: import h5py except Exception: raise ImportError('h5py not imported') f = h5py.File(os.path.join(path, 'resnet50_weights_tf_dim_ordering_tf_kernels.h5'), 'r') for layer in network.all_layers: if len(layer.all_weights) == 0: continue w_names = list(f[layer.name]) params = [f[layer.name][n][:] for n in w_names] # if 'bn' in layer.name: # params = [x.reshape(1, 1, 1, -1) for x in params] assign_weights(params, layer) del params f.close()