From 0c8820e6fbdcaa91e6b18da02eb84e998ed425c7 Mon Sep 17 00:00:00 2001 From: Flowingsun007 Date: Fri, 23 Oct 2020 15:10:02 +0800 Subject: [PATCH 1/9] add new cnn model:res2net --- Classification/cnns/of_cnn_train_val.py | 2 + Classification/cnns/res2net_model.py | 329 ++++++++++++++++++++++++ 2 files changed, 331 insertions(+) create mode 100644 Classification/cnns/res2net_model.py diff --git a/Classification/cnns/of_cnn_train_val.py b/Classification/cnns/of_cnn_train_val.py index ba84865..38bbc96 100755 --- a/Classification/cnns/of_cnn_train_val.py +++ b/Classification/cnns/of_cnn_train_val.py @@ -22,6 +22,7 @@ from util import Snapshot, Summary, InitNodes, Metric from job_function_util import get_train_config, get_val_config import resnet_model +import res2net_model import resnext_model import vgg_model import alexnet_model @@ -42,6 +43,7 @@ model_dict = { "resnet50": resnet_model.resnet50, + "res2net50": res2net_model.res2net50, "vgg": vgg_model.vgg16bn, "alexnet": alexnet_model.alexnet, "inceptionv3": inception_model.inceptionv3, diff --git a/Classification/cnns/res2net_model.py b/Classification/cnns/res2net_model.py new file mode 100644 index 0000000..c117926 --- /dev/null +++ b/Classification/cnns/res2net_model.py @@ -0,0 +1,329 @@ +""" +Copyright 2020 The OneFlow Authors. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +import oneflow as flow + + +class Res2netBuilder(object): + def __init__(self, weight_regularizer, trainable=True, training=True, channel_last=False, fuse_bn_relu=True, + fuse_bn_add_relu=True): + self.data_format = "NHWC" if channel_last else "NCHW" + self.weight_initializer = flow.variance_scaling_initializer(2, 'fan_in', 'random_normal', + data_format=self.data_format) + self.weight_regularizer = weight_regularizer + self.trainable = trainable + self.training = training + self.fuse_bn_relu = fuse_bn_relu + self.fuse_bn_add_relu = fuse_bn_add_relu + self.baseWidth = 26 + self.scale = 4 + self.stype = "stage" + self.nums = self.scale-1 + + def _conv2d( + self, + name, + input, + filters, + kernel_size, + strides=1, + padding="SAME", + dilations=1, + ): + # There are different shapes of weight metric between 'NCHW' and 'NHWC' mode + if self.data_format == "NHWC": + shape = (filters, kernel_size, kernel_size, input.shape[3]) + else: + shape = (filters, input.shape[1], kernel_size, kernel_size) + weight = flow.get_variable( + name + "-weight", + shape=shape, + dtype=input.dtype, + initializer=self.weight_initializer, + regularizer=self.weight_regularizer, + model_name="weight", + trainable=self.trainable, + ) + + return flow.nn.conv2d(input, weight, strides, padding, self.data_format, dilations, name=name) + + def _batch_norm(self, inputs, name=None, last=False): + initializer = flow.zeros_initializer() if last else flow.ones_initializer() + axis = 1 + if self.data_format == "NHWC": + axis = 3 + return flow.layers.batch_normalization( + inputs=inputs, + axis=axis, + momentum=0.9, # 97, + epsilon=1e-5, + center=True, + scale=True, + trainable=self.trainable, + training=self.training, + gamma_initializer=initializer, + moving_variance_initializer=initializer, + gamma_regularizer=self.weight_regularizer, + beta_regularizer=self.weight_regularizer, + name=name, + ) + + def _batch_norm_relu(self, inputs, name=None, last=False): + if self.fuse_bn_relu: + initializer = flow.zeros_initializer() if last else flow.ones_initializer() + axis = 1 + if self.data_format == "NHWC": + axis = 3 + return flow.layers.batch_normalization_relu( + inputs=inputs, + axis=axis, + momentum=0.9, + epsilon=1e-5, + center=True, + scale=True, + trainable=self.trainable, + training=self.training, + gamma_initializer=initializer, + moving_variance_initializer=initializer, + gamma_regularizer=self.weight_regularizer, + beta_regularizer=self.weight_regularizer, + name=name + "_bn_relu", + ) + else: + return flow.nn.relu(self._batch_norm(inputs, name + "_bn", last=last)) + + def _batch_norm_add_relu(self, inputs, addend, name=None, last=False): + if self.fuse_bn_add_relu: + initializer = flow.zeros_initializer() if last else flow.ones_initializer() + axis = 1 + if self.data_format == "NHWC": + axis = 3 + return flow.layers.batch_normalization_add_relu( + inputs=inputs, + addend=addend, + axis=axis, + momentum=0.9, + epsilon=1e-5, + center=True, + scale=True, + trainable=self.trainable, + training=self.training, + gamma_initializer=initializer, + moving_variance_initializer=initializer, + gamma_regularizer=self.weight_regularizer, + beta_regularizer=self.weight_regularizer, + name=name + "_bn_add_relu", + ) + else: + return flow.nn.relu(self._batch_norm(inputs, name + "_bn", last=last) + addend) + + def conv2d_affine(self, input, name, filters, kernel_size, strides): + # input data_format must be NCHW, cannot check now + padding = "SAME" if strides > 1 or kernel_size > 1 else "VALID" + output = self._conv2d(name, input, filters, kernel_size, strides, padding) + return output + + def bottleneck_res2net(self, input, block_name, filters, filters_inner, stride): + a = self.conv2d_affine( + input, block_name + "_branch2a", filters_inner, 1, 1) + x = self._batch_norm_relu(a, block_name + "_branch2a") + if self.scale == 1: + self.nums = 1 + + spx = [] + width = int(x.shape[1] / 4) + for i in range(4): + spx.append(flow.slice(x, begin=[None, i * width, None, None], size=[None, width, None, None])) + out = flow.concat(inputs=[spx[0], spx[1], spx[2], spx[3]], axis=1) + + for i in range(4): + if i == 0 or self.stype == 'stage': + sp = spx[i] + else: + sp = sp + spx[i] + if i == 0: + out = sp + else: + out = flow.concat(inputs=[out, sp], axis=1) + if self.stype == 'normal': + out = flow.concat(inputs=[out, sp[self.nums]], axis=1) + elif self.stype == 'stage': + out = flow.nn.avg_pool2d( + spx[self.nums], ksize=3, strides=stride, padding="SAME", + data_format=self.data_format, name=block_name+"bottleneck_avg_pool", + ) + + z = self.conv2d_affine(out, block_name + "_branch2c", filters, 1, 1) + return z + + def bottleneck_transformation(self, input, block_name, filters, filters_inner, strides): + a = self.conv2d_affine( + input, block_name + "_branch2a", filters_inner, 1, 1) + a = self._batch_norm_relu(a, block_name + "_branch2a") + + b = self.conv2d_affine( + a, block_name + "_branch2b", filters_inner, 3, strides) + b = self._batch_norm_relu(b, block_name + "_branch2b") + + c = self.conv2d_affine(b, block_name + "_branch2c", filters, 1, 1) + return c + + def residual_block(self, input, block_name, filters, filters_inner, strides_init): + if strides_init != 1 or block_name == "res2_0": + shortcut = self.conv2d_affine( + input, block_name + "_branch1", filters, 1, strides_init + ) + shortcut = self._batch_norm(shortcut, block_name + "_branch1_bn") + stride = 1 + else: + shortcut = input + stride = 2 + + + bottleneck = self.bottleneck_res2net( + input, block_name, filters, filters_inner, strides_init, + ) + + output = self._batch_norm_add_relu(bottleneck, shortcut, block_name + "_branch2c", last=True) + return output + + def residual_stage(self, input, stage_name, counts, filters, filters_inner, stride_init=2): + output = input + stype = "stage" + for i in range(counts): + # print("ResNet body resnet_conv_x_body >> residual_stage i:", i, "input:", output.shape) + block_name = "%s_%d" % (stage_name, i) + output = self.residual_block( + output, block_name, filters, filters_inner, stride_init if i == 0 else 1 + ) + return output + + def resnet_conv_x_body(self, input, resnet_blocks): + output = input + for i, (counts, filters, filters_inner) in enumerate(resnet_blocks): + # print("ResNet body resnet_conv_x_body i:", i, "input:", output.shape) + stage_name = "res%d" % (i + 2) + output = self.residual_stage( + output, stage_name, counts, filters, filters_inner, 1 if i == 0 else 2 + ) + + return output + + def resnet_stem(self, input): + conv1 = self._conv2d("conv1", input, 64, 7, 2) + conv1_bn = self._batch_norm_relu(conv1, "conv1") + pool1 = flow.nn.max_pool2d( + conv1_bn, ksize=3, strides=2, padding="SAME", data_format=self.data_format, name="pool1", + ) + return pool1 + + +def res2net50(images, args, trainable=True, training=True): + weight_regularizer = flow.regularizers.l2(args.wd) if args.wd > 0.0 and args.wd < 1.0 else None + builder = Res2netBuilder(weight_regularizer, trainable, training, args.channel_last, args.fuse_bn_relu, + args.fuse_bn_add_relu) + block_counts = [3, 4, 6, 3] + block_filters = [256, 512, 1024, 2048] + block_filters_inner = [64, 128, 256, 512] + resnet_blocks = zip(block_counts, block_filters, block_filters_inner) + + if args.pad_output: + if args.channel_last: + paddings = ((0, 0), (0, 0), (0, 0), (0, 1)) + else: + paddings = ((0, 0), (0, 1), (0, 0), (0, 0)) + images = flow.pad(images, paddings=paddings) + with flow.scope.namespace("Resnet"): + #print("ResNet stem input ", images.shape) + stem = builder.resnet_stem(images) + #print("ResNet body input ", stem.shape) + body = builder.resnet_conv_x_body(stem, resnet_blocks) + #print("ResNet body output ", body.shape) + pool5 = flow.nn.avg_pool2d( + body, ksize=7, strides=1, padding="VALID", data_format=builder.data_format, name="pool5", + ) + #print("ResNet body-pool output ", pool5.shape) + fc1001 = flow.layers.dense( + flow.reshape(pool5, (pool5.shape[0], -1)), + units=1000, + use_bias=True, + kernel_initializer=flow.variance_scaling_initializer(2, 'fan_in', 'random_normal'), + bias_initializer=flow.zeros_initializer(), + kernel_regularizer=weight_regularizer, + bias_regularizer=weight_regularizer, + trainable=trainable, + name="fc1001", + ) + # print("ResNet body-pool-fc output ", fc1001.shape) + return fc1001 + + +def res2net18(images, args, trainable=True, training=True): + weight_regularizer = flow.regularizers.l2(args.wd) if args.wd > 0.0 and args.wd < 1.0 else None + builder = Res2netBuilder(weight_regularizer, trainable, training, args.channel_last, args.fuse_bn_relu, + args.fuse_bn_add_relu) + block_counts = [2, 2, 2, 2] + block_filters = [64, 128, 256, 512] + block_filters_inner = [64, 128, 256, 512] + resnet_blocks = zip(block_counts, block_filters, block_filters_inner) + + if args.pad_output: + if args.channel_last: + paddings = ((0, 0), (0, 0), (0, 0), (0, 1)) + else: + paddings = ((0, 0), (0, 1), (0, 0), (0, 0)) + images = flow.pad(images, paddings=paddings) + with flow.scope.namespace("Resnet"): + stem = builder.resnet_stem(images) + body = builder.resnet_conv_x_body(stem, resnet_blocks) + pool5 = flow.nn.avg_pool2d( + body, ksize=7, strides=1, padding="VALID", data_format=builder.data_format, name="pool5", + ) + fc1001 = flow.layers.dense( + flow.reshape(pool5, (pool5.shape[0], -1)), + units=1000, + use_bias=True, + kernel_initializer=flow.variance_scaling_initializer(2, 'fan_in', 'random_normal'), + bias_initializer=flow.zeros_initializer(), + kernel_regularizer=weight_regularizer, + bias_regularizer=weight_regularizer, + trainable=trainable, + name="fc1001", + ) + return fc1001 + + +# import numpy as np +# import config as configs +# import oneflow.typing as tp +# +# parser = configs.get_parser() +# args = parser.parse_args() +# +# +# @flow.global_function(type="predict") +# def test_job( +# images: tp.Numpy.Placeholder((32, 3, 224, 224), dtype=flow.float), +# labels: tp.Numpy.Placeholder((32,), dtype=flow.int32)) -> tp.Numpy: +# output = res2net50(images, args) +# # print("images.shape, labels.shape, output.shape:", images.shape, labels.shape, output.shape) +# return output +# +# +# if __name__ == '__main__': +# images = np.random.uniform(-10, 10, (32, 1, 224, 224)).astype(np.float32) +# labels = np.random.randint(-10, 10, (32,)).astype(np.int32) +# output = test_job(images, labels) From 1919fc0c032831e459fba28bd8b69250dc33daca Mon Sep 17 00:00:00 2001 From: Flowingsun007 Date: Sun, 25 Oct 2020 18:41:47 +0800 Subject: [PATCH 2/9] modify structure of res2net --- Classification/cnns/res2net_model.py | 69 ++++++++++++++++------------ 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/Classification/cnns/res2net_model.py b/Classification/cnns/res2net_model.py index c117926..37bb543 100644 --- a/Classification/cnns/res2net_model.py +++ b/Classification/cnns/res2net_model.py @@ -30,8 +30,11 @@ def __init__(self, weight_regularizer, trainable=True, training=True, channel_la self.fuse_bn_add_relu = fuse_bn_add_relu self.baseWidth = 26 self.scale = 4 - self.stype = "stage" - self.nums = self.scale-1 + if self.scale == 1: + self.nums = 1 + else: + self.nums = self.scale - 1 + def _conv2d( self, @@ -136,31 +139,36 @@ def conv2d_affine(self, input, name, filters, kernel_size, strides): output = self._conv2d(name, input, filters, kernel_size, strides, padding) return output - def bottleneck_res2net(self, input, block_name, filters, filters_inner, stride): + def bottleneck_res2net(self, input, block_name, filters, filters_inner, stride, stype="normal"): + # width = int(math.floor(filters_inner * (self.baseWidth / 64.0))) + # self.conv1 = nn.Conv2d(inplanes, width * scale, kernel_size=1, bias=False) + # a = flow.slice(a, begin=[None, 0, None, None], size=[None, width * self.scale, None, None]) + a = self.conv2d_affine( input, block_name + "_branch2a", filters_inner, 1, 1) x = self._batch_norm_relu(a, block_name + "_branch2a") - if self.scale == 1: - self.nums = 1 spx = [] - width = int(x.shape[1] / 4) - for i in range(4): - spx.append(flow.slice(x, begin=[None, i * width, None, None], size=[None, width, None, None])) - out = flow.concat(inputs=[spx[0], spx[1], spx[2], spx[3]], axis=1) - - for i in range(4): - if i == 0 or self.stype == 'stage': - sp = spx[i] + split_num = int(x.shape[1] / self.scale) + for i in range(self.scale): + split_tensor = flow.slice(x, begin=[None, i * split_num, None, None], size=[None, split_num, None, None]) + spx.append(split_tensor) + # input = flow.concat(inputs=[spx[0], spx[1], spx[2], spx[3]], axis=1) + + for i in range(self.nums): + if i == 0 or stype == 'stage': + sp_tmp = spx[i] else: - sp = sp + spx[i] + sp_tmp = sp_tmp + spx[i] + sp = self.conv2d_affine(sp_tmp, block_name + "_branch2b_"+str(i), filters, 3, 1) + sp = self._batch_norm_relu(sp, block_name + "_branch2b_"+str(i)) if i == 0: out = sp else: - out = flow.concat(inputs=[out, sp], axis=1) - if self.stype == 'normal': - out = flow.concat(inputs=[out, sp[self.nums]], axis=1) - elif self.stype == 'stage': + out = flow.concat(inputs=[x, sp], axis=1) + if stype == 'normal': + out = flow.concat(inputs=[out, spx[self.nums]], axis=1) + elif stype == 'stage': out = flow.nn.avg_pool2d( spx[self.nums], ksize=3, strides=stride, padding="SAME", data_format=self.data_format, name=block_name+"bottleneck_avg_pool", @@ -169,17 +177,18 @@ def bottleneck_res2net(self, input, block_name, filters, filters_inner, stride): z = self.conv2d_affine(out, block_name + "_branch2c", filters, 1, 1) return z - def bottleneck_transformation(self, input, block_name, filters, filters_inner, strides): - a = self.conv2d_affine( - input, block_name + "_branch2a", filters_inner, 1, 1) - a = self._batch_norm_relu(a, block_name + "_branch2a") - b = self.conv2d_affine( - a, block_name + "_branch2b", filters_inner, 3, strides) - b = self._batch_norm_relu(b, block_name + "_branch2b") + # def bottleneck_transformation(self, input, block_name, filters, filters_inner, strides): + # a = self.conv2d_affine( + # input, block_name + "_branch2a", filters_inner, 1, 1) + # a = self._batch_norm_relu(a, block_name + "_branch2a") - c = self.conv2d_affine(b, block_name + "_branch2c", filters, 1, 1) - return c + # b = self.conv2d_affine( + # a, block_name + "_branch2b", filters_inner, 3, strides) + # b = self._batch_norm_relu(b, block_name + "_branch2b") + + # c = self.conv2d_affine(b, block_name + "_branch2c", filters, 1, 1) + # return c def residual_block(self, input, block_name, filters, filters_inner, strides_init): if strides_init != 1 or block_name == "res2_0": @@ -188,13 +197,14 @@ def residual_block(self, input, block_name, filters, filters_inner, strides_init ) shortcut = self._batch_norm(shortcut, block_name + "_branch1_bn") stride = 1 + stype="stage" else: shortcut = input stride = 2 - + stype="normal" bottleneck = self.bottleneck_res2net( - input, block_name, filters, filters_inner, strides_init, + input, block_name, filters, filters_inner, strides_init, stype ) output = self._batch_norm_add_relu(bottleneck, shortcut, block_name + "_branch2c", last=True) @@ -202,7 +212,6 @@ def residual_block(self, input, block_name, filters, filters_inner, strides_init def residual_stage(self, input, stage_name, counts, filters, filters_inner, stride_init=2): output = input - stype = "stage" for i in range(counts): # print("ResNet body resnet_conv_x_body >> residual_stage i:", i, "input:", output.shape) block_name = "%s_%d" % (stage_name, i) From a097f218fdd28f5e8b71992dbfba2cf17cac8047 Mon Sep 17 00:00:00 2001 From: Flowingsun007 Date: Tue, 27 Oct 2020 12:11:23 +0800 Subject: [PATCH 3/9] remove useless line --- Classification/cnns/res2net_model.py | 68 ++++++++++------------------ 1 file changed, 23 insertions(+), 45 deletions(-) diff --git a/Classification/cnns/res2net_model.py b/Classification/cnns/res2net_model.py index 37bb543..c335e91 100644 --- a/Classification/cnns/res2net_model.py +++ b/Classification/cnns/res2net_model.py @@ -140,20 +140,16 @@ def conv2d_affine(self, input, name, filters, kernel_size, strides): return output def bottleneck_res2net(self, input, block_name, filters, filters_inner, stride, stype="normal"): - # width = int(math.floor(filters_inner * (self.baseWidth / 64.0))) - # self.conv1 = nn.Conv2d(inplanes, width * scale, kernel_size=1, bias=False) - # a = flow.slice(a, begin=[None, 0, None, None], size=[None, width * self.scale, None, None]) - a = self.conv2d_affine( input, block_name + "_branch2a", filters_inner, 1, 1) x = self._batch_norm_relu(a, block_name + "_branch2a") spx = [] + # x = flow.concat(inputs=[spx[0], spx[1], spx[2], spx[3]], axis=1) split_num = int(x.shape[1] / self.scale) for i in range(self.scale): split_tensor = flow.slice(x, begin=[None, i * split_num, None, None], size=[None, split_num, None, None]) spx.append(split_tensor) - # input = flow.concat(inputs=[spx[0], spx[1], spx[2], spx[3]], axis=1) for i in range(self.nums): if i == 0 or stype == 'stage': @@ -178,18 +174,6 @@ def bottleneck_res2net(self, input, block_name, filters, filters_inner, stride, return z - # def bottleneck_transformation(self, input, block_name, filters, filters_inner, strides): - # a = self.conv2d_affine( - # input, block_name + "_branch2a", filters_inner, 1, 1) - # a = self._batch_norm_relu(a, block_name + "_branch2a") - - # b = self.conv2d_affine( - # a, block_name + "_branch2b", filters_inner, 3, strides) - # b = self._batch_norm_relu(b, block_name + "_branch2b") - - # c = self.conv2d_affine(b, block_name + "_branch2c", filters, 1, 1) - # return c - def residual_block(self, input, block_name, filters, filters_inner, strides_init): if strides_init != 1 or block_name == "res2_0": shortcut = self.conv2d_affine( @@ -210,10 +194,10 @@ def residual_block(self, input, block_name, filters, filters_inner, strides_init output = self._batch_norm_add_relu(bottleneck, shortcut, block_name + "_branch2c", last=True) return output + def residual_stage(self, input, stage_name, counts, filters, filters_inner, stride_init=2): output = input for i in range(counts): - # print("ResNet body resnet_conv_x_body >> residual_stage i:", i, "input:", output.shape) block_name = "%s_%d" % (stage_name, i) output = self.residual_block( output, block_name, filters, filters_inner, stride_init if i == 0 else 1 @@ -223,7 +207,6 @@ def residual_stage(self, input, stage_name, counts, filters, filters_inner, stri def resnet_conv_x_body(self, input, resnet_blocks): output = input for i, (counts, filters, filters_inner) in enumerate(resnet_blocks): - # print("ResNet body resnet_conv_x_body i:", i, "input:", output.shape) stage_name = "res%d" % (i + 2) output = self.residual_stage( output, stage_name, counts, filters, filters_inner, 1 if i == 0 else 2 @@ -256,15 +239,11 @@ def res2net50(images, args, trainable=True, training=True): paddings = ((0, 0), (0, 1), (0, 0), (0, 0)) images = flow.pad(images, paddings=paddings) with flow.scope.namespace("Resnet"): - #print("ResNet stem input ", images.shape) stem = builder.resnet_stem(images) - #print("ResNet body input ", stem.shape) body = builder.resnet_conv_x_body(stem, resnet_blocks) - #print("ResNet body output ", body.shape) pool5 = flow.nn.avg_pool2d( body, ksize=7, strides=1, padding="VALID", data_format=builder.data_format, name="pool5", ) - #print("ResNet body-pool output ", pool5.shape) fc1001 = flow.layers.dense( flow.reshape(pool5, (pool5.shape[0], -1)), units=1000, @@ -276,7 +255,6 @@ def res2net50(images, args, trainable=True, training=True): trainable=trainable, name="fc1001", ) - # print("ResNet body-pool-fc output ", fc1001.shape) return fc1001 @@ -315,24 +293,24 @@ def res2net18(images, args, trainable=True, training=True): return fc1001 -# import numpy as np -# import config as configs -# import oneflow.typing as tp -# -# parser = configs.get_parser() -# args = parser.parse_args() -# -# -# @flow.global_function(type="predict") -# def test_job( -# images: tp.Numpy.Placeholder((32, 3, 224, 224), dtype=flow.float), -# labels: tp.Numpy.Placeholder((32,), dtype=flow.int32)) -> tp.Numpy: -# output = res2net50(images, args) -# # print("images.shape, labels.shape, output.shape:", images.shape, labels.shape, output.shape) -# return output -# -# -# if __name__ == '__main__': -# images = np.random.uniform(-10, 10, (32, 1, 224, 224)).astype(np.float32) -# labels = np.random.randint(-10, 10, (32,)).astype(np.int32) -# output = test_job(images, labels) +import numpy as np +import config as configs +import oneflow.typing as tp + +parser = configs.get_parser() +args = parser.parse_args() + + +@flow.global_function(type="predict") +def test_job( + images: tp.Numpy.Placeholder((32, 3, 224, 224), dtype=flow.float), + labels: tp.Numpy.Placeholder((32,), dtype=flow.int32)) -> tp.Numpy: + output = res2net50(images, args) + print("images.shape, labels.shape, output.shape:", images.shape, labels.shape, output.shape) + return output + + +if __name__ == '__main__': + images = np.random.uniform(-10, 10, (32, 1, 224, 224)).astype(np.float32) + labels = np.random.randint(-10, 10, (32,)).astype(np.int32) + output = test_job(images, labels) From a70ac72139477c6bc11ea672dbbdd87d78f326de Mon Sep 17 00:00:00 2001 From: Flowingsun007 Date: Tue, 27 Oct 2020 12:12:01 +0800 Subject: [PATCH 4/9] add res2net model for evaluate --- Classification/cnns/of_cnn_evaluate.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Classification/cnns/of_cnn_evaluate.py b/Classification/cnns/of_cnn_evaluate.py index 286f25b..239888b 100644 --- a/Classification/cnns/of_cnn_evaluate.py +++ b/Classification/cnns/of_cnn_evaluate.py @@ -30,6 +30,7 @@ import oneflow as flow import vgg_model import resnet_model +import res2net_model import resnext_model import alexnet_model import mobilenet_v2_model @@ -42,6 +43,7 @@ model_dict = { + "res2net50": res2net_model.res2net50, "resnet50": resnet_model.resnet50, "vgg": vgg_model.vgg16bn, "alexnet": alexnet_model.alexnet, From 532a606b26afa783abc9ce624ba4ddf8ef7e4ba7 Mon Sep 17 00:00:00 2001 From: Flowingsun007 Date: Tue, 27 Oct 2020 13:03:05 +0800 Subject: [PATCH 5/9] add res2net to cnns readme --- Classification/cnns/README.md | 40 +++++++++++++++++++++++++-- Classification/cnns/data/res2net.jpg | Bin 0 -> 99601 bytes 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 Classification/cnns/data/res2net.jpg diff --git a/Classification/cnns/README.md b/Classification/cnns/README.md index 3bd7aa2..01356b8 100644 --- a/Classification/cnns/README.md +++ b/Classification/cnns/README.md @@ -596,7 +596,43 @@ onnx_model = oneflow_to_onnx(InferenceNet, flow_weights_path, onnx_model_dir, ex 生成 ONNX 模型之后可以使用 ONNX Runtime 运行 ONNX 模型,以验证 OneFlow 模型和 ONNX 模型能够在相同的输入下产生相同的结果。相应的代码在 resnet\_to\_onnx.py 的 `check_equality`。 -#### 训练AlexNet + +## 训练 Res2Net50 +```shell +#Please change $DATA_ROOT this to your own data root. +python3 of_cnn_train_val.py \ + --train_data_dir=$DATA_ROOT/train \ + --train_data_part_num=256 \ + --val_data_dir=$DATA_ROOT/validation \ + --val_data_part_num=256 \ + --num_nodes=1 \ + --gpu_num_per_node=8 \ + --optimizer="sgd" \ + --momentum=0.875 \ + --lr_decay="cosine" \ + --label_smoothing=0.1 \ + --learning_rate=0.512 \ + --loss_print_every_n_iter=100 \ + --batch_size_per_device=64 \ + --val_batch_size_per_device=50 \ + --channel_last=False \ + --fuse_bn_relu=True \ + --fuse_bn_add_relu=True \ + --nccl_fusion_threshold_mb=16 \ + --nccl_fusion_max_ops=24 \ + --gpu_image_decoder=False \ + --num_epoch=100 \ + --model="res2net50" + +``` +Res2Net源于论文:[Res2Net: A New Multi-scale Backbone Architecture](https://arxiv.org/pdf/1904.01169.pdf),是基于ResNet网络改进的,多尺度的卷积神经网络,其和ResNet主要的不点在于 bottleneck处: +
+ +
+ +此结构称为Res2Net块,可以将Res2Net块插入经典CNN网络如:ResNet,ResNeXt,BigLittleNet和DLA中以提高准确率。Res2Net各型号的网络,基于ImageNet上的分类准确率已经超越了传统的ResNet,本仓库也提供了基于ImageNet训练的Res2Net预训练模型(Top1 acc:;Top5 acc:),更多模型参考官方[github预训练模型](https://github.com/Res2Net/Res2Net-PretrainedModels#pretrained-models)。 + +## 训练AlexNet ``` #Please change $DATA_ROOT this to your own data root. @@ -622,7 +658,7 @@ python3 of_cnn_train_val.py \ -#### 训练 VGG-16 +## 训练 VGG-16 ``` #Please change $DATA_ROOT this to your own data root. python3 cnn_benchmark/of_cnn_train_val.py \ diff --git a/Classification/cnns/data/res2net.jpg b/Classification/cnns/data/res2net.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e5a815df6efc49196b9be7438f9d0318f65eb1be GIT binary patch literal 99601 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

tq6H|V3|3kclK9>EGXO4|aq{YDJ{Brzp2( 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

;3o!eC@%rNv}LF$Bve%R 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

Uks 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

A=3cc@` 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 N-6HG;6E(jK{R>{Xy?y`y literal 0 HcmV?d00001 From 9ea241aa76aa92a5a32174d36d061e454e8cd09e Mon Sep 17 00:00:00 2001 From: Flowingsun007 Date: Tue, 27 Oct 2020 15:27:37 +0800 Subject: [PATCH 6/9] refine res2net model --- Classification/cnns/res2net_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classification/cnns/res2net_model.py b/Classification/cnns/res2net_model.py index c335e91..bd7bc0d 100644 --- a/Classification/cnns/res2net_model.py +++ b/Classification/cnns/res2net_model.py @@ -306,7 +306,7 @@ def test_job( images: tp.Numpy.Placeholder((32, 3, 224, 224), dtype=flow.float), labels: tp.Numpy.Placeholder((32,), dtype=flow.int32)) -> tp.Numpy: output = res2net50(images, args) - print("images.shape, labels.shape, output.shape:", images.shape, labels.shape, output.shape) + # print("images.shape, labels.shape, output.shape:", images.shape, labels.shape, output.shape) return output From d07dbe7bcda6219f3bb9680b390652369efa4dd9 Mon Sep 17 00:00:00 2001 From: Flowingsun007 Date: Tue, 27 Oct 2020 15:28:26 +0800 Subject: [PATCH 7/9] update description of res2net --- Classification/cnns/README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Classification/cnns/README.md b/Classification/cnns/README.md index 01356b8..6032308 100644 --- a/Classification/cnns/README.md +++ b/Classification/cnns/README.md @@ -568,8 +568,10 @@ Class: tiger, Panthera tigris; score: 0.8112028241157532 #### 如何生成 ONNX 模型 + **步骤一:指定模型路径** + 首先指定待转换的OneFlow模型路径,然后指定转换后的ONNX模型存放路径,例如示例中: ```python @@ -598,6 +600,14 @@ onnx_model = oneflow_to_onnx(InferenceNet, flow_weights_path, onnx_model_dir, ex ## 训练 Res2Net50 +Res2Net源于论文:[Res2Net: A New Multi-scale Backbone Architecture](https://arxiv.org/pdf/1904.01169.pdf),是基于ResNet网络改进的,多尺度的卷积神经网络,其和ResNet主要的不点在于 bottleneck处: + +

+ +
+ +此结构称为Res2Net块,可以将Res2Net块插入经典CNN网络如:ResNet,ResNeXt,BigLittleNet和DLA中以提高准确率。 +训练脚本如下: ```shell #Please change $DATA_ROOT this to your own data root. python3 of_cnn_train_val.py \ @@ -625,12 +635,8 @@ python3 of_cnn_train_val.py \ --model="res2net50" ``` -Res2Net源于论文:[Res2Net: A New Multi-scale Backbone Architecture](https://arxiv.org/pdf/1904.01169.pdf),是基于ResNet网络改进的,多尺度的卷积神经网络,其和ResNet主要的不点在于 bottleneck处: -
- -
-此结构称为Res2Net块,可以将Res2Net块插入经典CNN网络如:ResNet,ResNeXt,BigLittleNet和DLA中以提高准确率。Res2Net各型号的网络,基于ImageNet上的分类准确率已经超越了传统的ResNet,本仓库也提供了基于ImageNet训练的Res2Net预训练模型(Top1 acc:;Top5 acc:),更多模型参考官方[github预训练模型](https://github.com/Res2Net/Res2Net-PretrainedModels#pretrained-models)。 +我们使用了和ResNet50一致的训练参数,经过90epoch的训练后,Res2Net模型精度达到了:Top1 acc:77.36%,点此下载[模型]。(https://oneflow-public.oss-cn-beijing.aliyuncs.com/model_zoo/res2net50_v15_of_best_model_val_top1_77366.zip) ## 训练AlexNet From f7484d650e96c176d2d12f2bc955431c68c79a6d Mon Sep 17 00:00:00 2001 From: Flowingsun007 Date: Tue, 27 Oct 2020 15:37:27 +0800 Subject: [PATCH 8/9] refine readme --- Classification/cnns/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classification/cnns/README.md b/Classification/cnns/README.md index 6032308..fa29c3f 100644 --- a/Classification/cnns/README.md +++ b/Classification/cnns/README.md @@ -636,7 +636,7 @@ python3 of_cnn_train_val.py \ ``` -我们使用了和ResNet50一致的训练参数,经过90epoch的训练后,Res2Net模型精度达到了:Top1 acc:77.36%,点此下载[模型]。(https://oneflow-public.oss-cn-beijing.aliyuncs.com/model_zoo/res2net50_v15_of_best_model_val_top1_77366.zip) +我们使用了和ResNet50一致的训练参数,经过90epoch的训练后,Res2Net模型精度达到了:Top1 acc:77.36%,点此下载[模型](https://oneflow-public.oss-cn-beijing.aliyuncs.com/model_zoo/res2net50_v15_of_best_model_val_top1_77366.zip)。 ## 训练AlexNet From 3dc2a5289040ce564f12076ca6f664d93c7cf927 Mon Sep 17 00:00:00 2001 From: Flowingsun007 Date: Sun, 1 Nov 2020 22:27:42 +0800 Subject: [PATCH 9/9] upload res2net pretrained model with top1 accuracy of 77.852% --- Classification/cnns/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Classification/cnns/README.md b/Classification/cnns/README.md index fa29c3f..76b4b68 100644 --- a/Classification/cnns/README.md +++ b/Classification/cnns/README.md @@ -609,7 +609,7 @@ Res2Net源于论文:[Res2Net: A New Multi-scale Backbone Architecture](https:/ 此结构称为Res2Net块,可以将Res2Net块插入经典CNN网络如:ResNet,ResNeXt,BigLittleNet和DLA中以提高准确率。 训练脚本如下: ```shell -#Please change $DATA_ROOT this to your own data root. +#Please change $DATA_ROOT to your own data root. python3 of_cnn_train_val.py \ --train_data_dir=$DATA_ROOT/train \ --train_data_part_num=256 \ @@ -625,18 +625,18 @@ python3 of_cnn_train_val.py \ --loss_print_every_n_iter=100 \ --batch_size_per_device=64 \ --val_batch_size_per_device=50 \ + --use_fp16=True \ --channel_last=False \ --fuse_bn_relu=True \ --fuse_bn_add_relu=True \ - --nccl_fusion_threshold_mb=16 \ - --nccl_fusion_max_ops=24 \ + --nccl_fusion_threshold_mb=32 \ + --nccl_fusion_max_ops=48 \ --gpu_image_decoder=False \ - --num_epoch=100 \ + --num_epoch=100 \ --model="res2net50" - ``` -我们使用了和ResNet50一致的训练参数,经过90epoch的训练后,Res2Net模型精度达到了:Top1 acc:77.36%,点此下载[模型](https://oneflow-public.oss-cn-beijing.aliyuncs.com/model_zoo/res2net50_v15_of_best_model_val_top1_77366.zip)。 +我们使用了和ResNet50一致的训练参数,经过93epoch的训练后,Res2Net模型精度达到了:Top1 acc:77.852%,点此下载[模型](https://oneflow-public.oss-cn-beijing.aliyuncs.com/model_zoo/res2net50_of_best_model_val_top1_77852.zip)。 ## 训练AlexNet