resnet_model.py 4.1 KB
Newer Older
M
mir-of 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import oneflow as flow


BLOCK_COUNTS = [3, 4, 6, 3]
BLOCK_FILTERS = [256, 512, 1024, 2048]
BLOCK_FILTERS_INNER = [64, 128, 256, 512]


def _conv2d(
    name,
    input,
    filters,
    kernel_size,
    strides=1,
    padding="SAME",
    data_format="NCHW",
    dilations=1,
H
hjchen2 已提交
22
    trainable=True,
M
mir-of 已提交
23 24
    weight_initializer=flow.variance_scaling_initializer(data_format="NCHW"),
):
M
mir-of 已提交
25 26 27 28 29
    weight = flow.get_variable(
        name + "-weight",
        shape=(filters, input.static_shape[1], kernel_size, kernel_size),
        dtype=input.dtype,
        initializer=weight_initializer,
H
hjchen2 已提交
30
        trainable=trainable,
M
mir-of 已提交
31 32 33 34
    )
    return flow.nn.conv2d(
        input, weight, strides, padding, data_format, dilations, name=name
    )
M
mir-of 已提交
35 36


H
hjchen2 已提交
37
def _batch_norm(inputs, name=None, trainable=True):
M
mir-of 已提交
38 39 40
    return flow.layers.batch_normalization(
        inputs=inputs,
        axis=1,
S
ShawnXuan 已提交
41
        momentum=0.9,#97,
S
fix  
ShawnXuan 已提交
42
        epsilon=1e-05,#1.001e-5,
M
mir-of 已提交
43 44
        center=True,
        scale=True,
H
hjchen2 已提交
45
        trainable=trainable,
M
mir-of 已提交
46 47
        name=name,
    )
M
mir-of 已提交
48 49


M
mir-of 已提交
50
def conv2d_affine(input, name, filters, kernel_size, strides, activation=None):
M
mir-of 已提交
51 52 53 54 55 56
    # input data_format must be NCHW, cannot check now
    padding = "SAME" if strides > 1 or kernel_size > 1 else "VALID"
    output = _conv2d(name, input, filters, kernel_size, strides, padding)
    output = _batch_norm(output, name + "_bn")
    if activation == "Relu":
        output = flow.keras.activations.relu(output)
M
mir-of 已提交
57

M
mir-of 已提交
58
    return output
M
mir-of 已提交
59 60


M
mir-of 已提交
61
def bottleneck_transformation(input, block_name, filters, filters_inner, strides):
M
mir-of 已提交
62
    a = conv2d_affine(
M
mir-of 已提交
63
        input, block_name + "_branch2a", filters_inner, 1, 1, activation="Relu",
M
mir-of 已提交
64
    )
M
mir-of 已提交
65

M
mir-of 已提交
66
    b = conv2d_affine(
M
mir-of 已提交
67
        a, block_name + "_branch2b", filters_inner, 3, strides, activation="Relu",
M
mir-of 已提交
68
    )
M
mir-of 已提交
69

M
mir-of 已提交
70
    c = conv2d_affine(b, block_name + "_branch2c", filters, 1, 1)
M
mir-of 已提交
71

M
mir-of 已提交
72
    return c
M
mir-of 已提交
73 74 75


def residual_block(input, block_name, filters, filters_inner, strides_init):
M
mir-of 已提交
76 77 78 79 80 81 82 83 84
    if strides_init != 1 or block_name == "res2_0":
        shortcut = conv2d_affine(
            input, block_name + "_branch1", filters, 1, strides_init
        )
    else:
        shortcut = input

    bottleneck = bottleneck_transformation(
        input, block_name, filters, filters_inner, strides_init
M
mir-of 已提交
85
    )
M
mir-of 已提交
86

M
mir-of 已提交
87
    return flow.keras.activations.relu(bottleneck + shortcut)
M
mir-of 已提交
88 89


M
mir-of 已提交
90
def residual_stage(input, stage_name, counts, filters, filters_inner, stride_init=2):
M
mir-of 已提交
91 92 93 94
    output = input
    for i in range(counts):
        block_name = "%s_%d" % (stage_name, i)
        output = residual_block(
M
mir-of 已提交
95
            output, block_name, filters, filters_inner, stride_init if i == 0 else 1,
M
mir-of 已提交
96
        )
M
mir-of 已提交
97

M
mir-of 已提交
98
    return output
M
mir-of 已提交
99 100 101


def resnet_conv_x_body(input, on_stage_end=lambda x: x):
M
mir-of 已提交
102 103 104 105 106 107
    output = input
    for i, (counts, filters, filters_inner) in enumerate(
        zip(BLOCK_COUNTS, BLOCK_FILTERS, BLOCK_FILTERS_INNER)
    ):
        stage_name = "res%d" % (i + 2)
        output = residual_stage(
M
mir-of 已提交
108
            output, stage_name, counts, filters, filters_inner, 1 if i == 0 else 2,
M
mir-of 已提交
109 110 111 112
        )
        on_stage_end(output)

    return output
M
mir-of 已提交
113 114


M
mir-of 已提交
115
def resnet_stem(input):
M
mir-of 已提交
116 117 118
    conv1 = _conv2d("conv1", input, 64, 7, 2)
    conv1_bn = flow.keras.activations.relu(_batch_norm(conv1, "conv1_bn"))
    pool1 = flow.nn.max_pool2d(
M
mir-of 已提交
119
        conv1_bn, ksize=3, strides=2, padding="VALID", data_format="NCHW", name="pool1",
M
mir-of 已提交
120
    )
M
mir-of 已提交
121 122 123
    return pool1


H
hjchen2 已提交
124
def resnet50(images, trainable=True):
M
mir-of 已提交
125 126 127 128 129 130 131

    images = flow.transpose(images, name="transpose", perm=[0, 3, 1, 2])

    with flow.deprecated.variable_scope("Resnet"):
        stem = resnet_stem(images)
        body = resnet_conv_x_body(stem, lambda x: x)
        pool5 = flow.nn.avg_pool2d(
M
mir-of 已提交
132
            body, ksize=7, strides=1, padding="VALID", data_format="NCHW", name="pool5",
M
mir-of 已提交
133 134 135 136 137 138 139 140
        )

        fc1001 = flow.layers.dense(
            flow.reshape(pool5, (pool5.shape[0], -1)),
            units=1001,
            use_bias=True,
            kernel_initializer=flow.xavier_uniform_initializer(),
            bias_initializer=flow.zeros_initializer(),
H
hjchen2 已提交
141
            trainable=trainable,
M
mir-of 已提交
142 143 144
            name="fc1001",
        )

H
hjchen2 已提交
145
    return fc1001