release commit
authorManu Mathew <a0393608@ti.com>
Thu, 16 Jan 2020 05:23:39 +0000 (10:53 +0530)
committerManu Mathew <a0393608@ti.com>
Thu, 16 Jan 2020 05:23:39 +0000 (10:53 +0530)
docs/Quantization.md
modules/pytorch_jacinto_ai/engine/infer_pixel2pixel.py
modules/pytorch_jacinto_ai/engine/test_pixel2pixel_onnx.py
modules/pytorch_jacinto_ai/engine/train_classification.py
modules/pytorch_jacinto_ai/engine/train_pixel2pixel.py
modules/pytorch_jacinto_ai/vision/models/pixel2pixel/deeplabv3lite.py
modules/pytorch_jacinto_ai/vision/models/pixel2pixel/fpn_pixel2pixel.py
modules/pytorch_jacinto_ai/vision/models/pixel2pixel/pixel2pixelnet.py
modules/pytorch_jacinto_ai/xnn/layers/functional.py
modules/pytorch_jacinto_ai/xnn/layers/rf_blocks.py
run_segmentation.sh

index 35e5532f9db11d26bb54bd7990a97c3210ca7c63..eee2ef2795ff199b827c8adb2614aeeec168cdd4 100644 (file)
@@ -158,11 +158,11 @@ python ./scripts/train_segmentation_main.py --dataset_name cityscapes_segmentati
 ```
 
 ## Important Notes - read carefully
-**Multi-GPU training/calibration/validation with DataParallel is not yet working with our quantization modules** QuantCalibrateModule, QuantTrainModule. 
-- **We recommend not to wrap the modules in DataParallel if you are training/calibrating/testing with quantization - i.e. if your model is wrapped in QuantCalibrateModule/QuantTrainModule/QuantTestModule.** If you get an error during training related to weights and input not being in the same GPU, please check and ensure that you are not using DataParallel with QuantCalibrateModule/QuantTrainModule/QuantTestModule. This may not be such a problem as calibration and quantization may not take as much time as the original training. If your calibration/training crashes with insufficient GPU memory, reduce the batch size and try again. The original training (without quantization) can use Multi-GPU as usual and we do not have any restrictions on that.
-- **The same module should not be re-used multiple times within the module** in order that the activation range estimation is correct. Unfortunately, in the torchvision ResNet models, the ReLU module in the BasicBlock and BottleneckBlock are re-used multiple times. We have corrected this by defining separate ReLU modules. This change is minor and **does not** affect the loading of existing pretrained weights. See the [our modified ResNet model definition here](./modules/pytorch_jacinto_ai/vision/models/resnet.py).
-- **Use Modules instead of functions** (we make use of modules to decide whether to do activation range clipping or not). For example use torch.nn.reLU instead of torch.nn.functional.relu(), torch.nn.AdaptiveAvgPool2d() instead of torch.nn.functional.adaptive_avg_pool2d(), torch.nn.Flatten() instead of torch.nn.functional.flatten() etc. If you are using functions in your model and is giving poor quantized accuracy, then consider replacing those functions by the corresponding modules.
-- Tools for Calibration and Trained Quantization have started appearing in mainstream Deep Learning training frameworks [[7,8]]. Using the tools natively provided by these frameworks may be faster compared to an implementation in the Python layer of these frameworks (like we have done) - but they may not be mature currently. 
+**Multi-GPU training/calibration/validation with DataParallel is not yet working with our quantization modules** QuantCalibrateModule, QuantTrainModule.<br>
+- **We recommend not to wrap the modules in DataParallel if you are training/calibrating/testing with quantization - i.e. if your model is wrapped in QuantCalibrateModule/QuantTrainModule/QuantTestModule.** If you get an error during training related to weights and input not being in the same GPU, please check and ensure that you are not using DataParallel with QuantCalibrateModule/QuantTrainModule/QuantTestModule. This may not be such a problem as calibration and quantization may not take as much time as the original training. If your calibration/training crashes with insufficient GPU memory, reduce the batch size and try again. The original training (without quantization) can use Multi-GPU as usual and we do not have any restrictions on that.<br>
+- **The same module should not be re-used multiple times within the module** in order that the activation range estimation is correct. Unfortunately, in the torchvision ResNet models, the ReLU module in the BasicBlock and BottleneckBlock are re-used multiple times. We have corrected this by defining separate ReLU modules. This change is minor and **does not** affect the loading of existing pretrained weights. See the [our modified ResNet model definition here](./modules/pytorch_jacinto_ai/vision/models/resnet.py).<br>
+- **Use Modules instead of functions** (we make use of modules to decide whether to do activation range clipping or not). For example use torch.nn.reLU instead of torch.nn.functional.relu(), torch.nn.AdaptiveAvgPool2d() instead of torch.nn.functional.adaptive_avg_pool2d(), torch.nn.Flatten() instead of torch.nn.functional.flatten() etc. If you are using functions in your model and is giving poor quantized accuracy, then consider replacing those functions by the corresponding modules.<br>
+- Tools for Calibration and Trained Quantization have started appearing in mainstream Deep Learning training frameworks [[7,8]]. Using the tools natively provided by these frameworks may be faster compared to an implementation in the Python layer of these frameworks (like we have done) - but they may not be mature currently.<br>
 
 
 ## Results
index d61ac15a09b022f57ee474f8b84e8516280db015..e05ebf1017830d8189617a76b818c68244327f4b 100644 (file)
@@ -3,6 +3,7 @@ import time
 import sys
 import math
 import copy
+import warnings
 
 import torch
 import torch.nn.parallel
@@ -266,7 +267,9 @@ def main(args):
 
     ################################
     # args check and config
-    assert args.iter_size == 1 or args.total_batch_size is None, "only one of --iter_size or --total_batch_size must be set"
+    if args.iter_size != 1 and args.total_batch_size is not None:
+        warnings.warn("only one of --iter_size or --total_batch_size must be set")
+    #
     if args.total_batch_size is not None:
         args.iter_size = args.total_batch_size//args.batch_size
     else:
index 458d9abc5c41cd4582a261e9b68338b41795050f..2b8ccfba5c7572880e8e1edc52653460d6275df5 100644 (file)
@@ -1,6 +1,7 @@
 import os
 import time
 import sys
+import warnings
 
 import torch
 import torch.nn.parallel
@@ -122,7 +123,9 @@ def main(args):
 
     ################################
     # args check and config
-    assert args.iter_size == 1 or args.total_batch_size is None, "only one of --iter_size or --total_batch_size must be set"
+    if args.iter_size != 1 and args.total_batch_size is not None:
+        warnings.warn("only one of --iter_size or --total_batch_size must be set")
+    #
     if args.total_batch_size is not None:
         args.iter_size = args.total_batch_size//args.batch_size
     else:
index bf9ffec12819b4ea31e4536e8df5510a8c8ba72c..be27d8f994d1d6373164daf6c2f4efe9535f65c8 100644 (file)
@@ -145,7 +145,9 @@ def main(args):
     args.pretrained = None if (args.pretrained == 'None') else args.pretrained
     args.num_inputs = len(args.multi_color_modes) if (args.multi_color_modes is not None) else 1
 
-    assert args.iter_size == 1 or args.total_batch_size is None, "only one of --iter_size or --total_batch_size must be set"
+    if args.iter_size != 1 and args.total_batch_size is not None:
+        warnings.warn("only one of --iter_size or --total_batch_size must be set")
+    #
     if args.total_batch_size is not None:
         args.iter_size = args.total_batch_size//args.batch_size
     else:
index 9273786f3f5d5932bffe82e008d233dfdfd4084c..11e0bf6deecd918088912efb145969b428bc7fe2 100644 (file)
@@ -229,7 +229,9 @@ def main(args):
 
     ################################
     # args check and config
-    assert args.iter_size == 1 or args.total_batch_size is None, "only one of --iter-size or --total-batch-size must be set"
+    if args.iter_size != 1 and args.total_batch_size is not None:
+        warnings.warn("only one of --iter_size or --total_batch_size must be set")
+    #
     if args.total_batch_size is not None:
         args.iter_size = args.total_batch_size//args.batch_size
     else:
index 8ba9b194140dfc7ab464e77c0c648259ec6b2e3d..b75366ea3cd213ece922141c7ff2be23193db6c8 100644 (file)
@@ -113,6 +113,7 @@ def get_config_deeplav3lite_mnv2():
     # and are expected to be passed from the main script.
     model_config = xnn.utils.ConfigNode()
     model_config.num_classes = None
+    model_config.num_decoders = None
     model_config.input_channels = (3,)
     model_config.output_channels = [19]
     model_config.intermediate_outputs = True
index 12ad0e208cc00436cbc264ca72183ec931a6b94a..cde3b4d04425ccf0321e9d886f04f81c229195e4 100644 (file)
@@ -7,7 +7,7 @@ from ..multi_input_net import MobileNetV2TVMI4, ResNet50MI4
 
 
 __all__ = ['FPNPixel2PixelASPP', 'FPNPixel2PixelDecoder',
-           'fpn_pixel2pixel_aspp_mobilenetv2_tv', 'fpn_pixel2pixel_aspp_mobilenetv2_tv_fd',
+           'fpn_pixel2pixel_aspp_mobilenetv2_tv', 'fpn_pixel2pixel_aspp_mobilenetv2_tv_fd', 'fpn128_pixel2pixel_aspp_mobilenetv2_tv_fd',
            # no aspp models
            'fpn_pixel2pixel_mobilenetv2_tv', 'fpn_pixel2pixel_mobilenetv2_tv_fd',
            # resnet models
@@ -120,6 +120,7 @@ class FPNPixel2PixelASPP(Pixel2PixelNet):
 def get_config_fpnp2p_mnv2():
     model_config = xnn.utils.ConfigNode()
     model_config.num_classes = None
+    model_config.num_decoders = None
     model_config.intermediate_outputs = True
     model_config.use_aspp = True
     model_config.use_extra_strides = False
@@ -186,10 +187,22 @@ def fpn_pixel2pixel_aspp_mobilenetv2_tv_fd(model_config, pretrained=None):
     model_config = get_config_fpnp2p_mnv2().merge_from(model_config)
     model_config.fastdown = True
     model_config.strides = (2,2,2,2,2)
-    model_config.shortcut_strides = (8,16,32,64) #(4,8,16,32,64)
-    model_config.shortcut_channels = (24,32,96,320) #(16,24,32,96,320)
-    model_config.decoder_chan = 256 #128
-    model_config.aspp_chan = 256 #128
+    model_config.shortcut_strides = (8,16,32,64)
+    model_config.shortcut_channels = (24,32,96,320)
+    model_config.decoder_chan = 256
+    model_config.aspp_chan = 256
+    return fpn_pixel2pixel_aspp_mobilenetv2_tv(model_config, pretrained=pretrained)
+
+
+# fast down sampling model (encoder stride 64 model) with fpn decoder channels 128
+def fpn128_pixel2pixel_aspp_mobilenetv2_tv_fd(model_config, pretrained=None):
+    model_config = get_config_fpnp2p_mnv2().merge_from(model_config)
+    model_config.fastdown = True
+    model_config.strides = (2,2,2,2,2)
+    model_config.shortcut_strides = (4,8,16,32,64)
+    model_config.shortcut_channels = (16,24,32,96,320)
+    model_config.decoder_chan = 128
+    model_config.aspp_chan = 128
     return fpn_pixel2pixel_aspp_mobilenetv2_tv(model_config, pretrained=pretrained)
 
 
index fbec903270e03dc9223f46c43250ef8b2749ca17..bcfa506221ef7218ad42ef57b9c730ca5e1b1e84 100644 (file)
@@ -4,27 +4,6 @@ import torch.nn.functional as F
 import copy
 
 
-def split_output_channels(output, output_channels):
-    if isinstance(output, (list, tuple)):
-        return output
-    elif len(output_channels) == 1:
-        return [output]
-    else:
-        start_ch = 0
-        task_outputs = []
-        for num_ch in output_channels:
-            if len(output.shape) == 3:
-                task_outputs.append(output[start_ch:(start_ch + num_ch), ...])
-            elif len(output.shape) == 4:
-                task_outputs.append(output[:, start_ch:(start_ch + num_ch), ...])
-            else:
-                assert False, 'incorrect dimensions'
-            # --
-            start_ch += num_ch
-        # --
-        return task_outputs
-
-
 ###########################################
 class Pixel2PixelSimpleDecoder(torch.nn.Module):
     def __init__(self, input_channels, output_channels):
@@ -111,7 +90,7 @@ class Pixel2PixelNet(torch.nn.Module):
             d_out = decoder(x_inp, x_feat, x_list)
             x_out.append(d_out)
 
-        x_out = split_output_channels(x_out[0], self.output_channels) if (self.num_decoders <= 1 and self.split_outputs) else x_out
+        x_out = xnn.layers.split_output_channels(x_out[0], self.output_channels) if (self.num_decoders <= 1 and self.split_outputs) else x_out
         return x_out
 
 
index 36589b3a565d1d42ee14053cb40bc29e48da91e7..996b4c92457ab0b634c4b53ef512f93480d9e889 100644 (file)
@@ -95,5 +95,23 @@ def crop_grid(features, crop_offsets, crop_size):
     return out
 
 
-
-
+###################################################
+def split_output_channels(output, output_channels):
+    if isinstance(output, (list, tuple)):
+        return output
+    elif len(output_channels) == 1:
+        return [output]
+    else:
+        start_ch = 0
+        task_outputs = []
+        for num_ch in output_channels:
+            if len(output.shape) == 3:
+                task_outputs.append(output[start_ch:(start_ch + num_ch), ...])
+            elif len(output.shape) == 4:
+                task_outputs.append(output[:, start_ch:(start_ch + num_ch), ...])
+            else:
+                assert False, 'incorrect dimensions'
+            # --
+            start_ch += num_ch
+        # --
+        return task_outputs
index 8fbd3a61ea07b9119a15a49b342f7db2b7388e69..b6399bbdd6c3aa1b9aefe202c82e28d108dcaa58 100644 (file)
@@ -41,7 +41,7 @@ class ASPPBlock(torch.nn.Module):
         b3 = self.aspp_bra3(x0)
 
         if self.avg_pool:
-            xavg = F.interpolate(self.gave_pool(x0), size=x0.shape[2:], mode='bilinear')
+            xavg = torch.nn.functional.interpolate(self.gave_pool(x0), size=x0.shape[2:], mode='bilinear')
             branches = [xavg, x1, b1, b2, b3]
         else:
             branches = [x1, b1, b2, b3]
index f447a3d1ed1d8b21fa6e84f1fa2b3432808ce78c..4e3e5ea87f828a2d3fb6f65bea8ac35987ab9113 100755 (executable)
 #python ./scripts/train_segmentation_main.py --dataset_name cityscapes_segmentation --model_name fpn_pixel2pixel_aspp_mobilenetv2_tv_fd --data_path ./data/datasets/cityscapes/data --img_resize 768 1536 --rand_crop 512 1024 --output_size 1024 2048 --gpus 0 1 \
 #--pretrained https://download.pytorch.org/models/mobilenet_v2-b0353104.pth
 
+#### Cityscapes Semantic Segmentation - fpn with 128 decoder channels - no aspp model, stride 64 model, Higher Resolution - Low Complexity Model
+#python ./scripts/train_segmentation_main.py --dataset_name cityscapes_segmentation --model_name fpn128_pixel2pixel_aspp_mobilenetv2_tv_fd --data_path ./data/datasets/cityscapes/data --img_resize 768 1536 --rand_crop 512 1024 --output_size 1024 2048 --gpus 0 1 \
+#--pretrained https://download.pytorch.org/models/mobilenet_v2-b0353104.pth
+
 #### Cityscapes Semantic Segmentation - Training with ResNet50+FPN
 #python ./scripts/train_segmentation_main.py --dataset_name cityscapes_segmentation --model_name fpn_pixel2pixel_aspp_resnet50 --data_path ./data/datasets/cityscapes/data --img_resize 768 1536 --rand_crop 512 1024 --output_size 1024 2048 --gpus 0 1 \
 #--pretrained https://download.pytorch.org/models/resnet50-19c8e357.pth