From bf76102594c2f05b406c346ce42e19042aca5368 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 01:31:04 +0800 Subject: [PATCH 01/20] new deeplabv3 --- model_zoo/deeplabv3/readme.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 model_zoo/deeplabv3/readme.txt diff --git a/model_zoo/deeplabv3/readme.txt b/model_zoo/deeplabv3/readme.txt new file mode 100644 index 0000000000..e69de29bb2 From ae042594420e705dbe57c4eb9de7592ab0db233d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 01:35:59 +0800 Subject: [PATCH 02/20] new branch --- model_zoo/deeplabv3/scripts/mock | 0 model_zoo/deeplabv3/src/mock | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 model_zoo/deeplabv3/scripts/mock create mode 100644 model_zoo/deeplabv3/src/mock diff --git a/model_zoo/deeplabv3/scripts/mock b/model_zoo/deeplabv3/scripts/mock new file mode 100644 index 0000000000..e69de29bb2 diff --git a/model_zoo/deeplabv3/src/mock b/model_zoo/deeplabv3/src/mock new file mode 100644 index 0000000000..e69de29bb2 From a728b328e13facb589c9261418a09dc2e367176e Mon Sep 17 00:00:00 2001 From: yangyongjie Date: Fri, 29 May 2020 01:40:04 +0800 Subject: [PATCH 03/20] add dataset --- model_zoo/deeplabv3/src/__init__.py | 14 + model_zoo/deeplabv3/src/adapter.py | 67 +++ model_zoo/deeplabv3/src/custom_transforms.py | 148 ++++++ model_zoo/deeplabv3/src/deeplabv3.py | 457 +++++++++++++++++++ model_zoo/deeplabv3/src/ei_datasest.py | 107 +++++ model_zoo/deeplabv3/src/md_dataset.py | 104 +++++ 6 files changed, 897 insertions(+) create mode 100644 model_zoo/deeplabv3/src/__init__.py create mode 100644 model_zoo/deeplabv3/src/adapter.py create mode 100644 model_zoo/deeplabv3/src/custom_transforms.py create mode 100644 model_zoo/deeplabv3/src/deeplabv3.py create mode 100644 model_zoo/deeplabv3/src/ei_datasest.py create mode 100644 model_zoo/deeplabv3/src/md_dataset.py diff --git a/model_zoo/deeplabv3/src/__init__.py b/model_zoo/deeplabv3/src/__init__.py new file mode 100644 index 0000000000..301ef9dcb7 --- /dev/null +++ b/model_zoo/deeplabv3/src/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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 +# +# httpwww.apache.orglicensesLICENSE-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. +# ============================================================================ diff --git a/model_zoo/deeplabv3/src/adapter.py b/model_zoo/deeplabv3/src/adapter.py new file mode 100644 index 0000000000..37173ebf48 --- /dev/null +++ b/model_zoo/deeplabv3/src/adapter.py @@ -0,0 +1,67 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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 +# +# httpwww.apache.orglicensesLICENSE-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. +# ============================================================================ +"""Adapter dataset.""" +import fnmatch +import io +import os + +import numpy as np +from PIL import Image + +from ..utils import file_io + + +def get_raw_samples(data_url): + """ + Get dataset from raw data. + + Args: + data_url (str): Dataset path. + + Returns: + list, a file list. + """ + def _list_files(dir_path, pattern): + full_files = [] + _, _, files = next(file_io.walk(dir_path)) + for f in files: + if fnmatch.fnmatch(f.lower(), pattern.lower()): + full_files.append(os.path.join(dir_path, f)) + return full_files + + img_files = _list_files(os.path.join(data_url, "Images"), "*.jpg") + seg_files = _list_files(os.path.join(data_url, "SegmentationClassRaw"), "*.png") + + files = [] + for img_file in img_files: + _, file_name = os.path.split(img_file) + name, _ = os.path.splitext(file_name) + seg_file = os.path.join(data_url, "SegmentationClassRaw", ".".join([name, "png"])) + if seg_file in seg_files: + files.append([img_file, seg_file]) + return files + + +def read_image(img_path): + """ + Read image from file. + + Args: + img_path (str): image path. + """ + img = file_io.read(img_path.strip(), binary=True) + data = io.BytesIO(img) + img = Image.open(data) + return np.array(img) diff --git a/model_zoo/deeplabv3/src/custom_transforms.py b/model_zoo/deeplabv3/src/custom_transforms.py new file mode 100644 index 0000000000..ddf544ea72 --- /dev/null +++ b/model_zoo/deeplabv3/src/custom_transforms.py @@ -0,0 +1,148 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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 +# +# httpwww.apache.orglicensesLICENSE-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. +# ============================================================================ +"""Random process dataset.""" +import random + +import numpy as np +from PIL import Image, ImageOps, ImageFilter + + +class Normalize(object): + """Normalize a tensor image with mean and standard deviation. + Args: + mean (tuple): means for each channel. + std (tuple): standard deviations for each channel. + """ + + def __init__(self, mean=(0., 0., 0.), std=(1., 1., 1.)): + self.mean = mean + self.std = std + + def __call__(self, img, mask): + img = np.array(img).astype(np.float32) + mask = np.array(mask).astype(np.float32) + + return img, mask + + +class RandomHorizontalFlip(object): + """Randomly decide whether to horizontal flip.""" + def __call__(self, img, mask): + if random.random() < 0.5: + img = img.transpose(Image.FLIP_LEFT_RIGHT) + mask = mask.transpose(Image.FLIP_LEFT_RIGHT) + + return img, mask + + +class RandomRotate(object): + """ + Randomly decide whether to rotate. + + Args: + degree (float): The degree of rotate. + """ + def __init__(self, degree): + self.degree = degree + + def __call__(self, img, mask): + rotate_degree = random.uniform(-1 * self.degree, self.degree) + img = img.rotate(rotate_degree, Image.BILINEAR) + mask = mask.rotate(rotate_degree, Image.NEAREST) + + return img, mask + + +class RandomGaussianBlur(object): + """Randomly decide whether to filter image with gaussian blur.""" + def __call__(self, img, mask): + if random.random() < 0.5: + img = img.filter(ImageFilter.GaussianBlur( + radius=random.random())) + + return img, mask + + +class RandomScaleCrop(object): + """Randomly decide whether to scale and crop image.""" + def __init__(self, base_size, crop_size, fill=0): + self.base_size = base_size + self.crop_size = crop_size + self.fill = fill + + def __call__(self, img, mask): + # random scale (short edge) + short_size = random.randint(int(self.base_size * 0.5), int(self.base_size * 2.0)) + w, h = img.size + if h > w: + ow = short_size + oh = int(1.0 * h * ow / w) + else: + oh = short_size + ow = int(1.0 * w * oh / h) + img = img.resize((ow, oh), Image.BILINEAR) + mask = mask.resize((ow, oh), Image.NEAREST) + # pad crop + if short_size < self.crop_size: + padh = self.crop_size - oh if oh < self.crop_size else 0 + padw = self.crop_size - ow if ow < self.crop_size else 0 + img = ImageOps.expand(img, border=(0, 0, padw, padh), fill=0) + mask = ImageOps.expand(mask, border=(0, 0, padw, padh), fill=self.fill) + # random crop crop_size + w, h = img.size + x1 = random.randint(0, w - self.crop_size) + y1 = random.randint(0, h - self.crop_size) + img = img.crop((x1, y1, x1 + self.crop_size, y1 + self.crop_size)) + mask = mask.crop((x1, y1, x1 + self.crop_size, y1 + self.crop_size)) + + return img, mask + + +class FixScaleCrop(object): + """Scale and crop image with fixing size.""" + def __init__(self, crop_size): + self.crop_size = crop_size + + def __call__(self, img, mask): + w, h = img.size + if w > h: + oh = self.crop_size + ow = int(1.0 * w * oh / h) + else: + ow = self.crop_size + oh = int(1.0 * h * ow / w) + img = img.resize((ow, oh), Image.BILINEAR) + mask = mask.resize((ow, oh), Image.NEAREST) + # center crop + w, h = img.size + x1 = int(round((w - self.crop_size) / 2.)) + y1 = int(round((h - self.crop_size) / 2.)) + img = img.crop((x1, y1, x1 + self.crop_size, y1 + self.crop_size)) + mask = mask.crop((x1, y1, x1 + self.crop_size, y1 + self.crop_size)) + + return img, mask + + +class FixedResize(object): + """Resize image with fixing size.""" + def __init__(self, size): + self.size = (size, size) + + def __call__(self, img, mask): + assert img.size == mask.size + + img = img.resize(self.size, Image.BILINEAR) + mask = mask.resize(self.size, Image.NEAREST) + return img, mask diff --git a/model_zoo/deeplabv3/src/deeplabv3.py b/model_zoo/deeplabv3/src/deeplabv3.py new file mode 100644 index 0000000000..75e2a87adc --- /dev/null +++ b/model_zoo/deeplabv3/src/deeplabv3.py @@ -0,0 +1,457 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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 +# +# httpwww.apache.orglicensesLICENSE-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. +# ============================================================================ +"""DeepLabv3.""" + +import numpy as np +import mindspore.nn as nn +from mindspore.ops import operations as P +from .backbone.resnet_deeplab import _conv_bn_relu, resnet50_dl, _deep_conv_bn_relu, \ + DepthwiseConv2dNative, SpaceToBatch, BatchToSpace + + +class ASPPSampleBlock(nn.Cell): + """ASPP sample block.""" + def __init__(self, feature_shape, scale_size,output_stride): + super(ASPPSampleBlock, self).__init__() + sample_h = (feature_shape[0] * scale_size + 1) / output_stride + 1 + sample_w = (feature_shape[1] * scale_size + 1) / output_stride + 1 + self.sample = P.ResizeBilinear((int(sample_h),int(sample_w)),align_corners=True) + + def construct(self, x): + return self.sample(x) + + +class ASPP(nn.Cell): + """ + ASPP model for DeepLabv3. + + Args: + channel (int): Input channel. + depth (int): Output channel. + feature_shape (list): The shape of feature,[h,w]. + scale_sizes (list): Input scales for multi-scale feature extraction. + atrous_rates (list): Atrous rates for atrous spatial pyramid pooling. + output_stride (int): 'The ratio of input to output spatial resolution.' + fine_tune_batch_norm (bool): 'Fine tune the batch norm parameters or not' + + Returns: + Tensor, output tensor. + + Examples: + >>> ASPP(channel=2048,256,[14,14],[1],[6],16) + """ + def __init__(self, channel, depth, feature_shape, scale_sizes, + atrous_rates, output_stride, fine_tune_batch_norm=False): + super(ASPP, self).__init__() + self.aspp0 = _conv_bn_relu(channel, + depth, + ksize=1, + stride=1, + use_batch_statistics=fine_tune_batch_norm) + self.atrous_rates = [] + if atrous_rates is not None: + self.atrous_rates = atrous_rates + self.aspp_pointwise = _conv_bn_relu(channel, + depth, + ksize=1, + stride=1, + use_batch_statistics=fine_tune_batch_norm) + self.aspp_depth_depthwiseconv = DepthwiseConv2dNative(channel, + channel_multiplier=1, + kernel_size=3, + stride=1, + dilation=1, + pad_mode="valid") + self.aspp_depth_bn = nn.BatchNorm2d(1 * channel, use_batch_statistics=fine_tune_batch_norm) + self.aspp_depth_relu = nn.ReLU() + self.aspp_depths = [] + self.aspp_depth_spacetobatchs = [] + self.aspp_depth_batchtospaces = [] + + for scale_size in scale_sizes: + aspp_scale_depth_size = np.ceil((feature_shape[0]*scale_size)/16) + if atrous_rates is None: + break + for i in range(len(atrous_rates)): + padding = 0 + for j in range(100): + padded_size = atrous_rates[i] * j + if padded_size >= aspp_scale_depth_size + 2 * atrous_rates[i]: + padding = padded_size - aspp_scale_depth_size - 2 * atrous_rates[i] + break + paddings = [[atrous_rates[i], atrous_rates[i] + int(padding)], + [atrous_rates[i], atrous_rates[i] + int(padding)]] + self.aspp_depth_spacetobatch = SpaceToBatch(atrous_rates[i],paddings) + self.aspp_depth_spacetobatchs.append(self.aspp_depth_spacetobatch) + crops =[[0, int(padding)], [0, int(padding)]] + self.aspp_depth_batchtospace = BatchToSpace(atrous_rates[i],crops) + self.aspp_depth_batchtospaces.append(self.aspp_depth_batchtospace) + self.aspp_depths = nn.CellList(self.aspp_depths) + self.aspp_depth_spacetobatchs = nn.CellList(self.aspp_depth_spacetobatchs) + self.aspp_depth_batchtospaces = nn.CellList(self.aspp_depth_batchtospaces) + + self.global_pooling = nn.AvgPool2d(kernel_size=(int(feature_shape[0]),int(feature_shape[1]))) + self.global_poolings = [] + for scale_size in scale_sizes: + pooling_h = np.ceil((feature_shape[0]*scale_size)/output_stride) + pooling_w = np.ceil((feature_shape[0]*scale_size)/output_stride) + self.global_poolings.append(nn.AvgPool2d(kernel_size=(int(pooling_h), int(pooling_w)))) + self.global_poolings = nn.CellList(self.global_poolings) + self.conv_bn = _conv_bn_relu(channel, + depth, + ksize=1, + stride=1, + use_batch_statistics=fine_tune_batch_norm) + self.samples = [] + for scale_size in scale_sizes: + self.samples.append(ASPPSampleBlock(feature_shape,scale_size,output_stride)) + self.samples = nn.CellList(self.samples) + self.feature_shape = feature_shape + self.concat = P.Concat(axis=1) + + def construct(self, x, scale_index=0): + aspp0 = self.aspp0(x) + aspp1 = self.global_poolings[scale_index](x) + aspp1 = self.conv_bn(aspp1) + aspp1 = self.samples[scale_index](aspp1) + output = self.concat((aspp1,aspp0)) + + for i in range(len(self.atrous_rates)): + aspp_i = self.aspp_depth_spacetobatchs[i + scale_index * len(self.atrous_rates)](x) + aspp_i = self.aspp_depth_depthwiseconv(aspp_i) + aspp_i = self.aspp_depth_batchtospaces[i + scale_index * len(self.atrous_rates)](aspp_i) + aspp_i = self.aspp_depth_bn(aspp_i) + aspp_i = self.aspp_depth_relu(aspp_i) + aspp_i = self.aspp_pointwise(aspp_i) + output = self.concat((output,aspp_i)) + return output + + +class DecoderSampleBlock(nn.Cell): + """Decoder sample block.""" + def __init__(self,feature_shape,scale_size=1.0,decoder_output_stride=4): + super(DecoderSampleBlock, self).__init__() + sample_h = (feature_shape[0] * scale_size + 1) / decoder_output_stride + 1 + sample_w = (feature_shape[1] * scale_size + 1) / decoder_output_stride + 1 + self.sample = P.ResizeBilinear((int(sample_h), int(sample_w)), align_corners=True) + + def construct(self, x): + return self.sample(x) + + +class Decoder(nn.Cell): + """ + Decode module for DeepLabv3. + Args: + low_level_channel (int): Low level input channel + channel (int): Input channel. + depth (int): Output channel. + feature_shape (list): 'Input image shape, [N,C,H,W].' + scale_sizes (list): 'Input scales for multi-scale feature extraction.' + decoder_output_stride (int): 'The ratio of input to output spatial resolution' + fine_tune_batch_norm (bool): 'Fine tune the batch norm parameters or not' + Returns: + Tensor, output tensor. + Examples: + >>> Decoder(256, 100, [56,56]) + """ + def __init__(self, + low_level_channel, + channel, + depth, + feature_shape, + scale_sizes, + decoder_output_stride, + fine_tune_batch_norm): + super(Decoder, self).__init__() + self.feature_projection = _conv_bn_relu(low_level_channel, 48, ksize=1, stride=1, + pad_mode="same", use_batch_statistics=fine_tune_batch_norm) + self.decoder_depth0 = _deep_conv_bn_relu(channel + 48, + channel_multiplier=1, + ksize=3, + stride=1, + pad_mode="same", + dilation=1, + use_batch_statistics=fine_tune_batch_norm) + self.decoder_pointwise0 = _conv_bn_relu(channel + 48, + depth, + ksize=1, + stride=1, + use_batch_statistics=fine_tune_batch_norm) + self.decoder_depth1 = _deep_conv_bn_relu(depth, + channel_multiplier=1, + ksize=3, + stride=1, + pad_mode="same", + dilation=1, + use_batch_statistics=fine_tune_batch_norm) + self.decoder_pointwise1 = _conv_bn_relu(depth, + depth, + ksize=1, + stride=1, + use_batch_statistics=fine_tune_batch_norm) + self.depth = depth + self.concat = P.Concat(axis=1) + self.samples = [] + for scale_size in scale_sizes: + self.samples.append(DecoderSampleBlock(feature_shape,scale_size,decoder_output_stride)) + self.samples = nn.CellList(self.samples) + + def construct(self, x, low_level_feature, scale_index): + low_level_feature = self.feature_projection(low_level_feature) + low_level_feature = self.samples[scale_index](low_level_feature) + x = self.samples[scale_index](x) + output = self.concat((x, low_level_feature)) + output = self.decoder_depth0(output) + output = self.decoder_pointwise0(output) + output = self.decoder_depth1(output) + output = self.decoder_pointwise1(output) + return output + + +class SingleDeepLabV3(nn.Cell): + """ + DeepLabv3 Network. + Args: + num_classes (int): Class number. + feature_shape (list): Input image shape, [N,C,H,W]. + backbone (Cell): Backbone Network. + channel (int): Resnet output channel. + depth (int): ASPP block depth. + scale_sizes (list): Input scales for multi-scale feature extraction. + atrous_rates (list): Atrous rates for atrous spatial pyramid pooling. + decoder_output_stride (int): 'The ratio of input to output spatial resolution' + output_stride (int): 'The ratio of input to output spatial resolution.' + fine_tune_batch_norm (bool): 'Fine tune the batch norm parameters or not' + Returns: + Tensor, output tensor. + Examples: + >>> SingleDeepLabV3(num_classes=10, + >>> feature_shape=[1,3,224,224], + >>> backbone=resnet50_dl(), + >>> channel=2048, + >>> depth=256) + >>> scale_sizes=[1.0]) + >>> atrous_rates=[6]) + >>> decoder_output_stride=4) + >>> output_stride=16) + """ + + def __init__(self, + num_classes, + feature_shape, + backbone, + channel, + depth, + scale_sizes, + atrous_rates, + decoder_output_stride, + output_stride, + fine_tune_batch_norm=False): + super(SingleDeepLabV3, self).__init__() + self.num_classes = num_classes + self.channel = channel + self.depth = depth + self.scale_sizes = [] + for scale_size in np.sort(scale_sizes): + self.scale_sizes.append(scale_size) + self.net = backbone + self.aspp = ASPP(channel=self.channel, + depth=self.depth, + feature_shape=[feature_shape[2], + feature_shape[3]], + scale_sizes=self.scale_sizes, + atrous_rates=atrous_rates, + output_stride=output_stride, + fine_tune_batch_norm=fine_tune_batch_norm) + self.aspp.add_flags(loop_can_unroll=True) + atrous_rates_len = 0 + if atrous_rates is not None: + atrous_rates_len = len(atrous_rates) + self.fc1 = _conv_bn_relu(depth * (2 + atrous_rates_len), depth, + ksize=1, + stride=1, + use_batch_statistics=fine_tune_batch_norm) + self.fc2 = nn.Conv2d(depth, + num_classes, + kernel_size=1, + stride=1, + has_bias=True) + self.upsample = P.ResizeBilinear((int(feature_shape[2]), + int(feature_shape[3])), + align_corners=True) + self.samples = [] + for scale_size in self.scale_sizes: + self.samples.append(SampleBlock(feature_shape, scale_size)) + self.samples = nn.CellList(self.samples) + self.feature_shape = [float(feature_shape[0]), float(feature_shape[1]), float(feature_shape[2]), + float(feature_shape[3])] + + self.pad = P.Pad(((0, 0), (0, 0), (1, 1), (1, 1))) + self.dropout = nn.Dropout(keep_prob=0.9) + self.shape = P.Shape() + self.decoder_output_stride = decoder_output_stride + if decoder_output_stride is not None: + self.decoder = Decoder(low_level_channel=depth, + channel=depth, + depth=depth, + feature_shape=[feature_shape[2], + feature_shape[3]], + scale_sizes=self.scale_sizes, + decoder_output_stride=decoder_output_stride, + fine_tune_batch_norm=fine_tune_batch_norm) + + def construct(self, x, scale_index=0): + x = (2.0 / 255.0) * x - 1.0 + x = self.pad(x) + low_level_feature, feature_map = self.net(x) + for scale_size in self.scale_sizes: + if scale_size * self.feature_shape[2] + 1.0 >= self.shape(x)[2] - 2: + output = self.aspp(feature_map, scale_index) + output = self.fc1(output) + if self.decoder_output_stride is not None: + output = self.decoder(output, low_level_feature, scale_index) + output = self.fc2(output) + output = self.samples[scale_index](output) + return output + scale_index += 1 + return feature_map + + +class SampleBlock(nn.Cell): + """Sample block.""" + def __init__(self, + feature_shape, + scale_size=1.0): + super(SampleBlock, self).__init__() + sample_h = np.ceil(float(feature_shape[2]) * scale_size) + sample_w = np.ceil(float(feature_shape[3]) * scale_size) + self.sample = P.ResizeBilinear((int(sample_h), int(sample_w)), align_corners=True) + + def construct(self, x): + return self.sample(x) + + +class DeepLabV3(nn.Cell): + """DeepLabV3 model.""" + def __init__(self, num_classes, feature_shape, backbone, channel, depth, infer_scale_sizes, atrous_rates, + decoder_output_stride, output_stride, fine_tune_batch_norm, image_pyramid): + super(DeepLabV3, self).__init__() + self.infer_scale_sizes = [] + if infer_scale_sizes is not None: + self.infer_scale_sizes = infer_scale_sizes + + self.infer_scale_sizes = infer_scale_sizes + if image_pyramid is None: + image_pyramid = [1.0] + + self.image_pyramid = image_pyramid + scale_sizes = [] + for i in range(len(image_pyramid)): + scale_sizes.append(image_pyramid[i]) + for i in range(len(infer_scale_sizes)): + scale_sizes.append(infer_scale_sizes[i]) + self.samples = [] + for scale_size in scale_sizes: + self.samples.append(SampleBlock(feature_shape, scale_size)) + self.samples = nn.CellList(self.samples) + self.deeplabv3 = SingleDeepLabV3(num_classes=num_classes, + feature_shape=feature_shape, + backbone=resnet50_dl(fine_tune_batch_norm), + channel=channel, + depth=depth, + scale_sizes=scale_sizes, + atrous_rates=atrous_rates, + decoder_output_stride=decoder_output_stride, + output_stride=output_stride, + fine_tune_batch_norm=fine_tune_batch_norm) + self.softmax = P.Softmax(axis=1) + self.concat = P.Concat(axis=2) + self.expand_dims = P.ExpandDims() + self.reduce_mean = P.ReduceMean() + self.sample_common = P.ResizeBilinear((int(feature_shape[2]), + int(feature_shape[3])), + align_corners=True) + + def construct(self, x): + logits = () + if self.training: + if len(self.image_pyramid) >= 1: + if self.image_pyramid[0] == 1: + logits = self.deeplabv3(x) + else: + x1 = self.samples[0](x) + logits = self.deeplabv3(x1) + logits = self.sample_common(logits) + logits = self.expand_dims(logits, 2) + for i in range(len(self.image_pyramid) - 1): + x_i = self.samples[i + 1](x) + logits_i = self.deeplabv3(x_i) + logits_i = self.sample_common(logits_i) + logits_i = self.expand_dims(logits_i, 2) + logits = self.concat((logits, logits_i)) + logits = self.reduce_mean(logits, 2) + return logits + if len(self.infer_scale_sizes) >= 1: + infer_index = len(self.image_pyramid) + x1 = self.samples[infer_index](x) + logits = self.deeplabv3(x1) + logits = self.sample_common(logits) + logits = self.softmax(logits) + logits = self.expand_dims(logits, 2) + for i in range(len(self.infer_scale_sizes) - 1): + x_i = self.samples[i + 1 + infer_index](x) + logits_i = self.deeplabv3(x_i) + logits_i = self.sample_common(logits_i) + logits_i = self.softmax(logits_i) + logits_i = self.expand_dims(logits_i, 2) + logits = self.concat((logits, logits_i)) + logits = self.reduce_mean(logits, 2) + return logits + + +def deeplabv3_resnet50(num_classes, feature_shape, image_pyramid, + infer_scale_sizes, atrous_rates=None, decoder_output_stride=None, + output_stride=16, fine_tune_batch_norm=False): + """ + ResNet50 based DeepLabv3 network. + + Args: + num_classes (int): Class number. + feature_shape (list): Input image shape, [N,C,H,W]. + image_pyramid (list): Input scales for multi-scale feature extraction. + atrous_rates (list): Atrous rates for atrous spatial pyramid pooling. + infer_scale_sizes (list): 'The scales to resize images for inference. + decoder_output_stride (int): 'The ratio of input to output spatial resolution' + output_stride (int): 'The ratio of input to output spatial resolution.' + fine_tune_batch_norm (bool): 'Fine tune the batch norm parameters or not' + + Returns: + Cell, cell instance of ResNet50 based DeepLabv3 neural network. + + Examples: + >>> deeplabv3_resnet50(100, [1,3,224,224],[1.0],[1.0]) + """ + return DeepLabV3(num_classes=num_classes, + feature_shape=feature_shape, + backbone=resnet50_dl(fine_tune_batch_norm), + channel=2048, + depth=256, + infer_scale_sizes=infer_scale_sizes, + atrous_rates=atrous_rates, + decoder_output_stride=decoder_output_stride, + output_stride=output_stride, + fine_tune_batch_norm=fine_tune_batch_norm, + image_pyramid=image_pyramid) \ No newline at end of file diff --git a/model_zoo/deeplabv3/src/ei_datasest.py b/model_zoo/deeplabv3/src/ei_datasest.py new file mode 100644 index 0000000000..b2a20999d6 --- /dev/null +++ b/model_zoo/deeplabv3/src/ei_datasest.py @@ -0,0 +1,107 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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 +# +# httpwww.apache.orglicensesLICENSE-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. +# ============================================================================ +"""Process Dataset.""" +import abc +import os +import time + +from .utils.adapter import get_manifest_samples, get_raw_samples, read_image + + +class BaseDataset(object): + """ + Create dataset. + + Args: + data_url (str): The path of data. + usage (str): Whether to use train or eval (default='train'). + + Returns: + Dataset. + """ + def __init__(self, data_url, usage): + self.data_url = data_url + self.usage = usage + self.cur_index = 0 + self.samples = [] + _s_time = time.time() + self._load_samples() + _e_time = time.time() + print(f"load samples success~, time cost = {_e_time - _s_time}") + + def __getitem__(self, item): + sample = self.samples[item] + return self._next_data(sample) + + def __len__(self): + return len(self.samples) + + @staticmethod + def _next_data(sample): + image_path = sample[0] + mask_image_path = sample[1] + + image = read_image(image_path) + mask_image = read_image(mask_image_path) + return [image, mask_image] + + @abc.abstractmethod + def _load_samples(self): + pass + + +class HwVocManifestDataset(BaseDataset): + """ + Create dataset with manifest data. + + Args: + data_url (str): The path of data. + usage (str): Whether to use train or eval (default='train'). + + Returns: + Dataset. + """ + + def __init__(self, data_url, usage="train"): + super().__init__(data_url, usage) + + def _load_samples(self): + try: + self.samples = get_manifest_samples(self.data_url, self.usage) + except Exception as e: + print("load HwVocManifestDataset samples failed!!!") + raise e + + +class HwVocRawDataset(BaseDataset): + """ + Create dataset with raw data. + + Args: + data_url (str): The path of data. + usage (str): Whether to use train or eval (default='train'). + + Returns: + Dataset. + """ + def __init__(self, data_url, usage="train"): + super().__init__(data_url, usage) + + def _load_samples(self): + try: + self.samples = get_raw_samples(os.path.join(self.data_url, self.usage)) + except Exception as e: + print("load HwVocRawDataset failed!!!") + raise e diff --git a/model_zoo/deeplabv3/src/md_dataset.py b/model_zoo/deeplabv3/src/md_dataset.py new file mode 100644 index 0000000000..b18d94cc0d --- /dev/null +++ b/model_zoo/deeplabv3/src/md_dataset.py @@ -0,0 +1,104 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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 +# +# httpwww.apache.orglicensesLICENSE-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. +# ============================================================================ +"""Dataset module.""" +from PIL import Image +import mindspore.dataset as de +import mindspore.dataset.transforms.vision.c_transforms as C + +from .ei_dataset import HwVocManifestDataset, HwVocRawDataset +from .utils import custom_transforms as tr + + +class DataTransform(object): + """Transform dataset for DeepLabV3.""" + + def __init__(self, args, usage): + self.args = args + self.usage = usage + + def __call__(self, image, label): + if "train" == self.usage: + return self._train(image, label) + elif "eval" == self.usage: + return self._eval(image, label) + + def _train(self, image, label): + image = Image.fromarray(image) + label = Image.fromarray(label) + + rsc_tr = tr.RandomScaleCrop(base_size=self.args.base_size, crop_size=self.args.crop_size) + image, label = rsc_tr(image, label) + + rhf_tr = tr.RandomHorizontalFlip() + image, label = rhf_tr(image, label) + + nor_tr = tr.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)) + image, label = nor_tr(image, label) + + return image, label + + def _eval(self, image, label): + image = Image.fromarray(image) + label = Image.fromarray(label) + + fsc_tr = tr.FixScaleCrop(crop_size=self.args.crop_size) + image, label = fsc_tr(image, label) + + nor_tr = tr.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)) + image, label = nor_tr(image, label) + + return image, label + + +def create_dataset(args, data_url, epoch_num=1, batch_size=1, usage="train"): + """ + Create Dataset for DeepLabV3. + + Args: + args (dict): Train parameters. + data_url (str): Dataset path. + epoch_num (int): Epoch of dataset (default=1). + batch_size (int): Batch size of dataset (default=1). + usage (str): Whether is use to train or eval (default='train'). + + Returns: + Dataset. + """ + # create iter dataset + if data_url.endswith(".manifest"): + dataset = HwVocManifestDataset(data_url, usage=usage) + else: + dataset = HwVocRawDataset(data_url, usage=usage) + dataset_len = len(dataset) + + # wrapped with GeneratorDataset + dataset = de.GeneratorDataset(dataset, ["image", "label"], sampler=None) + dataset.set_dataset_size(dataset_len) + dataset = dataset.map(input_columns=["image", "label"], operations=DataTransform(args, usage=usage)) + + channelswap_op = C.HWC2CHW() + dataset = dataset.map(input_columns="image", operations=channelswap_op) + + # 1464 samples / batch_size 8 = 183 batches + # epoch_num is num of steps + # 3658 steps / 183 = 20 epochs + if usage == "train": + dataset = dataset.shuffle(1464) + dataset = dataset.batch(batch_size, drop_remainder=(usage == usage)) + dataset = dataset.repeat(count=epoch_num) + dataset.map_model = 4 + + dataset.__loop_size__ = 1 + return dataset From 8aae0a18c7ef1df1ddfa81bebc82fbdd1f807019 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 02:08:42 +0800 Subject: [PATCH 04/20] add scripts --- .../scripts/run_distribute_pretrain.sh | 66 +++++++++++++++++++ model_zoo/deeplabv3/scripts/run_eval.sh | 31 +++++++++ .../deeplabv3/scripts/run_standalone_train.sh | 37 +++++++++++ 3 files changed, 134 insertions(+) create mode 100644 model_zoo/deeplabv3/scripts/run_distribute_pretrain.sh create mode 100644 model_zoo/deeplabv3/scripts/run_eval.sh create mode 100644 model_zoo/deeplabv3/scripts/run_standalone_train.sh diff --git a/model_zoo/deeplabv3/scripts/run_distribute_pretrain.sh b/model_zoo/deeplabv3/scripts/run_distribute_pretrain.sh new file mode 100644 index 0000000000..de6f508051 --- /dev/null +++ b/model_zoo/deeplabv3/scripts/run_distribute_pretrain.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ + +echo "==============================================================================================================" +echo "Please run the scipt as: " +echo "bash run_distribute_pretrain.sh DEVICE_NUM EPOCH_SIZE DATA_DIR MINDSPORE_HCCL_CONFIG_PATH" +echo "for example: bash run_distribute_train.sh 8 40 /path/zh-wiki/ /path/hccl.json" +echo "It is better to use absolute path." +echo "==============================================================================================================" + +EPOCH_SIZE=$2 +DATA_DIR=$3 + +export MINDSPORE_HCCL_CONFIG_PATH=$4 +export RANK_TABLE_FILE=$4 +export RANK_SIZE=$1 +cores=`cat /proc/cpuinfo|grep "processor" |wc -l` +echo "the number of logical core" $cores +avg_core_per_rank=`expr $cores \/ $RANK_SIZE` +core_gap=`expr $avg_core_per_rank \- 1` +echo "avg_core_per_rank" $avg_core_per_rank +echo "core_gap" $core_gap +for((i=0;i env.log + taskset -c $cmdopt python ../train.py \ + --distribute="true" \ + --epoch_size=$EPOCH_SIZE \ + --device_id=$DEVICE_ID \ + --enable_save_ckpt="true" \ + --checkpoint_url="/store1/deeplabv3/deeplabv3_split_url/train/checkpoint/CKP-12_732.ckpt" \ + --save_checkpoint_steps=10000 \ + --save_checkpoint_num=1 \ + --data_url=$DATA_DIR > log.txt 2>&1 & + cd ../ +done \ No newline at end of file diff --git a/model_zoo/deeplabv3/scripts/run_eval.sh b/model_zoo/deeplabv3/scripts/run_eval.sh new file mode 100644 index 0000000000..a3596e0be3 --- /dev/null +++ b/model_zoo/deeplabv3/scripts/run_eval.sh @@ -0,0 +1,31 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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 +# +# httpwww.apache.orglicensesLICENSE-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. +# ============================================================================ +echo "==============================================================================================================" +echo "Please run the scipt as: " +echo "bash run_eval.sh DEVICE_ID EPOCH_SIZE DATA_DIR" +echo "for example: bash run_eval.sh 0 /path/zh-wiki/ " +echo "==============================================================================================================" + +DEVICE_ID=$1 +DATA_DIR=$2 + +mkdir -p ms_log +CUR_DIR=`pwd` +export GLOG_log_dir=${CUR_DIR}/ms_log +export GLOG_logtostderr=0 +python evaluation.py \ + --device_id=$DEVICE_ID \ + --checkpoint_url="/store1/deeplabv3/deeplabv3_split_url/train/checkpoint/CKP-12_732.ckpt" \ + --data_url=$DATA_DIR > log.txt 2>&1 & \ No newline at end of file diff --git a/model_zoo/deeplabv3/scripts/run_standalone_train.sh b/model_zoo/deeplabv3/scripts/run_standalone_train.sh new file mode 100644 index 0000000000..91fa03194e --- /dev/null +++ b/model_zoo/deeplabv3/scripts/run_standalone_train.sh @@ -0,0 +1,37 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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 +# +# httpwww.apache.orglicensesLICENSE-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. +# ============================================================================ +echo "==============================================================================================================" +echo "Please run the scipt as: " +echo "bash run_standalone_pretrain.sh DEVICE_ID EPOCH_SIZE DATA_DIR" +echo "for example: bash run_standalone_train.sh 0 40 /path/zh-wiki/ " +echo "==============================================================================================================" + +DEVICE_ID=$1 +EPOCH_SIZE=$2 +DATA_DIR=$3 + +mkdir -p ms_log +CUR_DIR=`pwd` +export GLOG_log_dir=${CUR_DIR}/ms_log +export GLOG_logtostderr=0 +python train.py \ + --distribute="false" \ + --epoch_size=$EPOCH_SIZE \ + --device_id=$DEVICE_ID \ + --enable_save_ckpt="true" \ + --checkpoint_url="/store1/deeplabv3/deeplabv3_split_url/train/checkpoint/CKP-12_732.ckpt" \ + --save_checkpoint_steps=10000 \ + --save_checkpoint_num=1 \ + --data_url=$DATA_DIR > log.txt 2>&1 & \ No newline at end of file From ec7cbb9929d0dfc9857cd9cf970aa424a1f2183c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 02:44:12 +0800 Subject: [PATCH 05/20] modify deeplabv3 --- model_zoo/deeplabv3/evaluation.py | 58 ++ model_zoo/deeplabv3/scripts/mock | 0 model_zoo/deeplabv3/src/__init__.py | 10 + .../deeplabv3/src/backbone/resnet_deeplab.py | 534 ++++++++++++++++++ model_zoo/deeplabv3/src/config.py | 33 ++ model_zoo/deeplabv3/src/losses.py | 69 +++ model_zoo/deeplabv3/src/miou_precision.py | 65 +++ model_zoo/deeplabv3/src/mock | 0 model_zoo/deeplabv3/src/utils/__init__.py | 15 + .../deeplabv3/src/{ => utils}/adapter.py | 0 .../src/{ => utils}/custom_transforms.py | 0 model_zoo/deeplabv3/src/utils/file_io.py | 36 ++ model_zoo/deeplabv3/train.py | 99 ++++ 13 files changed, 919 insertions(+) create mode 100644 model_zoo/deeplabv3/evaluation.py delete mode 100644 model_zoo/deeplabv3/scripts/mock create mode 100644 model_zoo/deeplabv3/src/backbone/resnet_deeplab.py create mode 100644 model_zoo/deeplabv3/src/config.py create mode 100644 model_zoo/deeplabv3/src/losses.py create mode 100644 model_zoo/deeplabv3/src/miou_precision.py delete mode 100644 model_zoo/deeplabv3/src/mock create mode 100644 model_zoo/deeplabv3/src/utils/__init__.py rename model_zoo/deeplabv3/src/{ => utils}/adapter.py (100%) rename model_zoo/deeplabv3/src/{ => utils}/custom_transforms.py (100%) create mode 100644 model_zoo/deeplabv3/src/utils/file_io.py create mode 100644 model_zoo/deeplabv3/train.py diff --git a/model_zoo/deeplabv3/evaluation.py b/model_zoo/deeplabv3/evaluation.py new file mode 100644 index 0000000000..f4e3e38d9f --- /dev/null +++ b/model_zoo/deeplabv3/evaluation.py @@ -0,0 +1,58 @@ +#!/bin/bash +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ +"""evaluation.""" +import os, time +import argparse +from mindspore import context +from mindspore import log as logger +from mindspore.communication.management import init +import mindspore.nn as nn +from mindspore.nn.optim.momentum import Momentum +from mindspore.train.loss_scale_manager import FixedLossScaleManager +from mindspore import Model, ParallelMode +import argparse +from mindspore.train.serialization import load_checkpoint, load_param_into_net +from mindspore.train.callback import Callback,CheckpointConfig, ModelCheckpoint, TimeMonitor +from src.md_dataset import create_dataset +from src.losses import OhemLoss +from src.miou_precision import MiouPrecision +from src.deeplabv3 import deeplabv3_resnet50 +from src.config import config +parser = argparse.ArgumentParser(description="Deeplabv3 evaluation") +parser.add_argument('--epoch_size', type=int, default=2, help='Epoch size.') +parser.add_argument("--device_id", type=int, default=0, help="Device id, default is 0.") +parser.add_argument('--batch_size', type=int, default=2, help='Batch size.') +parser.add_argument('--data_url', required=True, default=None, help='Train data url') +parser.add_argument('--checkpoint_url', default=None, help='Checkpoint path') + +args_opt = parser.parse_args() +context.set_context(mode=context.GRAPH_MODE, device_target="Ascend", device_id=args_opt.device_id) +print(args_opt) +if __name__ == "__main__": + args_opt.crop_size = config.crop_size + args_opt.base_size = config.crop_size + eval_dataset = create_dataset(args_opt, args_opt.data_url, args_opt.epoch_size, args_opt.batch_size, usage="eval") + net = deeplabv3_resnet50(config.seg_num_classes, [args_opt.batch_size,3,args_opt.crop_size,args_opt.crop_size], + infer_scale_sizes=config.eval_scales, atrous_rates=config.atrous_rates, + decoder_output_stride=config.decoder_output_stride, output_stride = config.output_stride, + fine_tune_batch_norm=config.fine_tune_batch_norm, image_pyramid = config.image_pyramid) + param_dict = load_checkpoint(args_opt.checkpoint_url) + load_param_into_net(net, param_dict) + mIou = MiouPrecision(config.seg_num_classes) + metrics={'mIou':mIou} + loss = OhemLoss(config.seg_num_classes, config.ignore_label) + model = Model(net, loss, metrics=metrics) + model.eval(eval_dataset) \ No newline at end of file diff --git a/model_zoo/deeplabv3/scripts/mock b/model_zoo/deeplabv3/scripts/mock deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/model_zoo/deeplabv3/src/__init__.py b/model_zoo/deeplabv3/src/__init__.py index 301ef9dcb7..1cce2ac0db 100644 --- a/model_zoo/deeplabv3/src/__init__.py +++ b/model_zoo/deeplabv3/src/__init__.py @@ -12,3 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================ +"""Init DeepLabv3.""" +from .deeplabv3 import ASPP, DeepLabV3, deeplabv3_resnet50 +from . import backbone +from .backbone import * + +__all__ = [ + "ASPP", "DeepLabV3", "deeplabv3_resnet50", "Decoder" +] + +__all__.extend(backbone.__all__) diff --git a/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py b/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py new file mode 100644 index 0000000000..fff77beca8 --- /dev/null +++ b/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py @@ -0,0 +1,534 @@ +#!/bin/bash +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ +"""ResNet based DeepLab.""" +import mindspore.nn as nn +from mindspore.ops import operations as P +from mindspore import Tensor +import numpy as np +from mindspore.common.initializer import TruncatedNormal, initializer +from mindspore._checkparam import check_bool, twice +from mindspore import log as logger +from mindspore.common.parameter import Parameter +def _conv_bn_relu(in_channel, + out_channel, + ksize, + stride=1, + padding=0, + dilation=1, + pad_mode="pad", + use_batch_statistics=False): + """Get a conv2d -> batchnorm -> relu layer""" + return nn.SequentialCell( + [nn.Conv2d(in_channel, + out_channel, + kernel_size=ksize, + stride=stride, + padding=padding, + dilation=dilation, + pad_mode=pad_mode), + nn.BatchNorm2d(out_channel, use_batch_statistics=use_batch_statistics), + nn.ReLU()] + ) +def _deep_conv_bn_relu(in_channel, + channel_multiplier, + ksize, + stride=1, + padding=0, + dilation=1, + pad_mode="pad", + use_batch_statistics=False): + """Get a spacetobatch -> conv2d -> batchnorm -> relu -> batchtospace layer""" + return nn.SequentialCell( + [DepthwiseConv2dNative(in_channel, + channel_multiplier, + kernel_size=ksize, + stride=stride, + padding=padding, + dilation=dilation, + pad_mode=pad_mode), + nn.BatchNorm2d(channel_multiplier * in_channel, use_batch_statistics=use_batch_statistics), + nn.ReLU()] + ) +def _stob_deep_conv_btos_bn_relu(in_channel, + channel_multiplier, + ksize, + space_to_batch_block_shape, + batch_to_space_block_shape, + paddings, + crops, + stride=1, + padding=0, + dilation=1, + pad_mode="pad", + use_batch_statistics=False): + """Get a spacetobatch -> conv2d -> batchnorm -> relu -> batchtospace layer""" + return nn.SequentialCell( + [SpaceToBatch(space_to_batch_block_shape,paddings), + DepthwiseConv2dNative(in_channel, + channel_multiplier, + kernel_size=ksize, + stride=stride, + padding=padding, + dilation=dilation, + pad_mode=pad_mode), + BatchToSpace(batch_to_space_block_shape,crops), + nn.BatchNorm2d(channel_multiplier * in_channel, use_batch_statistics=use_batch_statistics), + nn.ReLU()] + ) +def _stob_conv_btos_bn_relu(in_channel, + out_channel, + ksize, + space_to_batch_block_shape, + batch_to_space_block_shape, + paddings, + crops, + stride=1, + padding=0, + dilation=1, + pad_mode="pad", + use_batch_statistics=False): + """Get a spacetobatch -> conv2d -> batchnorm -> relu -> batchtospace layer""" + return nn.SequentialCell( + [SpaceToBatch(space_to_batch_block_shape,paddings), + nn.Conv2d(in_channel, + out_channel, + kernel_size=ksize, + stride=stride, + padding=padding, + dilation=dilation, + pad_mode=pad_mode), + BatchToSpace(batch_to_space_block_shape,crops), + nn.BatchNorm2d(out_channel,use_batch_statistics=use_batch_statistics), + nn.ReLU()] + ) +def _make_layer(block, + in_channels, + out_channels, + num_blocks, + stride=1, + rate=1, + multi_grads=None, + output_stride=None, + g_current_stride=2, + g_rate=1): + """Make layer for DeepLab-ResNet network.""" + if multi_grads is None: + multi_grads = [1] * num_blocks + # (stride == 2, num_blocks == 4 --> strides == [1, 1, 1, 2]) + strides = [1] * (num_blocks - 1) + [stride] + blocks = [] + if output_stride is not None: + if output_stride % 4 != 0: + raise ValueError('The output_stride needs to be a multiple of 4.') + output_stride //= 4 + for i_stride, _ in enumerate(strides): + if output_stride is not None and g_current_stride > output_stride: + raise ValueError('The target output_stride cannot be reached.') + if output_stride is not None and g_current_stride == output_stride: + b_rate = g_rate + b_stride = 1 + g_rate *= strides[i_stride] + else: + b_rate = rate + b_stride = strides[i_stride] + g_current_stride *= strides[i_stride] + blocks.append(block(in_channels=in_channels, + out_channels=out_channels, + stride=b_stride, + rate=b_rate, + multi_grad=multi_grads[i_stride])) + in_channels = out_channels + layer = nn.SequentialCell(blocks) + return layer, g_current_stride, g_rate +class Subsample(nn.Cell): + """ + Subsample for DeepLab-ResNet. + Args: + factor (int): Sample factor. + Returns: + Tensor, the sub sampled tensor. + Examples: + >>> Subsample(2) + """ + def __init__(self, factor): + super(Subsample, self).__init__() + self.factor = factor + self.pool = nn.MaxPool2d(kernel_size=1, + stride=factor) + def construct(self, x): + if self.factor == 1: + return x + return self.pool(x) +class SpaceToBatch(nn.Cell): + def __init__(self, block_shape, paddings): + super(SpaceToBatch, self).__init__() + self.space_to_batch = P.SpaceToBatch(block_shape, paddings) + self.bs = block_shape + self.pd = paddings + def construct(self, x): + return self.space_to_batch(x) +class BatchToSpace(nn.Cell): + def __init__(self, block_shape, crops): + super(BatchToSpace, self).__init__() + self.batch_to_space = P.BatchToSpace(block_shape, crops) + self.bs = block_shape + self.cr = crops + def construct(self, x): + return self.batch_to_space(x) +class _DepthwiseConv2dNative(nn.Cell): + def __init__(self, + in_channels, + channel_multiplier, + kernel_size, + stride, + pad_mode, + padding, + dilation, + group, + weight_init): + super(_DepthwiseConv2dNative, self).__init__() + self.in_channels = in_channels + self.channel_multiplier = channel_multiplier + self.kernel_size = kernel_size + self.stride = stride + self.pad_mode = pad_mode + self.padding = padding + self.dilation = dilation + self.group = group + if not (isinstance(in_channels, int) and in_channels > 0): + raise ValueError('Attr \'in_channels\' of \'DepthwiseConv2D\' Op passed ' + + str(in_channels) + ', should be a int and greater than 0.') + if (not isinstance(kernel_size, tuple)) or len(kernel_size) != 2 or \ + (not isinstance(kernel_size[0], int)) or (not isinstance(kernel_size[1], int)) or \ + kernel_size[0] < 1 or kernel_size[1] < 1: + raise ValueError('Attr \'kernel_size\' of \'DepthwiseConv2D\' Op passed ' + + str(self.kernel_size) + ', should be a int or tuple and equal to or greater than 1.') + self.weight = Parameter(initializer(weight_init, [1, in_channels // group, *kernel_size]), + name='weight') + def construct(self, *inputs): + """Must be overridden by all subclasses.""" + raise NotImplementedError +class DepthwiseConv2dNative(_DepthwiseConv2dNative): + def __init__(self, + in_channels, + channel_multiplier, + kernel_size, + stride=1, + pad_mode='same', + padding=0, + dilation=1, + group=1, + weight_init='normal'): + kernel_size = twice(kernel_size) + super(DepthwiseConv2dNative, self).__init__( + in_channels, + channel_multiplier, + kernel_size, + stride, + pad_mode, + padding, + dilation, + group, + weight_init) + self.depthwise_conv2d_native = P.DepthwiseConv2dNative(channel_multiplier=self.channel_multiplier, + kernel_size=self.kernel_size, + mode=3, + pad_mode=self.pad_mode, + pad=self.padding, + stride=self.stride, + dilation=self.dilation, + group=self.group) + def set_strategy(self, strategy): + self.depthwise_conv2d_native.set_strategy(strategy) + return self + def construct(self, x): + return self.depthwise_conv2d_native(x, self.weight) +class BottleneckV1(nn.Cell): + """ + ResNet V1 BottleneckV1 block definition. + Args: + in_channels (int): Input channel. + out_channels (int): Output channel. + stride (int): Stride size for the initial convolutional layer. Default: 1. + rate (int): Rate for convolution. Default: 1. + multi_grad (int): Employ a rate within network. Default: 1. + Returns: + Tensor, the ResNet unit's output. + Examples: + >>> BottleneckV1(3,256,stride=2) + """ + def __init__(self, + in_channels, + out_channels, + stride=1, + use_batch_statistics=False, + use_batch_to_stob_and_btos=False): + super(BottleneckV1, self).__init__() + expansion = 4 + mid_channels = out_channels // expansion + self.conv_bn1 = _conv_bn_relu(in_channels, + mid_channels, + ksize=1, + stride=1, + use_batch_statistics=use_batch_statistics) + self.conv_bn2 = _conv_bn_relu(mid_channels, + mid_channels, + ksize=3, + stride=stride, + padding=1, + dilation=1, + use_batch_statistics=use_batch_statistics) + if use_batch_to_stob_and_btos == True: + self.conv_bn2 = _stob_conv_btos_bn_relu(mid_channels, + mid_channels, + ksize=3, + stride=stride, + padding=0, + dilation=1, + space_to_batch_block_shape = 2, + batch_to_space_block_shape = 2, + paddings =[[2, 3], [2, 3]], + crops =[[0, 1], [0, 1]], + pad_mode="valid", + use_batch_statistics=use_batch_statistics) + + self.conv3 = nn.Conv2d(mid_channels, + out_channels, + kernel_size=1, + stride=1) + self.bn3 = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) + if in_channels != out_channels: + conv = nn.Conv2d(in_channels, + out_channels, + kernel_size=1, + stride=stride) + bn = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) + self.downsample = nn.SequentialCell([conv, bn]) + else: + self.downsample = Subsample(stride) + self.add = P.TensorAdd() + self.relu = nn.ReLU() + self.Reshape = P.Reshape() + def construct(self, x): + out = self.conv_bn1(x) + out = self.conv_bn2(out) + out = self.bn3(self.conv3(out)) + out = self.add(out, self.downsample(x)) + out = self.relu(out) + return out + return out + +class BottleneckV2(nn.Cell): + """ + ResNet V2 Bottleneck variance V2 block definition. + Args: + in_channels (int): Input channel. + out_channels (int): Output channel. + stride (int): Stride size for the initial convolutional layer. Default: 1. + Returns: + Tensor, the ResNet unit's output. + Examples: + >>> BottleneckV2(3,256,stride=2) + """ + def __init__(self, + in_channels, + out_channels, + stride=1, + use_batch_statistics=False, + use_batch_to_stob_and_btos=False, + dilation=1): + super(BottleneckV2, self).__init__() + expansion = 4 + mid_channels = out_channels // expansion + self.conv_bn1 = _conv_bn_relu(in_channels, + mid_channels, + ksize=1, + stride=1, + use_batch_statistics=use_batch_statistics) + self.conv_bn2 = _conv_bn_relu(mid_channels, + mid_channels, + ksize=3, + stride=stride, + padding=1, + dilation=dilation, + use_batch_statistics=use_batch_statistics) + if use_batch_to_stob_and_btos == True: + self.conv_bn2 = _stob_conv_btos_bn_relu(mid_channels, + mid_channels, + ksize=3, + stride=stride, + padding=0, + dilation=1, + space_to_batch_block_shape = 2, + batch_to_space_block_shape = 2, + paddings =[[2, 3], [2, 3]], + crops =[[0, 1], [0, 1]], + pad_mode="valid", + use_batch_statistics=use_batch_statistics) + self.conv3 = nn.Conv2d(mid_channels, + out_channels, + kernel_size=1, + stride=1) + self.bn3 = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) + if in_channels != out_channels: + conv = nn.Conv2d(in_channels, + out_channels, + kernel_size=1, + stride=stride) + bn = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) + self.downsample = nn.SequentialCell([conv, bn]) + else: + self.downsample = Subsample(stride) + self.add = P.TensorAdd() + self.relu = nn.ReLU() + def construct(self, x): + out = self.conv_bn1(x) + out = self.conv_bn2(out) + out = self.bn3(self.conv3(out)) + out = self.add(out, x) + out = self.relu(out) + return out + +class BottleneckV3(nn.Cell): + """ + ResNet V1 Bottleneck variance V1 block definition. + Args: + in_channels (int): Input channel. + out_channels (int): Output channel. + stride (int): Stride size for the initial convolutional layer. Default: 1. + Returns: + Tensor, the ResNet unit's output. + Examples: + >>> BottleneckV3(3,256,stride=2) + """ + def __init__(self, + in_channels, + out_channels, + stride=1, + use_batch_statistics=False): + super(BottleneckV3, self).__init__() + expansion = 4 + mid_channels = out_channels // expansion + self.conv_bn1 = _conv_bn_relu(in_channels, + mid_channels, + ksize=1, + stride=1, + use_batch_statistics=use_batch_statistics) + self.conv_bn2 = _conv_bn_relu(mid_channels, + mid_channels, + ksize=3, + stride=stride, + padding=1, + dilation=1, + use_batch_statistics=use_batch_statistics) + self.conv3 = nn.Conv2d(mid_channels, + out_channels, + kernel_size=1, + stride=1) + self.bn3 = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) + + if in_channels != out_channels: + conv = nn.Conv2d(in_channels, + out_channels, + kernel_size=1, + stride=stride) + bn = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) + self.downsample = nn.SequentialCell([conv, bn]) + else: + self.downsample = Subsample(stride) + self.downsample = Subsample(stride) + self.add = P.TensorAdd() + self.relu = nn.ReLU() + def construct(self, x): + out = self.conv_bn1(x) + out = self.conv_bn2(out) + out = self.bn3(self.conv3(out)) + out = self.add(out, self.downsample(x)) + out = self.relu(out) + return out + +class ResNetV1(nn.Cell): + """ + ResNet V1 for DeepLab. + Args: + Returns: + Tuple, output tensor tuple, (c2,c5). + Examples: + >>> ResNetV1(False) + """ + def __init__(self, fine_tune_batch_norm=False): + super(ResNetV1, self).__init__() + self.layer_root = nn.SequentialCell( + [RootBlockBeta(fine_tune_batch_norm), + nn.MaxPool2d(kernel_size=(3,3), + stride=(2,2), + #padding=1, + pad_mode='same')]) + self.layer1_1 = BottleneckV1(128, 256, stride=1, use_batch_statistics=fine_tune_batch_norm) + self.layer1_2 = BottleneckV2(256, 256, stride=1, use_batch_statistics=fine_tune_batch_norm) + self.layer1_3 = BottleneckV3(256, 256, stride=2, use_batch_statistics=fine_tune_batch_norm) + self.layer2_1 = BottleneckV1(256, 512, stride=1, use_batch_statistics=fine_tune_batch_norm) + self.layer2_2 = BottleneckV2(512, 512, stride=1, use_batch_statistics=fine_tune_batch_norm) + self.layer2_3 = BottleneckV2(512, 512, stride=1, use_batch_statistics=fine_tune_batch_norm) + self.layer2_4 = BottleneckV3(512, 512, stride=2, use_batch_statistics=fine_tune_batch_norm) + self.layer3_1 = BottleneckV1(512, 1024, stride=1, use_batch_statistics=fine_tune_batch_norm) + self.layer3_2 = BottleneckV2(1024, 1024, stride=1, use_batch_statistics=fine_tune_batch_norm) + self.layer3_3 = BottleneckV2(1024, 1024, stride=1, use_batch_statistics=fine_tune_batch_norm) + self.layer3_4 = BottleneckV2(1024, 1024, stride=1, use_batch_statistics=fine_tune_batch_norm) + self.layer3_5 = BottleneckV2(1024, 1024, stride=1, use_batch_statistics=fine_tune_batch_norm) + self.layer3_6 = BottleneckV2(1024, 1024, stride=1, use_batch_statistics=fine_tune_batch_norm) + + self.layer4_1 = BottleneckV1(1024, 2048, stride=1, use_batch_to_stob_and_btos=True, use_batch_statistics=fine_tune_batch_norm) + self.layer4_2 = BottleneckV2(2048, 2048, stride=1, use_batch_to_stob_and_btos=True, use_batch_statistics=fine_tune_batch_norm) + self.layer4_3 = BottleneckV2(2048, 2048, stride=1, use_batch_to_stob_and_btos=True, use_batch_statistics=fine_tune_batch_norm) + def construct(self, x): + x = self.layer_root(x) + x = self.layer1_1(x) + c2 = self.layer1_2(x) + x = self.layer1_3(c2) + x = self.layer2_1(x) + x = self.layer2_2(x) + x = self.layer2_3(x) + x = self.layer2_4(x) + x = self.layer3_1(x) + x = self.layer3_2(x) + x = self.layer3_3(x) + x = self.layer3_4(x) + x = self.layer3_5(x) + x = self.layer3_6(x) + + x = self.layer4_1(x) + x = self.layer4_2(x) + c5 = self.layer4_3(x) + return c2, c5 +class RootBlockBeta(nn.Cell): + """ + ResNet V1 beta root block definition. + Returns: + Tensor, the block unit's output. + Examples: + >>> RootBlockBeta() + """ + def __init__(self, fine_tune_batch_norm=False): + super(RootBlockBeta, self).__init__() + self.conv1 = _conv_bn_relu(3, 64, ksize=3, stride=2, padding=0, pad_mode="valid", use_batch_statistics=fine_tune_batch_norm) + self.conv2 = _conv_bn_relu(64, 64, ksize=3, stride=1, padding=0, pad_mode="same", use_batch_statistics=fine_tune_batch_norm) + self.conv3 = _conv_bn_relu(64, 128, ksize=3, stride=1, padding=0, pad_mode="same", use_batch_statistics=fine_tune_batch_norm) + def construct(self, x): + x = self.conv1(x) + x = self.conv2(x) + x = self.conv3(x) + return x diff --git a/model_zoo/deeplabv3/src/config.py b/model_zoo/deeplabv3/src/config.py new file mode 100644 index 0000000000..742592fc19 --- /dev/null +++ b/model_zoo/deeplabv3/src/config.py @@ -0,0 +1,33 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ +""" +network config setting, will be used in train.py and evaluation.py +""" +from easydict import EasyDict as ed + +config = ed({ + "learning_rate": 0.0014, + "weight_decay": 0.00005, + "momentum": 0.97, + "crop_size": 513, + "eval_scales": [0.5, 0.75, 1.0, 1.25, 1.5, 1.75], + "atrous_rates": None, + "image_pyramid": None, + "output_stride": 16, + "fine_tune_batch_norm": False, + "ignore_label": 255, + "decoder_output_stride": None, + "seg_num_classes": 21 +}) \ No newline at end of file diff --git a/model_zoo/deeplabv3/src/losses.py b/model_zoo/deeplabv3/src/losses.py new file mode 100644 index 0000000000..ebecd54aea --- /dev/null +++ b/model_zoo/deeplabv3/src/losses.py @@ -0,0 +1,69 @@ +#!/bin/bash +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ +"""OhemLoss.""" +import mindspore.nn as nn +import mindspore.common.dtype as mstype +from mindspore import Tensor +from mindspore.ops import operations as P +from mindspore.ops import functional as F + +class OhemLoss(nn.Cell): + def __init__(self, num, ignore_label): + super(OhemLoss, self).__init__() + self.mul = P.Mul() + self.shape = P.Shape() + self.one_hot = nn.OneHot(-1, num, 1.0, 0.0) + self.squeeze = P.Squeeze() + self.num = num + self.cross_entropy = P.SoftmaxCrossEntropyWithLogits() + self.mean = P.ReduceMean() + self.select = P.Select() + self.reshape = P.Reshape() + self.cast = P.Cast() + self.not_equal = P.NotEqual() + self.equal = P.Equal() + self.reduce_sum = P.ReduceSum(keep_dims=False) + self.fill = P.Fill() + self.transpose = P.Transpose() + self.ignore_label = ignore_label + self.loss_weight = 1.0 + + def construct(self, logits, labels): + logits = self.transpose(logits,(0,2,3,1)) + logits = self.reshape(logits, (-1,self.num)) + labels = F.cast(labels,mstype.int32) + labels = self.reshape(labels, (-1,)) + one_hot_labels = self.one_hot(labels) + losses = self.cross_entropy(logits, one_hot_labels)[0] + weights = self.cast(self.not_equal(labels,self.ignore_label),mstype.float32) * self.loss_weight + weighted_losses = self.mul(losses, weights) + loss = self.reduce_sum(weighted_losses,(0,)) + zeros = self.fill(mstype.float32, self.shape(weights), 0.0) + ones = self.fill(mstype.float32, self.shape(weights), 1.0) + present = self.select( + self.equal(weights, zeros), + zeros, + ones) + present = self.reduce_sum(present,(0,)) + + zeros = self.fill(mstype.float32, self.shape(present), 0.0) + min_control = self.fill(mstype.float32, self.shape(present), 1.0) + present = self.select( + self.equal(present, zeros), + min_control, + present) + loss = loss / present + return loss \ No newline at end of file diff --git a/model_zoo/deeplabv3/src/miou_precision.py b/model_zoo/deeplabv3/src/miou_precision.py new file mode 100644 index 0000000000..03273b5b0c --- /dev/null +++ b/model_zoo/deeplabv3/src/miou_precision.py @@ -0,0 +1,65 @@ +#!/bin/bash +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ +"""mIou.""" +import numpy as np +from mindspore.nn.metrics.metric import Metric +def confuse_matrix(target, pred, n): + k = (target >= 0) & (target < n) + return np.bincount(n * target[k].astype(int) + pred[k], minlength=n ** 2).reshape(n, n) +def iou(hist): + denominator = hist.sum(1) + hist.sum(0) - np.diag(hist) + res = np.diag(hist) / np.where(denominator > 0, denominator, 1) + res = np.sum(res) / np.count_nonzero(denominator) + return res +class MiouPrecision(Metric): + def __init__(self, num_class=21): + super(MiouPrecision, self).__init__() + if not isinstance(num_class, int): + raise TypeError('num_class should be integer type, but got {}'.format(type(num_class))) + if num_class < 1: + raise ValueError('num_class must be at least 1, but got {}'.format(num_class)) + self._num_class = num_class + self._mIoU=[] + self.clear() + def clear(self): + self._hist = np.zeros((self._num_class, self._num_class)) + self._mIoU=[] + def update(self, *inputs): + if len(inputs) != 2: + raise ValueError('Need 2 inputs (y_pred, y), but got {}'.format(len(inputs))) + predict_in = self._convert_data(inputs[0]) + label_in = self._convert_data(inputs[1]) + if predict_in.shape[1] != self._num_class: + raise ValueError('Class number not match, last input data contain {} classes, but current data contain {} ' + 'classes'.format(self._num_class, predict_in.shape[1])) + batch_size = predict_in.shape[0] + pred = np.argmax(predict_in,axis=1) + label = label_in + if len(label.flatten()) != len(pred.flatten()): + print('Skipping: len(gt) = {:d}, len(pred) = {:d}'.format(len(label.flatten()), len(pred.flatten()))) + raise ValueError('Class number not match, last input data contain {} classes, but current data contain {} ' + 'classes'.format(self._num_class, predict_in.shape[1])) + self._hist = confuse_matrix(label.flatten(), pred.flatten(), self._num_class) + mIoUs = iou(self._hist) + self._mIoU.append(mIoUs) + + def eval(self): + """ + Computes the mIoU categorical accuracy. + """ + mIoU=np.nanmean(self._mIoU) + print('mIoU = {}'.format(mIoU)) + return mIoU \ No newline at end of file diff --git a/model_zoo/deeplabv3/src/mock b/model_zoo/deeplabv3/src/mock deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/model_zoo/deeplabv3/src/utils/__init__.py b/model_zoo/deeplabv3/src/utils/__init__.py new file mode 100644 index 0000000000..457700a020 --- /dev/null +++ b/model_zoo/deeplabv3/src/utils/__init__.py @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ \ No newline at end of file diff --git a/model_zoo/deeplabv3/src/adapter.py b/model_zoo/deeplabv3/src/utils/adapter.py similarity index 100% rename from model_zoo/deeplabv3/src/adapter.py rename to model_zoo/deeplabv3/src/utils/adapter.py diff --git a/model_zoo/deeplabv3/src/custom_transforms.py b/model_zoo/deeplabv3/src/utils/custom_transforms.py similarity index 100% rename from model_zoo/deeplabv3/src/custom_transforms.py rename to model_zoo/deeplabv3/src/utils/custom_transforms.py diff --git a/model_zoo/deeplabv3/src/utils/file_io.py b/model_zoo/deeplabv3/src/utils/file_io.py new file mode 100644 index 0000000000..a8fa34811d --- /dev/null +++ b/model_zoo/deeplabv3/src/utils/file_io.py @@ -0,0 +1,36 @@ +#!/bin/bash +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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 os + + +def _is_obs(url): + return url.startswith("obs://") or url.startswith("s3://") + + +def read(url, binary=False): + if _is_obs(url): + # TODO read cloud file. + return None + + with open(url, "rb" if binary else "r") as f: + return f.read() + + +def walk(url): + if _is_obs(url): + # TODO read cloud file. + return None + return os.walk(url) \ No newline at end of file diff --git a/model_zoo/deeplabv3/train.py b/model_zoo/deeplabv3/train.py new file mode 100644 index 0000000000..7ffe7879c2 --- /dev/null +++ b/model_zoo/deeplabv3/train.py @@ -0,0 +1,99 @@ +#!/bin/bash +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ +"""train.""" +import os, time +import argparse +from mindspore import context +from mindspore import log as logger +from mindspore.communication.management import init +import mindspore.nn as nn +from mindspore.nn.optim.momentum import Momentum +from mindspore.train.loss_scale_manager import FixedLossScaleManager +from mindspore import Model, ParallelMode +import argparse +from mindspore.train.serialization import load_checkpoint, load_param_into_net +from mindspore.train.callback import Callback,CheckpointConfig, ModelCheckpoint, TimeMonitor +from src.md_dataset import create_dataset +from src.losses import OhemLoss +from src.deeplabv3 import deeplabv3_resnet50 +from src.config import config + +parser = argparse.ArgumentParser(description="Deeplabv3 training") +parser.add_argument("--distribute", type=str, default="false", help="Run distribute, default is false.") +parser.add_argument('--epoch_size', type=int, default=2, help='Epoch size.') +parser.add_argument('--batch_size', type=int, default=2, help='Batch size.') +parser.add_argument('--data_url', required=True, default=None, help='Train data url') +parser.add_argument("--device_id", type=int, default=0, help="Device id, default is 0.") +parser.add_argument('--checkpoint_url', default=None, help='Checkpoint path') +parser.add_argument("--enable_save_ckpt", type=str, default="true", help="Enable save checkpoint, default is true.") +parser.add_argument('--max_checkpoint_num', type=int, default=5, help='Max checkpoint number.') +parser.add_argument("--save_checkpoint_steps", type=int, default=1000, help="Save checkpoint steps, " + "default is 1000.") +parser.add_argument("--save_checkpoint_num", type=int, default=1, help="Save checkpoint numbers, default is 1.") +args_opt = parser.parse_args() +print(args_opt) +context.set_context(mode=context.GRAPH_MODE, device_target="Ascend", device_id=args_opt.device_id) +class LossCallBack(Callback): + """ + Monitor the loss in training. + Note: + if per_print_times is 0 do not print loss. + Args: + per_print_times (int): Print loss every times. Default: 1. + """ + def __init__(self, per_print_times=1): + super(LossCallBack, self).__init__() + if not isinstance(per_print_times, int) or per_print_times < 0: + raise ValueError("print_step must be int and >= 0") + self._per_print_times = per_print_times + def step_end(self, run_context): + cb_params = run_context.original_args() + print("epoch: {}, step: {}, outputs are {}".format(cb_params.cur_epoch_num, cb_params.cur_step_num, + str(cb_params.net_outputs))) +def model_fine_tune(flags, net, fix_weight_layer): + checkpoint_path = flags.checkpoint_url + if checkpoint_path is None: + return + param_dict = load_checkpoint(checkpoint_path) + load_param_into_net(net, param_dict) + for para in net.trainable_params(): + if fix_weight_layer in para.name: + para.requires_grad=False +if __name__ == "__main__": + if args_opt.distribute == "true": + context.set_auto_parallel_context(parallel_mode=ParallelMode.DATA_PARALLEL, mirror_mean=True) + init() + args_opt.base_size = config.crop_size + args_opt.crop_size = config.crop_size + train_dataset = create_dataset(args_opt, args_opt.data_url, args_opt.epoch_size, args_opt.batch_size, usage="train") + dataset_size = train_dataset.get_dataset_size() + time_cb = TimeMonitor(data_size=dataset_size) + callback = [time_cb, LossCallBack()] + if args_opt.enable_save_ckpt == "true": + config_ck = CheckpointConfig(save_checkpoint_steps=args_opt.save_checkpoint_steps, + keep_checkpoint_max=args_opt.save_checkpoint_num) + ckpoint_cb = ModelCheckpoint(prefix='checkpoint_deeplabv3', config=config_ck) + callback.append(ckpoint_cb) + net = deeplabv3_resnet50(crop_size.seg_num_classes, [args_opt.batch_size,3,args_opt.crop_size,args_opt.crop_size], + infer_scale_sizes=crop_size.eval_scales, atrous_rates=crop_size.atrous_rates, + decoder_output_stride=crop_size.decoder_output_stride, output_stride = crop_size.output_stride, + fine_tune_batch_norm=crop_size.fine_tune_batch_norm, image_pyramid = crop_size.image_pyramid) + net.set_train() + model_fine_tune(args_opt, net, 'layer') + loss = OhemLoss(crop_size.seg_num_classes, crop_size.ignore_label) + opt = Momentum(filter(lambda x: 'beta' not in x.name and 'gamma' not in x.name and 'depth' not in x.name and 'bias' not in x.name, net.trainable_params()), learning_rate=args_opt.learning_rate, momentum=args_opt.momentum, weight_decay=args_opt.weight_decay) + model = Model(net, loss, opt) + model.train(args_opt.epoch_size, train_dataset, callback) \ No newline at end of file From 913b5b03dfcf7091c9a81d9ee65343fb991a48f2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 03:17:32 +0800 Subject: [PATCH 06/20] modify --- model_zoo/deeplabv3/src/backbone/__init__.py | 8 ++++++ .../deeplabv3/src/backbone/resnet_deeplab.py | 3 +++ model_zoo/deeplabv3/src/ei_datasest.py | 25 +------------------ model_zoo/deeplabv3/src/md_dataset.py | 8 ++---- model_zoo/deeplabv3/train.py | 12 ++++----- 5 files changed, 20 insertions(+), 36 deletions(-) create mode 100644 model_zoo/deeplabv3/src/backbone/__init__.py diff --git a/model_zoo/deeplabv3/src/backbone/__init__.py b/model_zoo/deeplabv3/src/backbone/__init__.py new file mode 100644 index 0000000000..4ccf212619 --- /dev/null +++ b/model_zoo/deeplabv3/src/backbone/__init__.py @@ -0,0 +1,8 @@ +from .resnet_deeplab import Subsample, DepthwiseConv2dNative, SpaceToBatch, BatchToSpace, ResNetV1, \ + RootBlockBeta, resnet50_dl + +__all__= [ + "Subsample", "DepthwiseConv2dNative", "SpaceToBatch", "BatchToSpace", "ResNetV1", "RootBlockBeta", + "resnet50_dl" +] + \ No newline at end of file diff --git a/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py b/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py index fff77beca8..187fd7ae79 100644 --- a/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py +++ b/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py @@ -532,3 +532,6 @@ class RootBlockBeta(nn.Cell): x = self.conv2(x) x = self.conv3(x) return x + +class resnet50_dl(fine_tune_batch_norm=False): + return ResNetV1(fine_tune_batch_norm) diff --git a/model_zoo/deeplabv3/src/ei_datasest.py b/model_zoo/deeplabv3/src/ei_datasest.py index b2a20999d6..c139bf48e5 100644 --- a/model_zoo/deeplabv3/src/ei_datasest.py +++ b/model_zoo/deeplabv3/src/ei_datasest.py @@ -17,7 +17,7 @@ import abc import os import time -from .utils.adapter import get_manifest_samples, get_raw_samples, read_image +from .utils.adapter import get_raw_samples, read_image class BaseDataset(object): @@ -62,29 +62,6 @@ class BaseDataset(object): pass -class HwVocManifestDataset(BaseDataset): - """ - Create dataset with manifest data. - - Args: - data_url (str): The path of data. - usage (str): Whether to use train or eval (default='train'). - - Returns: - Dataset. - """ - - def __init__(self, data_url, usage="train"): - super().__init__(data_url, usage) - - def _load_samples(self): - try: - self.samples = get_manifest_samples(self.data_url, self.usage) - except Exception as e: - print("load HwVocManifestDataset samples failed!!!") - raise e - - class HwVocRawDataset(BaseDataset): """ Create dataset with raw data. diff --git a/model_zoo/deeplabv3/src/md_dataset.py b/model_zoo/deeplabv3/src/md_dataset.py index b18d94cc0d..f800f7e12f 100644 --- a/model_zoo/deeplabv3/src/md_dataset.py +++ b/model_zoo/deeplabv3/src/md_dataset.py @@ -17,7 +17,7 @@ from PIL import Image import mindspore.dataset as de import mindspore.dataset.transforms.vision.c_transforms as C -from .ei_dataset import HwVocManifestDataset, HwVocRawDataset +from .ei_dataset import HwVocRawDataset from .utils import custom_transforms as tr @@ -77,10 +77,7 @@ def create_dataset(args, data_url, epoch_num=1, batch_size=1, usage="train"): Dataset. """ # create iter dataset - if data_url.endswith(".manifest"): - dataset = HwVocManifestDataset(data_url, usage=usage) - else: - dataset = HwVocRawDataset(data_url, usage=usage) + dataset = HwVocRawDataset(data_url, usage=usage) dataset_len = len(dataset) # wrapped with GeneratorDataset @@ -100,5 +97,4 @@ def create_dataset(args, data_url, epoch_num=1, batch_size=1, usage="train"): dataset = dataset.repeat(count=epoch_num) dataset.map_model = 4 - dataset.__loop_size__ = 1 return dataset diff --git a/model_zoo/deeplabv3/train.py b/model_zoo/deeplabv3/train.py index 7ffe7879c2..ed625ede6b 100644 --- a/model_zoo/deeplabv3/train.py +++ b/model_zoo/deeplabv3/train.py @@ -87,13 +87,13 @@ if __name__ == "__main__": keep_checkpoint_max=args_opt.save_checkpoint_num) ckpoint_cb = ModelCheckpoint(prefix='checkpoint_deeplabv3', config=config_ck) callback.append(ckpoint_cb) - net = deeplabv3_resnet50(crop_size.seg_num_classes, [args_opt.batch_size,3,args_opt.crop_size,args_opt.crop_size], - infer_scale_sizes=crop_size.eval_scales, atrous_rates=crop_size.atrous_rates, - decoder_output_stride=crop_size.decoder_output_stride, output_stride = crop_size.output_stride, - fine_tune_batch_norm=crop_size.fine_tune_batch_norm, image_pyramid = crop_size.image_pyramid) + net = deeplabv3_resnet50(config.seg_num_classes, [args_opt.batch_size,3,args_opt.crop_size,args_opt.crop_size], + infer_scale_sizes=config.eval_scales, atrous_rates=config.atrous_rates, + decoder_output_stride=config.decoder_output_stride, output_stride = config.output_stride, + fine_tune_batch_norm=config.fine_tune_batch_norm, image_pyramid = config.image_pyramid) net.set_train() model_fine_tune(args_opt, net, 'layer') - loss = OhemLoss(crop_size.seg_num_classes, crop_size.ignore_label) - opt = Momentum(filter(lambda x: 'beta' not in x.name and 'gamma' not in x.name and 'depth' not in x.name and 'bias' not in x.name, net.trainable_params()), learning_rate=args_opt.learning_rate, momentum=args_opt.momentum, weight_decay=args_opt.weight_decay) + loss = OhemLoss(config.seg_num_classes, config.ignore_label) + opt = Momentum(filter(lambda x: 'beta' not in x.name and 'gamma' not in x.name and 'depth' not in x.name and 'bias' not in x.name, net.trainable_params()), learning_rate=config.learning_rate, momentum=config.momentum, weight_decay=config.weight_decay) model = Model(net, loss, opt) model.train(args_opt.epoch_size, train_dataset, callback) \ No newline at end of file From 34198540e4a54ad25798ce15577e988fd16aabcf Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 03:30:54 +0800 Subject: [PATCH 07/20] 0331 --- model_zoo/deeplabv3/src/backbone/resnet_deeplab.py | 6 +++--- model_zoo/deeplabv3/src/{ei_datasest.py => ei_dataset.py} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename model_zoo/deeplabv3/src/{ei_datasest.py => ei_dataset.py} (100%) diff --git a/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py b/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py index 187fd7ae79..d1b66724af 100644 --- a/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py +++ b/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py @@ -208,7 +208,7 @@ class _DepthwiseConv2dNative(nn.Cell): self.padding = padding self.dilation = dilation self.group = group - if not (isinstance(in_channels, int) and in_channels > 0): + if not (isinstance(in_channels, int) and in_channels > 0): raise ValueError('Attr \'in_channels\' of \'DepthwiseConv2D\' Op passed ' + str(in_channels) + ', should be a int and greater than 0.') if (not isinstance(kernel_size, tuple)) or len(kernel_size) != 2 or \ @@ -526,12 +526,12 @@ class RootBlockBeta(nn.Cell): super(RootBlockBeta, self).__init__() self.conv1 = _conv_bn_relu(3, 64, ksize=3, stride=2, padding=0, pad_mode="valid", use_batch_statistics=fine_tune_batch_norm) self.conv2 = _conv_bn_relu(64, 64, ksize=3, stride=1, padding=0, pad_mode="same", use_batch_statistics=fine_tune_batch_norm) - self.conv3 = _conv_bn_relu(64, 128, ksize=3, stride=1, padding=0, pad_mode="same", use_batch_statistics=fine_tune_batch_norm) + self.conv3 = _conv_bn_relu(64, 128, ksize=3, stride=1, padding=0, pad_m ode="same", use_batch_statistics=fine_tune_batch_norm) def construct(self, x): x = self.conv1(x) x = self.conv2(x) x = self.conv3(x) return x -class resnet50_dl(fine_tune_batch_norm=False): +def resnet50_dl(fine_tune_batch_norm=False): return ResNetV1(fine_tune_batch_norm) diff --git a/model_zoo/deeplabv3/src/ei_datasest.py b/model_zoo/deeplabv3/src/ei_dataset.py similarity index 100% rename from model_zoo/deeplabv3/src/ei_datasest.py rename to model_zoo/deeplabv3/src/ei_dataset.py From cd22b355f9280e33ab145d63eeef86b3369862fc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 03:36:04 +0800 Subject: [PATCH 08/20] modify --- .../{run_distribute_pretrain.sh => run_distribute_train.sh} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename model_zoo/deeplabv3/scripts/{run_distribute_pretrain.sh => run_distribute_train.sh} (95%) diff --git a/model_zoo/deeplabv3/scripts/run_distribute_pretrain.sh b/model_zoo/deeplabv3/scripts/run_distribute_train.sh similarity index 95% rename from model_zoo/deeplabv3/scripts/run_distribute_pretrain.sh rename to model_zoo/deeplabv3/scripts/run_distribute_train.sh index de6f508051..26c5d45303 100644 --- a/model_zoo/deeplabv3/scripts/run_distribute_pretrain.sh +++ b/model_zoo/deeplabv3/scripts/run_distribute_train.sh @@ -16,7 +16,7 @@ echo "==============================================================================================================" echo "Please run the scipt as: " -echo "bash run_distribute_pretrain.sh DEVICE_NUM EPOCH_SIZE DATA_DIR MINDSPORE_HCCL_CONFIG_PATH" +echo "bash run_distribute_train.sh DEVICE_NUM EPOCH_SIZE DATA_DIR MINDSPORE_HCCL_CONFIG_PATH" echo "for example: bash run_distribute_train.sh 8 40 /path/zh-wiki/ /path/hccl.json" echo "It is better to use absolute path." echo "==============================================================================================================" From 67ef8b7aecd6bbbeb48128d7da63dde85b7364ae Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 09:09:10 +0800 Subject: [PATCH 09/20] modify --- model_zoo/deeplabv3/scripts/run_distribute_train.sh | 2 +- model_zoo/deeplabv3/scripts/run_eval.sh | 2 +- model_zoo/deeplabv3/scripts/run_standalone_train.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/model_zoo/deeplabv3/scripts/run_distribute_train.sh b/model_zoo/deeplabv3/scripts/run_distribute_train.sh index 26c5d45303..514b0229af 100644 --- a/model_zoo/deeplabv3/scripts/run_distribute_train.sh +++ b/model_zoo/deeplabv3/scripts/run_distribute_train.sh @@ -58,7 +58,7 @@ do --epoch_size=$EPOCH_SIZE \ --device_id=$DEVICE_ID \ --enable_save_ckpt="true" \ - --checkpoint_url="/store1/deeplabv3/deeplabv3_split_url/train/checkpoint/CKP-12_732.ckpt" \ + --checkpoint_url="" \ --save_checkpoint_steps=10000 \ --save_checkpoint_num=1 \ --data_url=$DATA_DIR > log.txt 2>&1 & diff --git a/model_zoo/deeplabv3/scripts/run_eval.sh b/model_zoo/deeplabv3/scripts/run_eval.sh index a3596e0be3..0d5031124c 100644 --- a/model_zoo/deeplabv3/scripts/run_eval.sh +++ b/model_zoo/deeplabv3/scripts/run_eval.sh @@ -27,5 +27,5 @@ export GLOG_log_dir=${CUR_DIR}/ms_log export GLOG_logtostderr=0 python evaluation.py \ --device_id=$DEVICE_ID \ - --checkpoint_url="/store1/deeplabv3/deeplabv3_split_url/train/checkpoint/CKP-12_732.ckpt" \ + --checkpoint_url="" \ --data_url=$DATA_DIR > log.txt 2>&1 & \ No newline at end of file diff --git a/model_zoo/deeplabv3/scripts/run_standalone_train.sh b/model_zoo/deeplabv3/scripts/run_standalone_train.sh index 91fa03194e..d832782685 100644 --- a/model_zoo/deeplabv3/scripts/run_standalone_train.sh +++ b/model_zoo/deeplabv3/scripts/run_standalone_train.sh @@ -31,7 +31,7 @@ python train.py \ --epoch_size=$EPOCH_SIZE \ --device_id=$DEVICE_ID \ --enable_save_ckpt="true" \ - --checkpoint_url="/store1/deeplabv3/deeplabv3_split_url/train/checkpoint/CKP-12_732.ckpt" \ + --checkpoint_url="" \ --save_checkpoint_steps=10000 \ --save_checkpoint_num=1 \ --data_url=$DATA_DIR > log.txt 2>&1 & \ No newline at end of file From e04cfdf6d88a7268a0cbc9180736e12bb0819d5e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 09:23:18 +0800 Subject: [PATCH 10/20] modify it --- model_zoo/deeplabv3/scripts/run_eval.sh | 1 + model_zoo/deeplabv3/scripts/run_standalone_train.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/model_zoo/deeplabv3/scripts/run_eval.sh b/model_zoo/deeplabv3/scripts/run_eval.sh index 0d5031124c..12505828c6 100644 --- a/model_zoo/deeplabv3/scripts/run_eval.sh +++ b/model_zoo/deeplabv3/scripts/run_eval.sh @@ -1,3 +1,4 @@ +#!/bin/bash # Copyright 2020 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the License); diff --git a/model_zoo/deeplabv3/scripts/run_standalone_train.sh b/model_zoo/deeplabv3/scripts/run_standalone_train.sh index d832782685..1b84f9d583 100644 --- a/model_zoo/deeplabv3/scripts/run_standalone_train.sh +++ b/model_zoo/deeplabv3/scripts/run_standalone_train.sh @@ -1,3 +1,4 @@ +#!/bin/bash # Copyright 2020 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the License); From 4d2b9b10f9354a7e4fbc53c2462b2a8bfb0ff9e2 Mon Sep 17 00:00:00 2001 From: yangyongjie Date: Fri, 29 May 2020 09:54:12 +0800 Subject: [PATCH 11/20] fix pylint problem. --- model_zoo/deeplabv3/src/deeplabv3.py | 44 +++++++++---------- model_zoo/deeplabv3/src/ei_dataset.py | 2 +- model_zoo/deeplabv3/src/md_dataset.py | 23 ++++++++-- .../deeplabv3/src/utils/custom_transforms.py | 14 +++--- model_zoo/deeplabv3/src/utils/file_io.py | 4 +- 5 files changed, 51 insertions(+), 36 deletions(-) diff --git a/model_zoo/deeplabv3/src/deeplabv3.py b/model_zoo/deeplabv3/src/deeplabv3.py index 75e2a87adc..906a207302 100644 --- a/model_zoo/deeplabv3/src/deeplabv3.py +++ b/model_zoo/deeplabv3/src/deeplabv3.py @@ -23,11 +23,11 @@ from .backbone.resnet_deeplab import _conv_bn_relu, resnet50_dl, _deep_conv_bn_r class ASPPSampleBlock(nn.Cell): """ASPP sample block.""" - def __init__(self, feature_shape, scale_size,output_stride): + def __init__(self, feature_shape, scale_size, output_stride): super(ASPPSampleBlock, self).__init__() sample_h = (feature_shape[0] * scale_size + 1) / output_stride + 1 sample_w = (feature_shape[1] * scale_size + 1) / output_stride + 1 - self.sample = P.ResizeBilinear((int(sample_h),int(sample_w)),align_corners=True) + self.sample = P.ResizeBilinear((int(sample_h), int(sample_w)), align_corners=True) def construct(self, x): return self.sample(x) @@ -84,25 +84,25 @@ class ASPP(nn.Cell): aspp_scale_depth_size = np.ceil((feature_shape[0]*scale_size)/16) if atrous_rates is None: break - for i in range(len(atrous_rates)): + for rate in atrous_rates: padding = 0 for j in range(100): - padded_size = atrous_rates[i] * j - if padded_size >= aspp_scale_depth_size + 2 * atrous_rates[i]: - padding = padded_size - aspp_scale_depth_size - 2 * atrous_rates[i] + padded_size = rate * j + if padded_size >= aspp_scale_depth_size + 2 * rate: + padding = padded_size - aspp_scale_depth_size - 2 * rate break - paddings = [[atrous_rates[i], atrous_rates[i] + int(padding)], - [atrous_rates[i], atrous_rates[i] + int(padding)]] - self.aspp_depth_spacetobatch = SpaceToBatch(atrous_rates[i],paddings) + paddings = [[rate, rate + int(padding)], + [rate, rate + int(padding)]] + self.aspp_depth_spacetobatch = SpaceToBatch(rate, paddings) self.aspp_depth_spacetobatchs.append(self.aspp_depth_spacetobatch) - crops =[[0, int(padding)], [0, int(padding)]] - self.aspp_depth_batchtospace = BatchToSpace(atrous_rates[i],crops) + crops = [[0, int(padding)], [0, int(padding)]] + self.aspp_depth_batchtospace = BatchToSpace(rate, crops) self.aspp_depth_batchtospaces.append(self.aspp_depth_batchtospace) self.aspp_depths = nn.CellList(self.aspp_depths) self.aspp_depth_spacetobatchs = nn.CellList(self.aspp_depth_spacetobatchs) self.aspp_depth_batchtospaces = nn.CellList(self.aspp_depth_batchtospaces) - self.global_pooling = nn.AvgPool2d(kernel_size=(int(feature_shape[0]),int(feature_shape[1]))) + self.global_pooling = nn.AvgPool2d(kernel_size=(int(feature_shape[0]), int(feature_shape[1]))) self.global_poolings = [] for scale_size in scale_sizes: pooling_h = np.ceil((feature_shape[0]*scale_size)/output_stride) @@ -116,7 +116,7 @@ class ASPP(nn.Cell): use_batch_statistics=fine_tune_batch_norm) self.samples = [] for scale_size in scale_sizes: - self.samples.append(ASPPSampleBlock(feature_shape,scale_size,output_stride)) + self.samples.append(ASPPSampleBlock(feature_shape, scale_size, output_stride)) self.samples = nn.CellList(self.samples) self.feature_shape = feature_shape self.concat = P.Concat(axis=1) @@ -126,7 +126,7 @@ class ASPP(nn.Cell): aspp1 = self.global_poolings[scale_index](x) aspp1 = self.conv_bn(aspp1) aspp1 = self.samples[scale_index](aspp1) - output = self.concat((aspp1,aspp0)) + output = self.concat((aspp1, aspp0)) for i in range(len(self.atrous_rates)): aspp_i = self.aspp_depth_spacetobatchs[i + scale_index * len(self.atrous_rates)](x) @@ -135,13 +135,13 @@ class ASPP(nn.Cell): aspp_i = self.aspp_depth_bn(aspp_i) aspp_i = self.aspp_depth_relu(aspp_i) aspp_i = self.aspp_pointwise(aspp_i) - output = self.concat((output,aspp_i)) + output = self.concat((output, aspp_i)) return output class DecoderSampleBlock(nn.Cell): """Decoder sample block.""" - def __init__(self,feature_shape,scale_size=1.0,decoder_output_stride=4): + def __init__(self, feature_shape, scale_size=1.0, decoder_output_stride=4): super(DecoderSampleBlock, self).__init__() sample_h = (feature_shape[0] * scale_size + 1) / decoder_output_stride + 1 sample_w = (feature_shape[1] * scale_size + 1) / decoder_output_stride + 1 @@ -206,7 +206,7 @@ class Decoder(nn.Cell): self.concat = P.Concat(axis=1) self.samples = [] for scale_size in scale_sizes: - self.samples.append(DecoderSampleBlock(feature_shape,scale_size,decoder_output_stride)) + self.samples.append(DecoderSampleBlock(feature_shape, scale_size, decoder_output_stride)) self.samples = nn.CellList(self.samples) def construct(self, x, low_level_feature, scale_index): @@ -359,10 +359,10 @@ class DeepLabV3(nn.Cell): self.image_pyramid = image_pyramid scale_sizes = [] - for i in range(len(image_pyramid)): - scale_sizes.append(image_pyramid[i]) - for i in range(len(infer_scale_sizes)): - scale_sizes.append(infer_scale_sizes[i]) + for pyramid in image_pyramid: + scale_sizes.append(pyramid) + for scale in infer_scale_sizes: + scale_sizes.append(scale) self.samples = [] for scale_size in scale_sizes: self.samples.append(SampleBlock(feature_shape, scale_size)) @@ -454,4 +454,4 @@ def deeplabv3_resnet50(num_classes, feature_shape, image_pyramid, decoder_output_stride=decoder_output_stride, output_stride=output_stride, fine_tune_batch_norm=fine_tune_batch_norm, - image_pyramid=image_pyramid) \ No newline at end of file + image_pyramid=image_pyramid) diff --git a/model_zoo/deeplabv3/src/ei_dataset.py b/model_zoo/deeplabv3/src/ei_dataset.py index c139bf48e5..8b471065ae 100644 --- a/model_zoo/deeplabv3/src/ei_dataset.py +++ b/model_zoo/deeplabv3/src/ei_dataset.py @@ -20,7 +20,7 @@ import time from .utils.adapter import get_raw_samples, read_image -class BaseDataset(object): +class BaseDataset: """ Create dataset. diff --git a/model_zoo/deeplabv3/src/md_dataset.py b/model_zoo/deeplabv3/src/md_dataset.py index f800f7e12f..37b57d1033 100644 --- a/model_zoo/deeplabv3/src/md_dataset.py +++ b/model_zoo/deeplabv3/src/md_dataset.py @@ -21,7 +21,7 @@ from .ei_dataset import HwVocRawDataset from .utils import custom_transforms as tr -class DataTransform(object): +class DataTransform: """Transform dataset for DeepLabV3.""" def __init__(self, args, usage): @@ -29,12 +29,20 @@ class DataTransform(object): self.usage = usage def __call__(self, image, label): - if "train" == self.usage: + if self.usage == "train": return self._train(image, label) - elif "eval" == self.usage: + if self.usage == "eval": return self._eval(image, label) + return None def _train(self, image, label): + """ + Process training data. + + Args: + image (list): Image data. + label (list): Dataset label. + """ image = Image.fromarray(image) label = Image.fromarray(label) @@ -50,6 +58,13 @@ class DataTransform(object): return image, label def _eval(self, image, label): + """ + Process eval data. + + Args: + image (list): Image data. + label (list): Dataset label. + """ image = Image.fromarray(image) label = Image.fromarray(label) @@ -93,7 +108,7 @@ def create_dataset(args, data_url, epoch_num=1, batch_size=1, usage="train"): # 3658 steps / 183 = 20 epochs if usage == "train": dataset = dataset.shuffle(1464) - dataset = dataset.batch(batch_size, drop_remainder=(usage == usage)) + dataset = dataset.batch(batch_size, drop_remainder=(usage == "train")) dataset = dataset.repeat(count=epoch_num) dataset.map_model = 4 diff --git a/model_zoo/deeplabv3/src/utils/custom_transforms.py b/model_zoo/deeplabv3/src/utils/custom_transforms.py index ddf544ea72..3473f7eef5 100644 --- a/model_zoo/deeplabv3/src/utils/custom_transforms.py +++ b/model_zoo/deeplabv3/src/utils/custom_transforms.py @@ -19,7 +19,7 @@ import numpy as np from PIL import Image, ImageOps, ImageFilter -class Normalize(object): +class Normalize: """Normalize a tensor image with mean and standard deviation. Args: mean (tuple): means for each channel. @@ -37,7 +37,7 @@ class Normalize(object): return img, mask -class RandomHorizontalFlip(object): +class RandomHorizontalFlip: """Randomly decide whether to horizontal flip.""" def __call__(self, img, mask): if random.random() < 0.5: @@ -47,7 +47,7 @@ class RandomHorizontalFlip(object): return img, mask -class RandomRotate(object): +class RandomRotate: """ Randomly decide whether to rotate. @@ -65,7 +65,7 @@ class RandomRotate(object): return img, mask -class RandomGaussianBlur(object): +class RandomGaussianBlur: """Randomly decide whether to filter image with gaussian blur.""" def __call__(self, img, mask): if random.random() < 0.5: @@ -75,7 +75,7 @@ class RandomGaussianBlur(object): return img, mask -class RandomScaleCrop(object): +class RandomScaleCrop: """Randomly decide whether to scale and crop image.""" def __init__(self, base_size, crop_size, fill=0): self.base_size = base_size @@ -110,7 +110,7 @@ class RandomScaleCrop(object): return img, mask -class FixScaleCrop(object): +class FixScaleCrop: """Scale and crop image with fixing size.""" def __init__(self, crop_size): self.crop_size = crop_size @@ -135,7 +135,7 @@ class FixScaleCrop(object): return img, mask -class FixedResize(object): +class FixedResize: """Resize image with fixing size.""" def __init__(self, size): self.size = (size, size) diff --git a/model_zoo/deeplabv3/src/utils/file_io.py b/model_zoo/deeplabv3/src/utils/file_io.py index a8fa34811d..9d6db034f3 100644 --- a/model_zoo/deeplabv3/src/utils/file_io.py +++ b/model_zoo/deeplabv3/src/utils/file_io.py @@ -1,4 +1,3 @@ -#!/bin/bash # Copyright 2020 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -13,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================ +"""File operation module.""" import os @@ -33,4 +33,4 @@ def walk(url): if _is_obs(url): # TODO read cloud file. return None - return os.walk(url) \ No newline at end of file + return os.walk(url) From 91adbf7e2c83049a3912e38ba7bdaee881ea5479 Mon Sep 17 00:00:00 2001 From: yangyongjie Date: Fri, 29 May 2020 10:05:23 +0800 Subject: [PATCH 12/20] pylint fix --- model_zoo/deeplabv3/src/losses.py | 32 +++++++++-------------- model_zoo/deeplabv3/src/miou_precision.py | 21 ++++++++++----- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/model_zoo/deeplabv3/src/losses.py b/model_zoo/deeplabv3/src/losses.py index ebecd54aea..051cc1b1f9 100644 --- a/model_zoo/deeplabv3/src/losses.py +++ b/model_zoo/deeplabv3/src/losses.py @@ -1,4 +1,3 @@ -#!/bin/bash # Copyright 2020 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,11 +15,12 @@ """OhemLoss.""" import mindspore.nn as nn import mindspore.common.dtype as mstype -from mindspore import Tensor from mindspore.ops import operations as P from mindspore.ops import functional as F - + + class OhemLoss(nn.Cell): + """Ohem loss cell.""" def __init__(self, num, ignore_label): super(OhemLoss, self).__init__() self.mul = P.Mul() @@ -40,30 +40,24 @@ class OhemLoss(nn.Cell): self.transpose = P.Transpose() self.ignore_label = ignore_label self.loss_weight = 1.0 - + def construct(self, logits, labels): - logits = self.transpose(logits,(0,2,3,1)) - logits = self.reshape(logits, (-1,self.num)) - labels = F.cast(labels,mstype.int32) + logits = self.transpose(logits, (0, 2, 3, 1)) + logits = self.reshape(logits, (-1, self.num)) + labels = F.cast(labels, mstype.int32) labels = self.reshape(labels, (-1,)) one_hot_labels = self.one_hot(labels) losses = self.cross_entropy(logits, one_hot_labels)[0] - weights = self.cast(self.not_equal(labels,self.ignore_label),mstype.float32) * self.loss_weight + weights = self.cast(self.not_equal(labels, self.ignore_label), mstype.float32) * self.loss_weight weighted_losses = self.mul(losses, weights) loss = self.reduce_sum(weighted_losses,(0,)) zeros = self.fill(mstype.float32, self.shape(weights), 0.0) ones = self.fill(mstype.float32, self.shape(weights), 1.0) - present = self.select( - self.equal(weights, zeros), - zeros, - ones) - present = self.reduce_sum(present,(0,)) - + present = self.select(self.equal(weights, zeros), zeros, ones) + present = self.reduce_sum(present, (0,)) + zeros = self.fill(mstype.float32, self.shape(present), 0.0) min_control = self.fill(mstype.float32, self.shape(present), 1.0) - present = self.select( - self.equal(present, zeros), - min_control, - present) + present = self.select(self.equal(present, zeros), min_control, present) loss = loss / present - return loss \ No newline at end of file + return loss diff --git a/model_zoo/deeplabv3/src/miou_precision.py b/model_zoo/deeplabv3/src/miou_precision.py index 03273b5b0c..ea2e975d81 100644 --- a/model_zoo/deeplabv3/src/miou_precision.py +++ b/model_zoo/deeplabv3/src/miou_precision.py @@ -1,4 +1,3 @@ -#!/bin/bash # Copyright 2020 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,15 +15,22 @@ """mIou.""" import numpy as np from mindspore.nn.metrics.metric import Metric + + def confuse_matrix(target, pred, n): k = (target >= 0) & (target < n) return np.bincount(n * target[k].astype(int) + pred[k], minlength=n ** 2).reshape(n, n) + + def iou(hist): denominator = hist.sum(1) + hist.sum(0) - np.diag(hist) res = np.diag(hist) / np.where(denominator > 0, denominator, 1) res = np.sum(res) / np.count_nonzero(denominator) return res + + class MiouPrecision(Metric): + """Calculate miou precision.""" def __init__(self, num_class=21): super(MiouPrecision, self).__init__() if not isinstance(num_class, int): @@ -32,11 +38,13 @@ class MiouPrecision(Metric): if num_class < 1: raise ValueError('num_class must be at least 1, but got {}'.format(num_class)) self._num_class = num_class - self._mIoU=[] + self._mIoU = [] self.clear() + def clear(self): self._hist = np.zeros((self._num_class, self._num_class)) - self._mIoU=[] + self._mIoU = [] + def update(self, *inputs): if len(inputs) != 2: raise ValueError('Need 2 inputs (y_pred, y), but got {}'.format(len(inputs))) @@ -45,8 +53,7 @@ class MiouPrecision(Metric): if predict_in.shape[1] != self._num_class: raise ValueError('Class number not match, last input data contain {} classes, but current data contain {} ' 'classes'.format(self._num_class, predict_in.shape[1])) - batch_size = predict_in.shape[0] - pred = np.argmax(predict_in,axis=1) + pred = np.argmax(predict_in, axis=1) label = label_in if len(label.flatten()) != len(pred.flatten()): print('Skipping: len(gt) = {:d}, len(pred) = {:d}'.format(len(label.flatten()), len(pred.flatten()))) @@ -60,6 +67,6 @@ class MiouPrecision(Metric): """ Computes the mIoU categorical accuracy. """ - mIoU=np.nanmean(self._mIoU) + mIoU = np.nanmean(self._mIoU) print('mIoU = {}'.format(mIoU)) - return mIoU \ No newline at end of file + return mIoU From 2d433e640864d77a1612df9126df0ecd79735851 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 10:11:23 +0800 Subject: [PATCH 13/20] modify --- model_zoo/deeplabv3/evaluation.py | 28 ++++++++++----------------- model_zoo/deeplabv3/train.py | 32 +++++++++++++------------------ 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/model_zoo/deeplabv3/evaluation.py b/model_zoo/deeplabv3/evaluation.py index f4e3e38d9f..2c03467587 100644 --- a/model_zoo/deeplabv3/evaluation.py +++ b/model_zoo/deeplabv3/evaluation.py @@ -1,4 +1,3 @@ -#!/bin/bash # Copyright 2020 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,21 +13,13 @@ # limitations under the License. # ============================================================================ """evaluation.""" -import os, time import argparse from mindspore import context -from mindspore import log as logger -from mindspore.communication.management import init -import mindspore.nn as nn -from mindspore.nn.optim.momentum import Momentum -from mindspore.train.loss_scale_manager import FixedLossScaleManager -from mindspore import Model, ParallelMode -import argparse +from mindspore import Model from mindspore.train.serialization import load_checkpoint, load_param_into_net -from mindspore.train.callback import Callback,CheckpointConfig, ModelCheckpoint, TimeMonitor from src.md_dataset import create_dataset from src.losses import OhemLoss -from src.miou_precision import MiouPrecision +from src.miou_precision import MiouPrecision from src.deeplabv3 import deeplabv3_resnet50 from src.config import config parser = argparse.ArgumentParser(description="Deeplabv3 evaluation") @@ -44,15 +35,16 @@ print(args_opt) if __name__ == "__main__": args_opt.crop_size = config.crop_size args_opt.base_size = config.crop_size - eval_dataset = create_dataset(args_opt, args_opt.data_url, args_opt.epoch_size, args_opt.batch_size, usage="eval") - net = deeplabv3_resnet50(config.seg_num_classes, [args_opt.batch_size,3,args_opt.crop_size,args_opt.crop_size], - infer_scale_sizes=config.eval_scales, atrous_rates=config.atrous_rates, - decoder_output_stride=config.decoder_output_stride, output_stride = config.output_stride, - fine_tune_batch_norm=config.fine_tune_batch_norm, image_pyramid = config.image_pyramid) + eval_dataset = create_dataset(args_opt, args_opt.data_url, args_opt.epoch_size, args_opt.batch_size, usage="eval") + net = deeplabv3_resnet50(config.seg_num_classes, [args_opt.batch_size, 3, args_opt.crop_size, args_opt.crop_size], + infer_scale_sizes=config.eval_scales, atrous_rates=config.atrous_rates, + decoder_output_stride=config.decoder_output_stride, output_stride=config.output_stride, + fine_tune_batch_norm=config.fine_tune_batch_norm, image_pyramid=config.image_pyramid) param_dict = load_checkpoint(args_opt.checkpoint_url) load_param_into_net(net, param_dict) mIou = MiouPrecision(config.seg_num_classes) - metrics={'mIou':mIou} + metrics = {'mIou': mIou} loss = OhemLoss(config.seg_num_classes, config.ignore_label) model = Model(net, loss, metrics=metrics) - model.eval(eval_dataset) \ No newline at end of file + model.eval(eval_dataset) + \ No newline at end of file diff --git a/model_zoo/deeplabv3/train.py b/model_zoo/deeplabv3/train.py index ed625ede6b..237d2f4800 100644 --- a/model_zoo/deeplabv3/train.py +++ b/model_zoo/deeplabv3/train.py @@ -1,4 +1,3 @@ -#!/bin/bash # Copyright 2020 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,18 +13,13 @@ # limitations under the License. # ============================================================================ """train.""" -import os, time import argparse from mindspore import context -from mindspore import log as logger from mindspore.communication.management import init -import mindspore.nn as nn from mindspore.nn.optim.momentum import Momentum -from mindspore.train.loss_scale_manager import FixedLossScaleManager from mindspore import Model, ParallelMode -import argparse from mindspore.train.serialization import load_checkpoint, load_param_into_net -from mindspore.train.callback import Callback,CheckpointConfig, ModelCheckpoint, TimeMonitor +from mindspore.train.callback import Callback, CheckpointConfig, ModelCheckpoint, TimeMonitor from src.md_dataset import create_dataset from src.losses import OhemLoss from src.deeplabv3 import deeplabv3_resnet50 @@ -40,8 +34,7 @@ parser.add_argument("--device_id", type=int, default=0, help="Device id, default parser.add_argument('--checkpoint_url', default=None, help='Checkpoint path') parser.add_argument("--enable_save_ckpt", type=str, default="true", help="Enable save checkpoint, default is true.") parser.add_argument('--max_checkpoint_num', type=int, default=5, help='Max checkpoint number.') -parser.add_argument("--save_checkpoint_steps", type=int, default=1000, help="Save checkpoint steps, " - "default is 1000.") +parser.add_argument("--save_checkpoint_steps", type=int, default=1000, help="Save checkpoint steps, default is 1000.") parser.add_argument("--save_checkpoint_num", type=int, default=1, help="Save checkpoint numbers, default is 1.") args_opt = parser.parse_args() print(args_opt) @@ -63,22 +56,22 @@ class LossCallBack(Callback): cb_params = run_context.original_args() print("epoch: {}, step: {}, outputs are {}".format(cb_params.cur_epoch_num, cb_params.cur_step_num, str(cb_params.net_outputs))) -def model_fine_tune(flags, net, fix_weight_layer): +def model_fine_tune(flags, train_net, fix_weight_layer): checkpoint_path = flags.checkpoint_url if checkpoint_path is None: return param_dict = load_checkpoint(checkpoint_path) - load_param_into_net(net, param_dict) - for para in net.trainable_params(): + load_param_into_net(train_net, param_dict) + for para in train_net.trainable_params(): if fix_weight_layer in para.name: - para.requires_grad=False + para.requires_grad = False if __name__ == "__main__": if args_opt.distribute == "true": context.set_auto_parallel_context(parallel_mode=ParallelMode.DATA_PARALLEL, mirror_mean=True) init() args_opt.base_size = config.crop_size args_opt.crop_size = config.crop_size - train_dataset = create_dataset(args_opt, args_opt.data_url, args_opt.epoch_size, args_opt.batch_size, usage="train") + train_dataset = create_dataset(args_opt, args_opt.data_url, args_opt.epoch_size, args_opt.batch_size, usage="train") dataset_size = train_dataset.get_dataset_size() time_cb = TimeMonitor(data_size=dataset_size) callback = [time_cb, LossCallBack()] @@ -87,13 +80,14 @@ if __name__ == "__main__": keep_checkpoint_max=args_opt.save_checkpoint_num) ckpoint_cb = ModelCheckpoint(prefix='checkpoint_deeplabv3', config=config_ck) callback.append(ckpoint_cb) - net = deeplabv3_resnet50(config.seg_num_classes, [args_opt.batch_size,3,args_opt.crop_size,args_opt.crop_size], - infer_scale_sizes=config.eval_scales, atrous_rates=config.atrous_rates, - decoder_output_stride=config.decoder_output_stride, output_stride = config.output_stride, - fine_tune_batch_norm=config.fine_tune_batch_norm, image_pyramid = config.image_pyramid) + net = deeplabv3_resnet50(config.seg_num_classes, [args_opt.batch_size, 3, args_opt.crop_size, args_opt.crop_size], + infer_scale_sizes=config.eval_scales, atrous_rates=config.atrous_rates, + decoder_output_stride=config.decoder_output_stride, output_stride=config.output_stride, + fine_tune_batch_norm=config.fine_tune_batch_norm, image_pyramid=config.image_pyramid) net.set_train() model_fine_tune(args_opt, net, 'layer') loss = OhemLoss(config.seg_num_classes, config.ignore_label) opt = Momentum(filter(lambda x: 'beta' not in x.name and 'gamma' not in x.name and 'depth' not in x.name and 'bias' not in x.name, net.trainable_params()), learning_rate=config.learning_rate, momentum=config.momentum, weight_decay=config.weight_decay) model = Model(net, loss, opt) - model.train(args_opt.epoch_size, train_dataset, callback) \ No newline at end of file + model.train(args_opt.epoch_size, train_dataset, callback) + \ No newline at end of file From 52c59900a7f99b685a0229eb64a6c7f658b31cad Mon Sep 17 00:00:00 2001 From: yangyongjie Date: Fri, 29 May 2020 10:43:36 +0800 Subject: [PATCH 14/20] fix pylint problem --- model_zoo/deeplabv3/src/__init__.py | 3 +- model_zoo/deeplabv3/src/backbone/__init__.py | 23 ++- .../deeplabv3/src/backbone/resnet_deeplab.py | 152 +++++++++++------- model_zoo/deeplabv3/src/config.py | 2 +- model_zoo/deeplabv3/src/utils/__init__.py | 3 +- 5 files changed, 117 insertions(+), 66 deletions(-) diff --git a/model_zoo/deeplabv3/src/__init__.py b/model_zoo/deeplabv3/src/__init__.py index 1cce2ac0db..64d0707992 100644 --- a/model_zoo/deeplabv3/src/__init__.py +++ b/model_zoo/deeplabv3/src/__init__.py @@ -14,11 +14,10 @@ # ============================================================================ """Init DeepLabv3.""" from .deeplabv3 import ASPP, DeepLabV3, deeplabv3_resnet50 -from . import backbone from .backbone import * __all__ = [ - "ASPP", "DeepLabV3", "deeplabv3_resnet50", "Decoder" + "ASPP", "DeepLabV3", "deeplabv3_resnet50" ] __all__.extend(backbone.__all__) diff --git a/model_zoo/deeplabv3/src/backbone/__init__.py b/model_zoo/deeplabv3/src/backbone/__init__.py index 4ccf212619..005e41d8b5 100644 --- a/model_zoo/deeplabv3/src/backbone/__init__.py +++ b/model_zoo/deeplabv3/src/backbone/__init__.py @@ -1,8 +1,21 @@ +# Copyright 2020 Huawei Technologies Co., Ltd +# +# 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 +# +# httpwww.apache.orglicensesLICENSE-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. +# ============================================================================ +"""Init backbone.""" from .resnet_deeplab import Subsample, DepthwiseConv2dNative, SpaceToBatch, BatchToSpace, ResNetV1, \ RootBlockBeta, resnet50_dl - -__all__= [ - "Subsample", "DepthwiseConv2dNative", "SpaceToBatch", "BatchToSpace", "ResNetV1", "RootBlockBeta", - "resnet50_dl" + +__all__ = [ + "Subsample", "DepthwiseConv2dNative", "SpaceToBatch", "BatchToSpace", "ResNetV1", "RootBlockBeta", "resnet50_dl" ] - \ No newline at end of file diff --git a/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py b/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py index d1b66724af..76abe29d12 100644 --- a/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py +++ b/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py @@ -1,4 +1,3 @@ -#!/bin/bash # Copyright 2020 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,12 +15,11 @@ """ResNet based DeepLab.""" import mindspore.nn as nn from mindspore.ops import operations as P -from mindspore import Tensor -import numpy as np -from mindspore.common.initializer import TruncatedNormal, initializer -from mindspore._checkparam import check_bool, twice -from mindspore import log as logger +from mindspore.common.initializer import initializer +from mindspore._checkparam import twice from mindspore.common.parameter import Parameter + + def _conv_bn_relu(in_channel, out_channel, ksize, @@ -42,52 +40,58 @@ def _conv_bn_relu(in_channel, nn.BatchNorm2d(out_channel, use_batch_statistics=use_batch_statistics), nn.ReLU()] ) + + def _deep_conv_bn_relu(in_channel, - channel_multiplier, - ksize, - stride=1, - padding=0, - dilation=1, - pad_mode="pad", - use_batch_statistics=False): + channel_multiplier, + ksize, + stride=1, + padding=0, + dilation=1, + pad_mode="pad", + use_batch_statistics=False): """Get a spacetobatch -> conv2d -> batchnorm -> relu -> batchtospace layer""" return nn.SequentialCell( [DepthwiseConv2dNative(in_channel, - channel_multiplier, - kernel_size=ksize, - stride=stride, - padding=padding, - dilation=dilation, - pad_mode=pad_mode), + channel_multiplier, + kernel_size=ksize, + stride=stride, + padding=padding, + dilation=dilation, + pad_mode=pad_mode), nn.BatchNorm2d(channel_multiplier * in_channel, use_batch_statistics=use_batch_statistics), nn.ReLU()] ) + + def _stob_deep_conv_btos_bn_relu(in_channel, - channel_multiplier, - ksize, - space_to_batch_block_shape, - batch_to_space_block_shape, - paddings, - crops, - stride=1, - padding=0, - dilation=1, - pad_mode="pad", - use_batch_statistics=False): + channel_multiplier, + ksize, + space_to_batch_block_shape, + batch_to_space_block_shape, + paddings, + crops, + stride=1, + padding=0, + dilation=1, + pad_mode="pad", + use_batch_statistics=False): """Get a spacetobatch -> conv2d -> batchnorm -> relu -> batchtospace layer""" return nn.SequentialCell( - [SpaceToBatch(space_to_batch_block_shape,paddings), + [SpaceToBatch(space_to_batch_block_shape, paddings), DepthwiseConv2dNative(in_channel, - channel_multiplier, - kernel_size=ksize, - stride=stride, - padding=padding, - dilation=dilation, - pad_mode=pad_mode), - BatchToSpace(batch_to_space_block_shape,crops), + channel_multiplier, + kernel_size=ksize, + stride=stride, + padding=padding, + dilation=dilation, + pad_mode=pad_mode), + BatchToSpace(batch_to_space_block_shape, crops), nn.BatchNorm2d(channel_multiplier * in_channel, use_batch_statistics=use_batch_statistics), nn.ReLU()] - ) + ) + + def _stob_conv_btos_bn_relu(in_channel, out_channel, ksize, @@ -114,6 +118,8 @@ def _stob_conv_btos_bn_relu(in_channel, nn.BatchNorm2d(out_channel,use_batch_statistics=use_batch_statistics), nn.ReLU()] ) + + def _make_layer(block, in_channels, out_channels, @@ -153,6 +159,8 @@ def _make_layer(block, in_channels = out_channels layer = nn.SequentialCell(blocks) return layer, g_current_stride, g_rate + + class Subsample(nn.Cell): """ Subsample for DeepLab-ResNet. @@ -168,26 +176,35 @@ class Subsample(nn.Cell): self.factor = factor self.pool = nn.MaxPool2d(kernel_size=1, stride=factor) + def construct(self, x): if self.factor == 1: return x return self.pool(x) + + class SpaceToBatch(nn.Cell): def __init__(self, block_shape, paddings): super(SpaceToBatch, self).__init__() self.space_to_batch = P.SpaceToBatch(block_shape, paddings) self.bs = block_shape self.pd = paddings + def construct(self, x): return self.space_to_batch(x) + + class BatchToSpace(nn.Cell): def __init__(self, block_shape, crops): super(BatchToSpace, self).__init__() self.batch_to_space = P.BatchToSpace(block_shape, crops) self.bs = block_shape self.cr = crops + def construct(self, x): return self.batch_to_space(x) + + class _DepthwiseConv2dNative(nn.Cell): def __init__(self, in_channels, @@ -218,9 +235,12 @@ class _DepthwiseConv2dNative(nn.Cell): + str(self.kernel_size) + ', should be a int or tuple and equal to or greater than 1.') self.weight = Parameter(initializer(weight_init, [1, in_channels // group, *kernel_size]), name='weight') + def construct(self, *inputs): """Must be overridden by all subclasses.""" raise NotImplementedError + + class DepthwiseConv2dNative(_DepthwiseConv2dNative): def __init__(self, in_channels, @@ -244,18 +264,22 @@ class DepthwiseConv2dNative(_DepthwiseConv2dNative): group, weight_init) self.depthwise_conv2d_native = P.DepthwiseConv2dNative(channel_multiplier=self.channel_multiplier, - kernel_size=self.kernel_size, - mode=3, - pad_mode=self.pad_mode, - pad=self.padding, - stride=self.stride, - dilation=self.dilation, - group=self.group) + kernel_size=self.kernel_size, + mode=3, + pad_mode=self.pad_mode, + pad=self.padding, + stride=self.stride, + dilation=self.dilation, + group=self.group) + def set_strategy(self, strategy): self.depthwise_conv2d_native.set_strategy(strategy) return self + def construct(self, x): return self.depthwise_conv2d_native(x, self.weight) + + class BottleneckV1(nn.Cell): """ ResNet V1 BottleneckV1 block definition. @@ -322,6 +346,7 @@ class BottleneckV1(nn.Cell): self.add = P.TensorAdd() self.relu = nn.ReLU() self.Reshape = P.Reshape() + def construct(self, x): out = self.conv_bn1(x) out = self.conv_bn2(out) @@ -329,8 +354,8 @@ class BottleneckV1(nn.Cell): out = self.add(out, self.downsample(x)) out = self.relu(out) return out - return out - + + class BottleneckV2(nn.Cell): """ ResNet V2 Bottleneck variance V2 block definition. @@ -365,7 +390,7 @@ class BottleneckV2(nn.Cell): padding=1, dilation=dilation, use_batch_statistics=use_batch_statistics) - if use_batch_to_stob_and_btos == True: + if use_batch_to_stob_and_btos: self.conv_bn2 = _stob_conv_btos_bn_relu(mid_channels, mid_channels, ksize=3, @@ -394,6 +419,7 @@ class BottleneckV2(nn.Cell): self.downsample = Subsample(stride) self.add = P.TensorAdd() self.relu = nn.ReLU() + def construct(self, x): out = self.conv_bn1(x) out = self.conv_bn2(out) @@ -402,6 +428,7 @@ class BottleneckV2(nn.Cell): out = self.relu(out) return out + class BottleneckV3(nn.Cell): """ ResNet V1 Bottleneck variance V1 block definition. @@ -452,6 +479,7 @@ class BottleneckV3(nn.Cell): self.downsample = Subsample(stride) self.add = P.TensorAdd() self.relu = nn.ReLU() + def construct(self, x): out = self.conv_bn1(x) out = self.conv_bn2(out) @@ -460,6 +488,7 @@ class BottleneckV3(nn.Cell): out = self.relu(out) return out + class ResNetV1(nn.Cell): """ ResNet V1 for DeepLab. @@ -491,9 +520,13 @@ class ResNetV1(nn.Cell): self.layer3_5 = BottleneckV2(1024, 1024, stride=1, use_batch_statistics=fine_tune_batch_norm) self.layer3_6 = BottleneckV2(1024, 1024, stride=1, use_batch_statistics=fine_tune_batch_norm) - self.layer4_1 = BottleneckV1(1024, 2048, stride=1, use_batch_to_stob_and_btos=True, use_batch_statistics=fine_tune_batch_norm) - self.layer4_2 = BottleneckV2(2048, 2048, stride=1, use_batch_to_stob_and_btos=True, use_batch_statistics=fine_tune_batch_norm) - self.layer4_3 = BottleneckV2(2048, 2048, stride=1, use_batch_to_stob_and_btos=True, use_batch_statistics=fine_tune_batch_norm) + self.layer4_1 = BottleneckV1(1024, 2048, stride=1, use_batch_to_stob_and_btos=True, + use_batch_statistics=fine_tune_batch_norm) + self.layer4_2 = BottleneckV2(2048, 2048, stride=1, use_batch_to_stob_and_btos=True, + use_batch_statistics=fine_tune_batch_norm) + self.layer4_3 = BottleneckV2(2048, 2048, stride=1, use_batch_to_stob_and_btos=True, + use_batch_statistics=fine_tune_batch_norm) + def construct(self, x): x = self.layer_root(x) x = self.layer1_1(x) @@ -514,6 +547,8 @@ class ResNetV1(nn.Cell): x = self.layer4_2(x) c5 = self.layer4_3(x) return c2, c5 + + class RootBlockBeta(nn.Cell): """ ResNet V1 beta root block definition. @@ -524,14 +559,19 @@ class RootBlockBeta(nn.Cell): """ def __init__(self, fine_tune_batch_norm=False): super(RootBlockBeta, self).__init__() - self.conv1 = _conv_bn_relu(3, 64, ksize=3, stride=2, padding=0, pad_mode="valid", use_batch_statistics=fine_tune_batch_norm) - self.conv2 = _conv_bn_relu(64, 64, ksize=3, stride=1, padding=0, pad_mode="same", use_batch_statistics=fine_tune_batch_norm) - self.conv3 = _conv_bn_relu(64, 128, ksize=3, stride=1, padding=0, pad_m ode="same", use_batch_statistics=fine_tune_batch_norm) + self.conv1 = _conv_bn_relu(3, 64, ksize=3, stride=2, padding=0, pad_mode="valid", + use_batch_statistics=fine_tune_batch_norm) + self.conv2 = _conv_bn_relu(64, 64, ksize=3, stride=1, padding=0, pad_mode="same", + use_batch_statistics=fine_tune_batch_norm) + self.conv3 = _conv_bn_relu(64, 128, ksize=3, stride=1, padding=0, pad_mode="same", + use_batch_statistics=fine_tune_batch_norm) + def construct(self, x): x = self.conv1(x) x = self.conv2(x) x = self.conv3(x) return x - + + def resnet50_dl(fine_tune_batch_norm=False): return ResNetV1(fine_tune_batch_norm) diff --git a/model_zoo/deeplabv3/src/config.py b/model_zoo/deeplabv3/src/config.py index 742592fc19..c3b73e1097 100644 --- a/model_zoo/deeplabv3/src/config.py +++ b/model_zoo/deeplabv3/src/config.py @@ -30,4 +30,4 @@ config = ed({ "ignore_label": 255, "decoder_output_stride": None, "seg_num_classes": 21 -}) \ No newline at end of file +}) diff --git a/model_zoo/deeplabv3/src/utils/__init__.py b/model_zoo/deeplabv3/src/utils/__init__.py index 457700a020..e30774307c 100644 --- a/model_zoo/deeplabv3/src/utils/__init__.py +++ b/model_zoo/deeplabv3/src/utils/__init__.py @@ -1,4 +1,3 @@ -#!/bin/bash # Copyright 2020 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,4 +11,4 @@ # 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. -# ============================================================================ \ No newline at end of file +# ============================================================================ From eef3c58b5ec5c84d81340f1a124178d97a45eb3d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 11:47:13 +0800 Subject: [PATCH 15/20] modify --- model_zoo/deeplabv3/README.md | 64 +++++++++++++++++++++++++ model_zoo/deeplabv3/evaluation.py | 2 +- model_zoo/deeplabv3/readme.txt | 0 model_zoo/deeplabv3/scripts/run_eval.sh | 4 +- model_zoo/deeplabv3/train.py | 5 +- 5 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 model_zoo/deeplabv3/README.md delete mode 100644 model_zoo/deeplabv3/readme.txt diff --git a/model_zoo/deeplabv3/README.md b/model_zoo/deeplabv3/README.md new file mode 100644 index 0000000000..977da7040a --- /dev/null +++ b/model_zoo/deeplabv3/README.md @@ -0,0 +1,64 @@ +Deeplab-V3 Example + +Description +This is an example of training DeepLabv3 with PASCAL VOC 2012 dataset in MindSpore. +Paper Rethinking Atrous Convolution for Semantic Image Segmentation +Liang-Chieh Chen, George Papandreou, Florian Schroff, Hartwig Adam + + +Requirements +Install MindSpore. +Download the VOC 2012 dataset for training. +For more information, please check the resources below: +MindSpore tutorials +MindSpore API + +Notes: If you are running a fine-tuning or evaluation task, prepare the corresponding checkpoint file. + + +Running the Example + +Training +Set options in config.py. +Run run_standalone_train.sh for non-distributed training. +sh scripts/run_standalone_train.sh DEVICE_ID EPOCH_SIZE DATA_DIR +Run run_distribute_train.sh for distributed training. +sh scripts/run_distribute_train.sh DEVICE_NUM EPOCH_SIZE DATA_DIR MINDSPORE_HCCL_CONFIG_PATH + +Evaluation +Set options in evaluation_config.py. Make sure the 'data_file' and 'finetune_ckpt' are set to your own path. +Run run_eval.sh for evaluation. +sh scripts/run_eval.sh DEVICE_ID DATA_DIR + +Options and Parameters +It contains of parameters of Deeplab-V3 model and options for training, which is set in file config.py. + +Options: +config.py: + learning_rate Learning rate, default is 0.0014. + weight_decay Weight decay, default is 5e-5. + momentum Momentum, default is 0.97. + crop_size Image crop size [height, width] during training, default is 513. + eval_scales The scales to resize images for evaluation, default is [0.5, 0.75, 1.0, 1.25, 1.5, 1.75]. + output_stride The ratio of input to output spatial resolution, default is 16. + ignore_label Ignore label value, default is 255. + seg_num_classes Number of semantic classes, including the background class (if exists). + foreground classes + 1 background class in the PASCAL VOC 2012 dataset, default is 21. + fine_tune_batch_norm Fine tune the batch norm parameters or not, default is False. + atrous_rates Atrous rates for atrous spatial pyramid pooling, default is None. + decoder_output_stride The ratio of input to output spatial resolution when employing decoder + to refine segmentation results, default is None. + image_pyramid Input scales for multi-scale feature extraction, default is None. + + + +Parameters: +Parameters for dataset and network: + distribute Run distribute, default is false. + epoch_size Epoch size, default is 6. + batch_size batch size of input dataset: N, default is 2. + data_url Train/Evaluation data url, required. + checkpoint_url Checkpoint path, default is None. + enable_save_ckpt Enable save checkpoint, default is true. + save_checkpoint_steps Save checkpoint steps, default is 1000. + save_checkpoint_num Save checkpoint numbers, default is 1. \ No newline at end of file diff --git a/model_zoo/deeplabv3/evaluation.py b/model_zoo/deeplabv3/evaluation.py index 2c03467587..09c9a2b692 100644 --- a/model_zoo/deeplabv3/evaluation.py +++ b/model_zoo/deeplabv3/evaluation.py @@ -26,7 +26,7 @@ parser = argparse.ArgumentParser(description="Deeplabv3 evaluation") parser.add_argument('--epoch_size', type=int, default=2, help='Epoch size.') parser.add_argument("--device_id", type=int, default=0, help="Device id, default is 0.") parser.add_argument('--batch_size', type=int, default=2, help='Batch size.') -parser.add_argument('--data_url', required=True, default=None, help='Train data url') +parser.add_argument('--data_url', required=True, default=None, help='Evaluation data url') parser.add_argument('--checkpoint_url', default=None, help='Checkpoint path') args_opt = parser.parse_args() diff --git a/model_zoo/deeplabv3/readme.txt b/model_zoo/deeplabv3/readme.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/model_zoo/deeplabv3/scripts/run_eval.sh b/model_zoo/deeplabv3/scripts/run_eval.sh index 12505828c6..2470138c33 100644 --- a/model_zoo/deeplabv3/scripts/run_eval.sh +++ b/model_zoo/deeplabv3/scripts/run_eval.sh @@ -15,8 +15,8 @@ # ============================================================================ echo "==============================================================================================================" echo "Please run the scipt as: " -echo "bash run_eval.sh DEVICE_ID EPOCH_SIZE DATA_DIR" -echo "for example: bash run_eval.sh 0 /path/zh-wiki/ " +echo "bash run_eval.sh DEVICE_ID DATA_DIR" +echo "for example: bash run_eval.sh /path/zh-wiki/ " echo "==============================================================================================================" DEVICE_ID=$1 diff --git a/model_zoo/deeplabv3/train.py b/model_zoo/deeplabv3/train.py index 237d2f4800..a0f5b01d0d 100644 --- a/model_zoo/deeplabv3/train.py +++ b/model_zoo/deeplabv3/train.py @@ -27,13 +27,12 @@ from src.config import config parser = argparse.ArgumentParser(description="Deeplabv3 training") parser.add_argument("--distribute", type=str, default="false", help="Run distribute, default is false.") -parser.add_argument('--epoch_size', type=int, default=2, help='Epoch size.') +parser.add_argument('--epoch_size', type=int, default=6, help='Epoch size.') parser.add_argument('--batch_size', type=int, default=2, help='Batch size.') parser.add_argument('--data_url', required=True, default=None, help='Train data url') parser.add_argument("--device_id", type=int, default=0, help="Device id, default is 0.") parser.add_argument('--checkpoint_url', default=None, help='Checkpoint path') parser.add_argument("--enable_save_ckpt", type=str, default="true", help="Enable save checkpoint, default is true.") -parser.add_argument('--max_checkpoint_num', type=int, default=5, help='Max checkpoint number.') parser.add_argument("--save_checkpoint_steps", type=int, default=1000, help="Save checkpoint steps, default is 1000.") parser.add_argument("--save_checkpoint_num", type=int, default=1, help="Save checkpoint numbers, default is 1.") args_opt = parser.parse_args() @@ -80,7 +79,7 @@ if __name__ == "__main__": keep_checkpoint_max=args_opt.save_checkpoint_num) ckpoint_cb = ModelCheckpoint(prefix='checkpoint_deeplabv3', config=config_ck) callback.append(ckpoint_cb) - net = deeplabv3_resnet50(config.seg_num_classes, [args_opt.batch_size, 3, args_opt.crop_size, args_opt.crop_size], + net = deeplabv3_resnet50(config.seg_num_classes, [args_opt.batch_size, 3, args_opt.crop_size, args_opt.crop_size], infer_scale_sizes=config.eval_scales, atrous_rates=config.atrous_rates, decoder_output_stride=config.decoder_output_stride, output_stride=config.output_stride, fine_tune_batch_norm=config.fine_tune_batch_norm, image_pyramid=config.image_pyramid) From ee2efd3589c99edb8f13be2c8c2afdcc35f24dbf Mon Sep 17 00:00:00 2001 From: yangyongjie Date: Fri, 29 May 2020 11:52:07 +0800 Subject: [PATCH 16/20] fix pylint --- model_zoo/deeplabv3/src/backbone/__init__.py | 4 ++-- model_zoo/deeplabv3/src/miou_precision.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/model_zoo/deeplabv3/src/backbone/__init__.py b/model_zoo/deeplabv3/src/backbone/__init__.py index 005e41d8b5..6f78084131 100644 --- a/model_zoo/deeplabv3/src/backbone/__init__.py +++ b/model_zoo/deeplabv3/src/backbone/__init__.py @@ -14,8 +14,8 @@ # ============================================================================ """Init backbone.""" from .resnet_deeplab import Subsample, DepthwiseConv2dNative, SpaceToBatch, BatchToSpace, ResNetV1, \ - RootBlockBeta, resnet50_dl + RootBlockBeta, resnet50_dl __all__ = [ - "Subsample", "DepthwiseConv2dNative", "SpaceToBatch", "BatchToSpace", "ResNetV1", "RootBlockBeta", "resnet50_dl" + "Subsample", "DepthwiseConv2dNative", "SpaceToBatch", "BatchToSpace", "ResNetV1", "RootBlockBeta", "resnet50_dl" ] diff --git a/model_zoo/deeplabv3/src/miou_precision.py b/model_zoo/deeplabv3/src/miou_precision.py index ea2e975d81..b73b3947d4 100644 --- a/model_zoo/deeplabv3/src/miou_precision.py +++ b/model_zoo/deeplabv3/src/miou_precision.py @@ -24,7 +24,7 @@ def confuse_matrix(target, pred, n): def iou(hist): denominator = hist.sum(1) + hist.sum(0) - np.diag(hist) - res = np.diag(hist) / np.where(denominator > 0, denominator, 1) + res = np.diag(hist) / np.where(denominator > 0, denominator, 1) res = np.sum(res) / np.count_nonzero(denominator) return res @@ -62,7 +62,7 @@ class MiouPrecision(Metric): self._hist = confuse_matrix(label.flatten(), pred.flatten(), self._num_class) mIoUs = iou(self._hist) self._mIoU.append(mIoUs) - + def eval(self): """ Computes the mIoU categorical accuracy. From e66b23b357df69d90315041ce2c245b7a1732f9e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 12:00:10 +0800 Subject: [PATCH 17/20] add readme --- model_zoo/deeplabv3/README.md | 57 +++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/model_zoo/deeplabv3/README.md b/model_zoo/deeplabv3/README.md index 977da7040a..f2c5fe0bc7 100644 --- a/model_zoo/deeplabv3/README.md +++ b/model_zoo/deeplabv3/README.md @@ -1,39 +1,42 @@ -Deeplab-V3 Example +# Deeplab-V3 Example -Description +## Description This is an example of training DeepLabv3 with PASCAL VOC 2012 dataset in MindSpore. Paper Rethinking Atrous Convolution for Semantic Image Segmentation Liang-Chieh Chen, George Papandreou, Florian Schroff, Hartwig Adam -Requirements -Install MindSpore. -Download the VOC 2012 dataset for training. -For more information, please check the resources below: -MindSpore tutorials -MindSpore API +## Requirements +- Install [MindSpore](https://www.mindspore.cn/install/en). +- Download the VOC 2012 dataset for training. -Notes: If you are running a fine-tuning or evaluation task, prepare the corresponding checkpoint file. +> Notes: + If you are running a fine-tuning or evaluation task, prepare the corresponding checkpoint file. -Running the Example - -Training -Set options in config.py. -Run run_standalone_train.sh for non-distributed training. -sh scripts/run_standalone_train.sh DEVICE_ID EPOCH_SIZE DATA_DIR -Run run_distribute_train.sh for distributed training. -sh scripts/run_distribute_train.sh DEVICE_NUM EPOCH_SIZE DATA_DIR MINDSPORE_HCCL_CONFIG_PATH - -Evaluation +## Running the Example +### Training +- Set options in config.py. +- Run `run_standalone_train.sh` for non-distributed training. + ``` bash + sh scripts/run_standalone_train.sh DEVICE_ID EPOCH_SIZE DATA_DIR + ``` +- Run `run_distribute_train.sh` for distributed training. + ``` bash + sh scripts/run_distribute_train.sh DEVICE_NUM EPOCH_SIZE DATA_DIR MINDSPORE_HCCL_CONFIG_PATH + ``` +### Evaluation Set options in evaluation_config.py. Make sure the 'data_file' and 'finetune_ckpt' are set to your own path. -Run run_eval.sh for evaluation. -sh scripts/run_eval.sh DEVICE_ID DATA_DIR +- Run run_eval.sh for evaluation. + ``` bash + sh scripts/run_eval.sh DEVICE_ID DATA_DIR + ``` -Options and Parameters +## Options and Parameters It contains of parameters of Deeplab-V3 model and options for training, which is set in file config.py. -Options: +### Options: +``` config.py: learning_rate Learning rate, default is 0.0014. weight_decay Weight decay, default is 5e-5. @@ -49,10 +52,11 @@ config.py: decoder_output_stride The ratio of input to output spatial resolution when employing decoder to refine segmentation results, default is None. image_pyramid Input scales for multi-scale feature extraction, default is None. - +``` -Parameters: +### Parameters: +``` Parameters for dataset and network: distribute Run distribute, default is false. epoch_size Epoch size, default is 6. @@ -61,4 +65,5 @@ Parameters for dataset and network: checkpoint_url Checkpoint path, default is None. enable_save_ckpt Enable save checkpoint, default is true. save_checkpoint_steps Save checkpoint steps, default is 1000. - save_checkpoint_num Save checkpoint numbers, default is 1. \ No newline at end of file + save_checkpoint_num Save checkpoint numbers, default is 1. +``` \ No newline at end of file From 2065383e3833a3ce57c67f2c1fe7464cacbbdbd6 Mon Sep 17 00:00:00 2001 From: yangyongjie Date: Fri, 29 May 2020 12:01:09 +0800 Subject: [PATCH 18/20] pylint fix --- model_zoo/deeplabv3/evaluation.py | 13 ++- .../deeplabv3/src/backbone/resnet_deeplab.py | 92 +++++++++---------- 2 files changed, 54 insertions(+), 51 deletions(-) diff --git a/model_zoo/deeplabv3/evaluation.py b/model_zoo/deeplabv3/evaluation.py index 2c03467587..a76273ed63 100644 --- a/model_zoo/deeplabv3/evaluation.py +++ b/model_zoo/deeplabv3/evaluation.py @@ -22,6 +22,8 @@ from src.losses import OhemLoss from src.miou_precision import MiouPrecision from src.deeplabv3 import deeplabv3_resnet50 from src.config import config + + parser = argparse.ArgumentParser(description="Deeplabv3 evaluation") parser.add_argument('--epoch_size', type=int, default=2, help='Epoch size.') parser.add_argument("--device_id", type=int, default=0, help="Device id, default is 0.") @@ -32,14 +34,16 @@ parser.add_argument('--checkpoint_url', default=None, help='Checkpoint path') args_opt = parser.parse_args() context.set_context(mode=context.GRAPH_MODE, device_target="Ascend", device_id=args_opt.device_id) print(args_opt) + + if __name__ == "__main__": args_opt.crop_size = config.crop_size args_opt.base_size = config.crop_size eval_dataset = create_dataset(args_opt, args_opt.data_url, args_opt.epoch_size, args_opt.batch_size, usage="eval") - net = deeplabv3_resnet50(config.seg_num_classes, [args_opt.batch_size, 3, args_opt.crop_size, args_opt.crop_size], - infer_scale_sizes=config.eval_scales, atrous_rates=config.atrous_rates, - decoder_output_stride=config.decoder_output_stride, output_stride=config.output_stride, - fine_tune_batch_norm=config.fine_tune_batch_norm, image_pyramid=config.image_pyramid) + net = deeplabv3_resnet50(config.seg_num_classes, [args_opt.batch_size, 3, args_opt.crop_size, args_opt.crop_size], + infer_scale_sizes=config.eval_scales, atrous_rates=config.atrous_rates, + decoder_output_stride=config.decoder_output_stride, output_stride=config.output_stride, + fine_tune_batch_norm=config.fine_tune_batch_norm, image_pyramid=config.image_pyramid) param_dict = load_checkpoint(args_opt.checkpoint_url) load_param_into_net(net, param_dict) mIou = MiouPrecision(config.seg_num_classes) @@ -47,4 +51,3 @@ if __name__ == "__main__": loss = OhemLoss(config.seg_num_classes, config.ignore_label) model = Model(net, loss, metrics=metrics) model.eval(eval_dataset) - \ No newline at end of file diff --git a/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py b/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py index 76abe29d12..1dda6fe746 100644 --- a/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py +++ b/model_zoo/deeplabv3/src/backbone/resnet_deeplab.py @@ -93,31 +93,30 @@ def _stob_deep_conv_btos_bn_relu(in_channel, def _stob_conv_btos_bn_relu(in_channel, - out_channel, - ksize, - space_to_batch_block_shape, - batch_to_space_block_shape, - paddings, - crops, - stride=1, - padding=0, - dilation=1, - pad_mode="pad", - use_batch_statistics=False): + out_channel, + ksize, + space_to_batch_block_shape, + batch_to_space_block_shape, + paddings, + crops, + stride=1, + padding=0, + dilation=1, + pad_mode="pad", + use_batch_statistics=False): """Get a spacetobatch -> conv2d -> batchnorm -> relu -> batchtospace layer""" - return nn.SequentialCell( - [SpaceToBatch(space_to_batch_block_shape,paddings), - nn.Conv2d(in_channel, - out_channel, - kernel_size=ksize, - stride=stride, - padding=padding, - dilation=dilation, - pad_mode=pad_mode), - BatchToSpace(batch_to_space_block_shape,crops), - nn.BatchNorm2d(out_channel,use_batch_statistics=use_batch_statistics), - nn.ReLU()] - ) + return nn.SequentialCell([SpaceToBatch(space_to_batch_block_shape, paddings), + nn.Conv2d(in_channel, + out_channel, + kernel_size=ksize, + stride=stride, + padding=padding, + dilation=dilation, + pad_mode=pad_mode), + BatchToSpace(batch_to_space_block_shape, crops), + nn.BatchNorm2d(out_channel, use_batch_statistics=use_batch_statistics), + nn.ReLU()] + ) def _make_layer(block, @@ -206,6 +205,7 @@ class BatchToSpace(nn.Cell): class _DepthwiseConv2dNative(nn.Cell): + """Depthwise Conv2D Cell.""" def __init__(self, in_channels, channel_multiplier, @@ -242,6 +242,7 @@ class _DepthwiseConv2dNative(nn.Cell): class DepthwiseConv2dNative(_DepthwiseConv2dNative): + """Depthwise Conv2D Cell.""" def __init__(self, in_channels, channel_multiplier, @@ -315,31 +316,31 @@ class BottleneckV1(nn.Cell): padding=1, dilation=1, use_batch_statistics=use_batch_statistics) - if use_batch_to_stob_and_btos == True: + if use_batch_to_stob_and_btos: self.conv_bn2 = _stob_conv_btos_bn_relu(mid_channels, mid_channels, ksize=3, stride=stride, padding=0, dilation=1, - space_to_batch_block_shape = 2, - batch_to_space_block_shape = 2, - paddings =[[2, 3], [2, 3]], - crops =[[0, 1], [0, 1]], + space_to_batch_block_shape=2, + batch_to_space_block_shape=2, + paddings=[[2, 3], [2, 3]], + crops=[[0, 1], [0, 1]], pad_mode="valid", use_batch_statistics=use_batch_statistics) - + self.conv3 = nn.Conv2d(mid_channels, out_channels, kernel_size=1, stride=1) - self.bn3 = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) + self.bn3 = nn.BatchNorm2d(out_channels, use_batch_statistics=use_batch_statistics) if in_channels != out_channels: conv = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride) - bn = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) + bn = nn.BatchNorm2d(out_channels, use_batch_statistics=use_batch_statistics) self.downsample = nn.SequentialCell([conv, bn]) else: self.downsample = Subsample(stride) @@ -397,23 +398,23 @@ class BottleneckV2(nn.Cell): stride=stride, padding=0, dilation=1, - space_to_batch_block_shape = 2, - batch_to_space_block_shape = 2, - paddings =[[2, 3], [2, 3]], - crops =[[0, 1], [0, 1]], + space_to_batch_block_shape=2, + batch_to_space_block_shape=2, + paddings=[[2, 3], [2, 3]], + crops=[[0, 1], [0, 1]], pad_mode="valid", use_batch_statistics=use_batch_statistics) self.conv3 = nn.Conv2d(mid_channels, out_channels, kernel_size=1, stride=1) - self.bn3 = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) + self.bn3 = nn.BatchNorm2d(out_channels, use_batch_statistics=use_batch_statistics) if in_channels != out_channels: conv = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride) - bn = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) + bn = nn.BatchNorm2d(out_channels, use_batch_statistics=use_batch_statistics) self.downsample = nn.SequentialCell([conv, bn]) else: self.downsample = Subsample(stride) @@ -465,14 +466,14 @@ class BottleneckV3(nn.Cell): out_channels, kernel_size=1, stride=1) - self.bn3 = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) - + self.bn3 = nn.BatchNorm2d(out_channels, use_batch_statistics=use_batch_statistics) + if in_channels != out_channels: conv = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride) - bn = nn.BatchNorm2d(out_channels,use_batch_statistics=use_batch_statistics) + bn = nn.BatchNorm2d(out_channels, use_batch_statistics=use_batch_statistics) self.downsample = nn.SequentialCell([conv, bn]) else: self.downsample = Subsample(stride) @@ -502,9 +503,8 @@ class ResNetV1(nn.Cell): super(ResNetV1, self).__init__() self.layer_root = nn.SequentialCell( [RootBlockBeta(fine_tune_batch_norm), - nn.MaxPool2d(kernel_size=(3,3), - stride=(2,2), - #padding=1, + nn.MaxPool2d(kernel_size=(3, 3), + stride=(2, 2), pad_mode='same')]) self.layer1_1 = BottleneckV1(128, 256, stride=1, use_batch_statistics=fine_tune_batch_norm) self.layer1_2 = BottleneckV2(256, 256, stride=1, use_batch_statistics=fine_tune_batch_norm) @@ -519,7 +519,7 @@ class ResNetV1(nn.Cell): self.layer3_4 = BottleneckV2(1024, 1024, stride=1, use_batch_statistics=fine_tune_batch_norm) self.layer3_5 = BottleneckV2(1024, 1024, stride=1, use_batch_statistics=fine_tune_batch_norm) self.layer3_6 = BottleneckV2(1024, 1024, stride=1, use_batch_statistics=fine_tune_batch_norm) - + self.layer4_1 = BottleneckV1(1024, 2048, stride=1, use_batch_to_stob_and_btos=True, use_batch_statistics=fine_tune_batch_norm) self.layer4_2 = BottleneckV2(2048, 2048, stride=1, use_batch_to_stob_and_btos=True, @@ -542,7 +542,7 @@ class ResNetV1(nn.Cell): x = self.layer3_4(x) x = self.layer3_5(x) x = self.layer3_6(x) - + x = self.layer4_1(x) x = self.layer4_2(x) c5 = self.layer4_3(x) From db7b728d6ae3c8953855b5c8ca64a40b4f64ad43 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 12:02:16 +0800 Subject: [PATCH 19/20] add readme --- model_zoo/deeplabv3/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/model_zoo/deeplabv3/README.md b/model_zoo/deeplabv3/README.md index f2c5fe0bc7..fa9c880810 100644 --- a/model_zoo/deeplabv3/README.md +++ b/model_zoo/deeplabv3/README.md @@ -1,8 +1,8 @@ # Deeplab-V3 Example ## Description -This is an example of training DeepLabv3 with PASCAL VOC 2012 dataset in MindSpore. -Paper Rethinking Atrous Convolution for Semantic Image Segmentation +- This is an example of training DeepLabv3 with PASCAL VOC 2012 dataset in MindSpore. +- Paper Rethinking Atrous Convolution for Semantic Image Segmentation Liang-Chieh Chen, George Papandreou, Florian Schroff, Hartwig Adam From 75d77806c094f3540fb90b96d59c6e1ea62c922d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 May 2020 12:52:36 +0800 Subject: [PATCH 20/20] fix pylint --- model_zoo/deeplabv3/README.md | 5 +---- model_zoo/deeplabv3/src/losses.py | 2 +- model_zoo/deeplabv3/train.py | 6 +++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/model_zoo/deeplabv3/README.md b/model_zoo/deeplabv3/README.md index fa9c880810..b178a83e6d 100644 --- a/model_zoo/deeplabv3/README.md +++ b/model_zoo/deeplabv3/README.md @@ -1,10 +1,7 @@ # Deeplab-V3 Example ## Description -- This is an example of training DeepLabv3 with PASCAL VOC 2012 dataset in MindSpore. -- Paper Rethinking Atrous Convolution for Semantic Image Segmentation -Liang-Chieh Chen, George Papandreou, Florian Schroff, Hartwig Adam - +This is an example of training DeepLabv3 with PASCAL VOC 2012 dataset in MindSpore. ## Requirements - Install [MindSpore](https://www.mindspore.cn/install/en). diff --git a/model_zoo/deeplabv3/src/losses.py b/model_zoo/deeplabv3/src/losses.py index 051cc1b1f9..af782c2de9 100644 --- a/model_zoo/deeplabv3/src/losses.py +++ b/model_zoo/deeplabv3/src/losses.py @@ -50,7 +50,7 @@ class OhemLoss(nn.Cell): losses = self.cross_entropy(logits, one_hot_labels)[0] weights = self.cast(self.not_equal(labels, self.ignore_label), mstype.float32) * self.loss_weight weighted_losses = self.mul(losses, weights) - loss = self.reduce_sum(weighted_losses,(0,)) + loss = self.reduce_sum(weighted_losses, (0,)) zeros = self.fill(mstype.float32, self.shape(weights), 0.0) ones = self.fill(mstype.float32, self.shape(weights), 1.0) present = self.select(self.equal(weights, zeros), zeros, ones) diff --git a/model_zoo/deeplabv3/train.py b/model_zoo/deeplabv3/train.py index a0f5b01d0d..2135b0abf5 100644 --- a/model_zoo/deeplabv3/train.py +++ b/model_zoo/deeplabv3/train.py @@ -80,9 +80,9 @@ if __name__ == "__main__": ckpoint_cb = ModelCheckpoint(prefix='checkpoint_deeplabv3', config=config_ck) callback.append(ckpoint_cb) net = deeplabv3_resnet50(config.seg_num_classes, [args_opt.batch_size, 3, args_opt.crop_size, args_opt.crop_size], - infer_scale_sizes=config.eval_scales, atrous_rates=config.atrous_rates, - decoder_output_stride=config.decoder_output_stride, output_stride=config.output_stride, - fine_tune_batch_norm=config.fine_tune_batch_norm, image_pyramid=config.image_pyramid) + infer_scale_sizes=config.eval_scales, atrous_rates=config.atrous_rates, + decoder_output_stride=config.decoder_output_stride, output_stride=config.output_stride, + fine_tune_batch_norm=config.fine_tune_batch_norm, image_pyramid=config.image_pyramid) net.set_train() model_fine_tune(args_opt, net, 'layer') loss = OhemLoss(config.seg_num_classes, config.ignore_label)