docs update and minor fixes
authorManu Mathew <a0393608@ti.com>
Tue, 28 Apr 2020 12:51:44 +0000 (18:21 +0530)
committerManu Mathew <a0393608@ti.com>
Wed, 29 Apr 2020 09:51:52 +0000 (15:21 +0530)
20 files changed:
docs/Calibration.md
docs/Multi_Task_Learning.md
docs/Quantization.md
examples/quantization_example.py
examples/write_onnx_model_example.py
modules/pytorch_jacinto_ai/engine/infer_classification_onnx_rt.py
modules/pytorch_jacinto_ai/engine/infer_pixel2pixel.py
modules/pytorch_jacinto_ai/engine/infer_pixel2pixel_onnx_rt.py
modules/pytorch_jacinto_ai/engine/test_classification.py
modules/pytorch_jacinto_ai/engine/train_classification.py
modules/pytorch_jacinto_ai/engine/train_pixel2pixel.py
modules/pytorch_jacinto_ai/xnn/layers/multi_task.py
modules/pytorch_jacinto_ai/xnn/layers/resize_blocks.py
modules/pytorch_jacinto_ai/xnn/quantize/quant_train_utils.py [deleted file]
scripts/infer_segmentation_main.py
scripts/train_classification_main.py
scripts/train_depth_main.py
scripts/train_motion_segmentation_main.py
scripts/train_pixel2pixel_multitask_main.py
scripts/train_segmentation_main.py

index 9e749243912347892ca54e3b33f2ee3b0115e5c4..2cfe4ef071c905a15be55075b348fa6acc47f2d8 100644 (file)
@@ -61,7 +61,7 @@ for images, target in my_dataset_train:
 
 # save the model - the calibrated module is in model.module
 torch.save(model.module.state_dict(), os.path.join(save_path,'model.pth'))
-torch.onnx.export(model.module, dummy_input, os.path.join(save_path,'model.onnx'), export_params=True, verbose=False)
+torch.onnx.export(model.module, dummy_input, os.path.join(save_path,'model.onnx'), export_params=True, verbose=False, do_constant_folding=True, opset_version=9)
 
 ```
 
index 14253a7a72e907608a5971d4ac5bd121be032c15..6685a1e7f64a07aac34ba7b464120455fa6b0397 100644 (file)
@@ -38,28 +38,31 @@ There are many practical challenges in training a network for multiple tasks wit
 
 **Vanilla multi-task learning**: Here the weights are not learnt.They are all set to 1.0. To train a vanilla multi-task model run the following command, <br> 
 ``` 
-python ./scripts/train_pixel2pixel_main.py --dataset_name cityscapes_image_dof_conf --data_path ./data/datasets/cityscapes/data --img_resize 384 768 --output_size 1024 2048 --gpus 0 1 
+python ./scripts/train_pixel2pixel_multitask_main.py  --img_resize 384 768 --output_size 1024 2048 --gpus 0 1 
 ```
-**Uncertainty bassed learning**: In this case, the weights are updated based on homscedastic uncertainty. To train a uncertainty based multi-task model run the following command: <br>
+**Gradient nornalization** : The weights are updated based on the norm of the backward gradient of the last common along with the rate of learning for each task. To train a model based on gradient normalization run the following command: <br>
 ```
-python ./scripts/train_pixel2pixel_main.py --dataset_name cityscapes_image_dof_conf_uncerainty --data_path ./data/datasets/cityscapes/data --img_resize 384 768 --output_size 1024 2048 --gpus 0 1 <br>
+python ./scripts/train_pixel2pixel_multitask_main.py  --multi_task_type pseudo_grad_norm --img_resize 384 768 --output_size 1024 2048 --gpus 0 1
 ```
-**Gradient nornalization** : The weights are updated based on the norm of the backward gradient of the last common along with the rate of learning for each task. To train a model based on gradient normalization run the following command: <br>
+**Uncertainty bassed learning**: In this case, the weights are updated based on homscedastic uncertainty. To train a uncertainty based multi-task model run the following command: <br>
 ```
-python ./scripts/train_pixel2pixel_main.py --dataset_name cityscapes_image_dof_conf_unceraintys --data_path ./data/datasets/cityscapes/data --img_resize 384 768 --output_size 1024 2048 --gpus 0 1 <br>
+python ./scripts/train_pixel2pixel_multitask_main.py --multi_task_type uncertainty --img_resize 384 768 --output_size 1024 2048 --gpus 0 1 
 ```
+
 ## Results:
-## Cityscapes Multi Task Learning(Depth, Semantic, Motion)
-| Training Modality       | Depth(ARD), Semantic(mIOU), Motion(mIOU) |
-|-------------------------------------------------|-------------------|
-| Single Task Training                            | ----- , -----, -----|
-| Vanilla Multi Task Training                     |12.31, 82.32, 80.52|
-| Uncertainty based Multi Task Training           | ----  , ---- , ----|
-| Gradient-norm based Multi Task Learning         | 12.64, 85.53, 84.75|
+## Cityscapes Multi Task Learning 
+Depth Estimation, Semantic Segmentation(Five class), Motion Segmentation
+
+| Training Modality                       | Depth(ARD%), Semantic(mIOU), Motion(mIOU) | Complexity (GigaMACS) |
+|-----------------------------------------|-------------------------------------------|-----------------------|
+| Single Task Training                    | 11.35, 86.71, 86.6                        |   3.44, 3.54, 3.92    |
+| Vanilla Multi Task Training             | 12.31, 82.32, 80.52                       |          5.71         |
+| Gradient-norm based Multi Task Learning | 12.64, 85.53, 84.95                       |          5.71         |
+| Uncertainty based Multi Task Training   |----- , -----, -----                       |          5.71         |
 
 ## References
-[1]The Cityscapes Dataset for Semantic Urban Scene Understanding, Marius Cordts, Mohamed Omran, Sebastian Ramos, Timo Rehfeld, Markus Enzweiler, Rodrigo Benenson, Uwe Franke, Stefan Roth, Bernt Schiele, CVPR 2016, https://www.cityscapes-dataset.com/
+[1] The Cityscapes Dataset for Semantic Urban Scene Understanding, Marius Cordts, Mohamed Omran, Sebastian Ramos, Timo Rehfeld, Markus Enzweiler, Rodrigo Benenson, Uwe Franke, Stefan Roth, Bernt Schiele, CVPR 2016, https://www.cityscapes-dataset.com/
 
-[2]A. Kendall, Y. Gal, and R. Cipolla. Multi-task learning using uncertainty to weigh losses for scene geometry and semantics. In CVPR, 2018.
+[2] A. Kendall, Y. Gal, and R. Cipolla. Multi-task learning using uncertainty to weigh losses for scene geometry and semantics. In CVPR, 2018.
 
-[3]Z. Chen, V. Badrinarayanan, C. Lee, and A. Rabinovich. GradNorm: Gradient normalization for adaptive loss balancing in deep multitask networks. In ICML, 2018.
+[3] Z. Chen, V. Badrinarayanan, C. Lee, and A. Rabinovich. GradNorm: Gradient normalization for adaptive loss balancing in deep multitask networks. In ICML, 2018.
index 6e76a48db34938c3d0827aca05e452818f834ee0..cb3b077993baf789aa8f5857489d58812437712f 100644 (file)
@@ -68,7 +68,7 @@ model.module.load_state_dict(pretrained_data)
 
 # save the model - the trained module is in model.module
 torch.save(model.module.state_dict(), os.path.join(save_path,'model.pth'))
-torch.onnx.export(model.module, dummy_input, os.path.join(save_path,'model.onnx'), export_params=True, verbose=False)
+torch.onnx.export(model.module, dummy_input, os.path.join(save_path,'model.onnx'), export_params=True, verbose=False, do_constant_folding=True, opset_version=9)
 ```
 
 As can be seen, it is easy to incorporate QuantTrainModule in your existing training code as the only thing required is to wrap your original model in QuantTrainModule. Careful attention needs to be given to how the parameters of the pretrained model is loaded and trained model is saved as shown in the above code snippet.
index 91dac7325bffe7b29844ef547c23af6b05a0eb17..3a9061b45f7cffe28cf77891b9be98023881cca3 100644 (file)
@@ -97,6 +97,9 @@ parser.add_argument('--save_path', type=str, default='./data/checkpoints/quantiz
                     help='path to save the logs and models')
 parser.add_argument('--quantize', action='store_true',
                     help='Enable Quantization')
+parser.add_argument('--opset_version', default=9, type=int,
+                    help='opset version for onnx export')
+
 best_acc1 = 0
 
 
@@ -308,7 +311,7 @@ def main_worker(gpu, ngpus_per_node, args):
             }
             save_checkpoint(checkpoint_dict, is_best, filename=save_filename)
             save_onnxname = os.path.splitext(save_filename)[0]+'.onnx'
-            write_onnx_model(model, is_best, filename=save_onnxname)
+            write_onnx_model(args, model, is_best, filename=save_onnxname)
 
 
 def train(train_loader, model, criterion, optimizer, epoch, args):
@@ -419,11 +422,12 @@ def create_rand_inputs(is_cuda):
     return dummy_input
 
 
-def write_onnx_model(model, is_best, filename='checkpoint.onnx'):
+def write_onnx_model(args, model, is_best, filename='checkpoint.onnx'):
     model.eval()
     is_cuda = next(model.parameters()).is_cuda
     dummy_input = create_rand_inputs(is_cuda)
-    torch.onnx.export(model, dummy_input, filename, export_params=True, verbose=False)
+    torch.onnx.export(model, dummy_input, filename, export_params=True, verbose=False,
+                      do_constant_folding=True, opset_version=args.opset_vesion)
     if is_best:
         shutil.copyfile(filename, os.path.splitext(filename)[0]+'_best.onnx')
 
index be09729ac1021d2782141fdac90e8205893edb7a..fe55e4b4817243ad06c34c7610fe2d44d6e44446 100644 (file)
@@ -15,6 +15,7 @@ dataset_name = 'image_folder_classification'
 model_names = ['mobilenet_v2', 'resnet18', 'resnet50', 'resnext50_32x4d', 'shufflenet_v2_x1_0']
 img_resize = (256,256)
 rand_crop = (224,224)
+opset_version = 9
 
 # the saving path - you can choose any path
 save_path = './data/checkpoints'
@@ -40,6 +41,6 @@ for model_name in model_names:
     torch.save(model.state_dict(), model_path)
 
     # write the onnx model
-    opset_version=9
     model_path=os.path.join(save_path, f'{model_name}_opset{opset_version}.onnx')
-    torch.onnx.export(model, rand_input, model_path, export_params=True, verbose=False, opset_version=opset_version)
+    torch.onnx.export(model, rand_input, model_path, export_params=True, verbose=False,
+                      do_constant_folding=True, opset_version=opset_version)
index b637955e8387176dcae1929777097211a3ac15f8..e6a0f900efcd7d7ee5c3d481adeada733d0baa63 100644 (file)
@@ -57,7 +57,7 @@ def get_config():
     args.lr_calib = 0.05                                # lr for bias calibration
 
     args.rand_seed = 1                                  # random seed
-    args.generate_onnx = False                          # apply quantized inference or not
+    args.save_onnx = False                          # apply quantized inference or not
     args.print_model = False                            # print the model to text
     args.run_soon = True                                # Set to false if only cfs files/onnx  modelsneeded but no training
     args.parallel_model = True                          # parallel or not
@@ -75,6 +75,8 @@ def get_config():
     args.histogram_range = True                         # histogram range for calibration
     args.per_channel_q = False                          # apply separate quantizion factor for each channel in depthwise or not
     args.bias_calibration = False                        # apply bias correction during quantized inference calibration
+
+    args.opset_version = 9                              # onnx opset version
     return args
 
 
@@ -246,7 +248,8 @@ def write_onnx_model(args, model, save_path, name='checkpoint.onnx'):
     dummy_input = create_rand_inputs(args, is_cuda)
     #
     model.eval()
-    torch.onnx.export(model, dummy_input, os.path.join(save_path,name), export_params=True, verbose=False)
+    torch.onnx.export(model, dummy_input, os.path.join(save_path,name), export_params=True, verbose=False,
+                      do_constant_folding=True, opset_version=args.opset_version)
 
 def save_checkpoint(state, is_best, filename='checkpoint.pth.tar'):
     torch.save(state, filename)
index d439c28b1bb9e73cfed13d415277fb9ed8fa127d..397422225bc771a7421a0f8319a71fec4d611ae8 100644 (file)
@@ -118,7 +118,7 @@ def get_config():
     args.gpu_mode = True                        #False will make inference run on CPU
     args.write_layer_ip_op= False               #True will make it tap inputs outputs for layers
     args.file_format = 'none'                   #Ip/Op tapped points for each layer: None : it will not be written but print will still appear
-    args.generate_onnx = True
+    args.save_onnx = True
     args.remove_ignore_lbls_in_pred = False     #True: if in the pred where GT has ignore label do not visualize for GT visualization
     args.do_pred_cordi_f2r = False              #true: Do f2r operation on detected location for interet point task
     args.depth_cmap_plasma = False      
@@ -131,6 +131,8 @@ def get_config():
     args.viz_op_type = None
     args.car_mask = None
     args.en_accuracy_measurement = True         #enabling accuracy measurement makes whole operation sequential and hence slows down inference significantly.
+
+    args.opset_version = 9                      # onnx opset version
     return args
 
 
@@ -172,7 +174,7 @@ def main(args):
     assert args.pretrained is not None, 'pretrained path must be provided'
 
     # onnx generation is filing for post quantized module
-    # args.generate_onnx = False if (args.quantize) else args.generate_onnx
+    # args.save_onnx = False if (args.quantize) else args.save_onnx
     #################################################
     # set some global flags and initializations
     # keep it in args for now - although they don't belong here strictly
@@ -289,7 +291,7 @@ def main(args):
     # load pretrained weights
     xnn.utils.load_weights(get_model_orig(model), pretrained=pretrained_data, change_names_dict=change_names_dict)
 
-    if args.generate_onnx:
+    if args.save_onnx:
         write_onnx_model(args, model, save_path, name='model_best.onnx')
     #################################################
     # multi gpu mode is not yet supported with quantization in evaluate
@@ -866,7 +868,8 @@ def write_onnx_model(args, model, save_path, name='checkpoint.onnx'):
     input_list = create_rand_inputs(args, is_cuda=is_cuda)
     #
     model.eval()
-    torch.onnx.export(model, input_list, os.path.join(save_path, name), export_params=True, verbose=False)
+    torch.onnx.export(model, input_list, os.path.join(save_path, name), export_params=True, verbose=False,
+                      do_constant_folding=True, opset_version=args.opset_version)
     # torch onnx export does not update names. Do it using onnx.save
 
 
index 5823c53deb5790c730d1132a3734b2a71451bb13..0a02316259cbe491b36073d3d40049bcc3b6234f 100644 (file)
@@ -123,14 +123,16 @@ def get_config():
     args.gpu_mode = True                        #False will make inference run on CPU
     args.write_layer_ip_op= False               #True will make it tap inputs outputs for layers
     args.file_format = 'none'                   #Ip/Op tapped points for each layer: None : it will not be written but print will still appear
-    args.generate_onnx = True
+    args.save_onnx = True
     args.remove_ignore_lbls_in_pred = False     #True: if in the pred where GT has ignore label do not visualize for GT visualization
     args.do_pred_cordi_f2r = False              #true: Do f2r operation on detected location for interet point task
     args.depth_cmap_plasma = False      
     args.visualize_gt = False                   #to vis pred or GT
-    args.viz_depth_color_type = 'plasma'       #color type for dpeth visualization
+    args.viz_depth_color_type = 'plasma'        #color type for dpeth visualization
     args.depth = [False]
     args.dump_layers = True
+
+    args.opset_version = 9                      # onnx opset version
     return args
 
 
@@ -170,7 +172,7 @@ def main(args):
     assert args.pretrained is not None, 'pretrained path must be provided'
 
     # onnx generation is filing for post quantized module
-    # args.generate_onnx = False if (args.quantize) else args.generate_onnx
+    # args.save_onnx = False if (args.quantize) else args.save_onnx
     #################################################
     # set some global flags and initializations
     # keep it in args for now - although they don't belong here strictly
@@ -825,7 +827,8 @@ def write_onnx_model(args, model, save_path, name='checkpoint.onnx'):
     input_list = create_rand_inputs(args, is_cuda=is_cuda)
     #
     model.eval()
-    torch.onnx.export(get_model_orig(model), input_list, os.path.join(save_path, name), export_params=True, verbose=False)
+    torch.onnx.export(get_model_orig(model), input_list, os.path.join(save_path, name), export_params=True, verbose=False,
+                      do_constant_folding=True, opset_version=args.opset_version)
     # torch onnx export does not update names. Do it using onnx.save
 
 
index 4674bfe908b39125f70ef9a8a527db3afe85ac52..4b7f14d74fc26208f1e1de2d38881254e079896d 100644 (file)
@@ -54,7 +54,7 @@ def get_config():
     args.lr_calib = 0.05                                # lr for bias calibration
 
     args.rand_seed = 1                                  # random seed
-    args.generate_onnx = False                          # apply quantized inference or not
+    args.save_onnx = False                          # apply quantized inference or not
     args.print_model = False                            # print the model to text
     args.run_soon = True                                # Set to false if only cfs files/onnx  modelsneeded but no training
     args.parallel_model = True                          # parallel or not
@@ -71,6 +71,8 @@ def get_config():
     args.histogram_range = True                         # histogram range for calibration
     args.per_channel_q = False                          # apply separate quantizion factor for each channel in depthwise or not
     args.bias_calibration = False                        # apply bias correction during quantized inference calibration
+
+    args.opset_version = 9                              # onnx opset version
     return args
 
 
@@ -84,7 +86,7 @@ def main(args):
 
     #################################################
     # onnx generation is filing for post quantized module
-    args.generate_onnx = False if (args.quantize) else args.generate_onnx
+    args.save_onnx = False if (args.quantize) else args.save_onnx
 
     if args.save_path is None:
         save_path = get_save_path(args)
@@ -172,7 +174,7 @@ def main(args):
         count_flops(args, model)
 
     #################################################
-    if args.generate_onnx:
+    if args.save_onnx:
         write_onnx_model(args, get_model_orig(model), save_path)
     #
 
@@ -326,7 +328,8 @@ def write_onnx_model(args, model, save_path, name='checkpoint.onnx'):
     dummy_input = create_rand_inputs(args, is_cuda)
     #
     model.eval()
-    torch.onnx.export(model, dummy_input, os.path.join(save_path,name), export_params=True, verbose=False)
+    torch.onnx.export(model, dummy_input, os.path.join(save_path,name), export_params=True, verbose=False,
+                      do_constant_folding=True, opset_version=args.opset_version)
 
 def save_checkpoint(state, is_best, filename='checkpoint.pth.tar'):
     torch.save(state, filename)
index 58e8be83a2af4c556ede9a712cb0e521130fe613..fafaa45ce6099329d1bcc2836370facee40a7708 100644 (file)
@@ -85,7 +85,7 @@ def get_config():
     args.data_augument = 'inception'                    # data augumentation method, choices=['inception','resize','adaptive_resize']
     args.count_flops = True                             # count flops and report
 
-    args.generate_onnx = True                           # apply quantized inference or not
+    args.save_onnx = True                           # apply quantized inference or not
     args.print_model = False                            # print the model to text
     args.run_soon = True                                # Set to false if only cfs files/onnx  modelsneeded but no training
 
@@ -255,7 +255,7 @@ def main(args):
         count_flops(args, model)
 
     #################################################
-    if args.generate_onnx and (any(p in args.phase for p in ('training','calibration')) or (args.run_soon == False)):
+    if args.save_onnx and (any(p in args.phase for p in ('training','calibration')) or (args.run_soon == False)):
         write_onnx_model(args, get_model_orig(model), save_path)
     #
 
@@ -437,7 +437,8 @@ def write_onnx_model(args, model, save_path, name='checkpoint.onnx'):
     dummy_input = create_rand_inputs(args, is_cuda)
     #
     model.eval()
-    torch.onnx.export(model, dummy_input, os.path.join(save_path,name), export_params=True, verbose=False, opset_version=args.opset_version)
+    torch.onnx.export(model, dummy_input, os.path.join(save_path,name), export_params=True, verbose=False,
+                      do_constant_folding=True, opset_version=args.opset_version)
 
 
 def train(args, train_loader, model, criterion, optimizer, epoch):
@@ -618,7 +619,7 @@ def save_checkpoint(args, save_path, model, state, is_best, filename='checkpoint
         bestname = os.path.join(save_path, 'model_best.pth.tar')
         shutil.copyfile(filename, bestname)
     #
-    if args.generate_onnx:
+    if args.save_onnx:
         write_onnx_model(args, model, save_path, name='checkpoint.onnx')
         if is_best:
             write_onnx_model(args, model, save_path, name='model_best.onnx')
index 775bc484341477e0fe5bc4343f6a10edfcf88c70..d9f41ed83b8ce0e01f12cc335d18d29ac8bdd7d8 100644 (file)
@@ -147,7 +147,7 @@ def get_config():
     args.parallel_criterion = True                      # Usedata parallel for loss and metric
 
     args.evaluate_start = True                          # evaluate right at the begining of training or not
-    args.generate_onnx = True                           # apply quantized inference or not
+    args.save_onnx = True                               # apply quantized inference or not
     args.print_model = False                            # print the model to text
     args.run_soon = True                                # To start training after generating configs/models
 
@@ -380,9 +380,8 @@ def main(args):
         count_flops(args, model)
 
     #################################################
-    if args.generate_onnx and (any(args.phase in p for p in ('training','calibration')) or (args.run_soon == False)):
-        write_onnx_model(args, get_model_orig(model), save_path, export_torch_script=False)
-
+    if args.save_onnx and (any(args.phase in p for p in ('training','calibration')) or (args.run_soon == False)):
+        write_onnx_model(args, get_model_orig(model), save_path, save_traced_model=False)
     #
 
     #################################################
@@ -925,7 +924,7 @@ def derive_node_name(input_name):
 
 
 #torch onnx export does not update names. Do it using onnx.save
-def add_node_names(onnx_model_name= []):
+def add_node_names(onnx_model_name):
     onnx_model = onnx.load(onnx_model_name)
     for i in range(len(onnx_model.graph.node)):
         for j in range(len(onnx_model.graph.node[i].input)):
@@ -940,21 +939,24 @@ def add_node_names(onnx_model_name= []):
     #update model inplace
     onnx.save(onnx_model, onnx_model_name)
 
-def write_onnx_model(args, model, save_path, name='checkpoint.onnx', export_torch_script=False):
+
+def write_onnx_model(args, model, save_path, name='checkpoint.onnx', save_traced_model=False):
     is_cuda = next(model.parameters()).is_cuda
     input_list = create_rand_inputs(args, is_cuda=is_cuda)
     #
     model.eval()
-    torch.onnx.export(model, input_list, os.path.join(save_path, name), export_params=True, verbose=False, opset_version=args.opset_version)
+    torch.onnx.export(model, input_list, os.path.join(save_path, name), export_params=True, verbose=False,
+                      do_constant_folding=True, opset_version=args.opset_version)
+
     #torch onnx export does not update names. Do it using onnx.save
     add_node_names(onnx_model_name = os.path.join(save_path, name))
 
-    #write troch script model 
-    if export_torch_script:
-        traced_script_module = torch.jit.trace(model, (input_list,))
-        pretrained_files = args.pretrained if isinstance(args.pretrained, (list, tuple)) else [args.pretrained]
-        trace_model_name = pretrained_files[0].replace('.pth.tar', '_{}_{}_traced_model.pth'.format(args.img_resize[0], args.img_resize[1]))
-        torch.jit.save(traced_script_module, trace_model_name)
+    if save_traced_model:
+        traced_model = torch.jit.trace(model, (input_list,))
+        traced_save_path = os.path.join(save_path, 'traced_model.pth')
+        torch.jit.save(traced_model, traced_save_path)
+    #
+
 
 ###################################################################
 def write_output(args, prefix, val_epoch_size, iter, epoch, dataset, output_writer, input_images, task_outputs, task_targets, metric_names, writer_idx):
@@ -1102,7 +1104,7 @@ def save_checkpoint(args, save_path, model, checkpoint_dict, is_best, filename='
     if is_best:
         shutil.copyfile(os.path.join(save_path,filename), os.path.join(save_path,'model_best.pth.tar'))
     #
-    if args.generate_onnx:
+    if args.save_onnx:
         write_onnx_model(args, model, save_path, name='checkpoint.onnx')
         if is_best:
             write_onnx_model(args, model, save_path, name='model_best.onnx')
index e45908d64c4b23804e284936329a2271b875f364..8dd2afb4cf58009223d7ba1b4d36187afee157c1 100644 (file)
@@ -31,7 +31,7 @@ class MultiTask(torch.nn.Module):
         self.lr = 1e-4  #1e-2 #1e-3 #1e-4 #1e-5
         self.momentum = 0.9
         self.beta = 0.999
-        self.multi_task_type = ('uncertainty' if multi_task_type == 'learned' else multi_task_type)
+        self.multi_task_type = ('pseudo_grad_norm' if multi_task_type == 'learned' else multi_task_type)
         self.output_type = output_type
         self.long_smooth = 1e-6
         self.short_smooth = 1e-3
index 003c179dfcb156f66b05e65dd5eadee64ce83f75..8bab95da30ba8f0bcc0da3d1853e6fe7b0de9edb 100644 (file)
@@ -9,6 +9,7 @@ from .deconv_blocks import *
 # older ResizeTo, UpsampleTo. The older modules may be removed in a later version.
 ##############################################################################################
 
+# resize with output size or scale factor
 def resize_with(x, size=None, scale_factor=None, mode='nearest', align_corners=None):
     assert size is None or scale_factor is None, 'both size and scale_factor must not be specified'
     assert size is not None or scale_factor is not None, 'at least one of size or scale factor must be specified'
@@ -32,6 +33,26 @@ def resize_with(x, size=None, scale_factor=None, mode='nearest', align_corners=N
     return y
 
 
+# always use scale factor to do the rescaling. if scale factor is not provided, generate it from the size.
+def resize_with_scale_factor(x, size=None, scale_factor=None, mode='nearest', align_corners=None):
+    assert size is None or scale_factor is None, 'both size and scale_factor must not be specified'
+    assert size is not None or scale_factor is not None, 'at least one of size or scale factor must be specified'
+    assert isinstance(x, torch.Tensor), 'must provide a single tensor as input'
+    if scale_factor is None:
+        if isinstance(size, torch.Tensor):
+            size = [float(s) for s in size]
+        elif isinstance(size, (int,float)):
+            size = [size,size]
+        #
+        if isinstance(size, (list,tuple)) and len(size) > 2:
+            size = size[-2:]
+        #
+        x_size = [float(s) for s in x.size()][-2:]
+        scale_factor = [float(s)/float(x_s) for (s,x_s) in zip(size,x_size)]
+    #
+    y = resize_with(x, scale_factor=scale_factor, mode=mode, align_corners=align_corners)
+
+
 class ResizeWith(torch.nn.Module):
     def __init__(self, size=None, scale_factor=None, mode='nearest', align_corners=None):
         super().__init__()
diff --git a/modules/pytorch_jacinto_ai/xnn/quantize/quant_train_utils.py b/modules/pytorch_jacinto_ai/xnn/quantize/quant_train_utils.py
deleted file mode 100644 (file)
index 23965eb..0000000
+++ /dev/null
@@ -1,402 +0,0 @@
-import warnings
-import numpy as np
-import torch
-from .. import utils
-from .. import layers
-from .quant_base_module import *
-from .quant_utils import *
-
-###########################################################
-class QuantTrainParams:
-    pass
-
-
-def get_qparams():
-    qparams = QuantTrainParams()
-    qparams.inputs = []
-    qparams.modules = []
-    return qparams
-
-
-def is_merged_layer(x):
-    is_merged = (hasattr(x, 'qparams') and isinstance(x.qparams, QuantTrainParams) and len(x.qparams.modules)>0)
-    return is_merged
-
-
-###########################################################
-class QuantTrainConv2d(torch.nn.Conv2d):
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.quantize_enable = True
-        self.bitwidth_weights = None
-        self.bitwidth_activations = None
-        self.per_channel_q = False
-
-    def forward(self, x):
-        is_merged = is_merged_layer(x)
-        if is_merged:
-           warnings.warn('please see if a PAct can be inserted before this module to collect ranges')
-        #
-
-        y = super().forward(x)
-
-        if not self.quantize_enable:
-            # if quantization is disabled - return
-            return y
-        #
-
-        qparams = get_qparams()
-        qparams.inputs.append(x)
-        qparams.modules.append(self)
-        y.qparams = qparams
-        #
-        return y
-    #
-
-
-###########################################################
-class QuantTrainConvTranspose2d(torch.nn.ConvTranspose2d):
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.quantize_enable = True
-        self.bitwidth_weights = None
-        self.bitwidth_activations = None
-        self.per_channel_q = False
-
-    def forward(self, x):
-        is_merged = is_merged_layer(x)
-        if is_merged:
-           warnings.warn('please see if a PAct can be inserted before this module to collect ranges')
-        #
-
-        y = super().forward(x)
-
-        if not self.quantize_enable:
-            # if quantization is disabled - return
-            return y
-        #
-
-        qparams = get_qparams()
-        qparams.inputs.append(x)
-        qparams.modules.append(self)
-        y.qparams = qparams
-        #
-        return y
-    #
-
-
-###########################################################
-class QuantTrainBatchNorm2d(torch.nn.BatchNorm2d):
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.quantize_enable = True
-
-
-    def forward(self, x):
-        y = super().forward(x)
-
-        if not self.quantize_enable:
-            # if quantization is disabled - return
-            return y
-        #
-
-        if is_merged_layer(x) and utils.is_conv_deconv(x.qparams.modules[-1]):
-            qparams = get_qparams()
-            qparams.inputs = [x.qparams.inputs[0], x]
-            qparams.modules = [x.qparams.modules[0], self]
-            y.qparams = qparams
-        #
-
-        return y
-    #
-
-
-###########################################################
-# fake quantized PAct2 for training
-class QuantTrainPAct2(layers.PAct2):
-    def __init__(self, inplace=False, signed=False, clip_range=None, bitwidth_weights=None, bitwidth_activations=None, per_channel_q=False):
-        super().__init__(inplace=inplace, signed=signed, clip_range=clip_range)
-
-        self.bitwidth_weights = bitwidth_weights
-        self.bitwidth_activations = bitwidth_activations
-        self.per_channel_q = per_channel_q
-        # weight shrinking is done by clamp weights - set this factor to zero.
-        # this must me zero - as in pact we do not have the actual weight param, but just a temporary tensor
-        # so any clipping we do here is not stored int he weight params
-        self.range_shrink_weights = 0.0
-        self.round_dither = 0.0
-        self.update_range = True
-        self.quantize_enable = True
-        self.quantize_weights = True
-        self.quantize_bias = True
-        self.quantize_activations = True
-        self.constrain_weights = True
-        self.bias_calibration = False
-        # save quantized weight/bias once in a while into the params - not needed
-        self.params_save_frequency = None #(10 if self.bias_calibration else None)
-
-        # set to STRAIGHT_THROUGH_ESTIMATION or ALPHA_BLENDING_ESTIMATION
-        # For a comparison of STE and ABE, read:
-        # Learning low-precision neural networks without Straight-Through Estimator (STE):
-        # https://arxiv.org/pdf/1903.01061.pdf
-        self.quantized_estimation_type = QuantEstimationType.STRAIGHT_THROUGH_ESTIMATION
-        self.alpha_blending_estimation_factor = 0.5
-
-        if (layers.PAct2.PACT2_RANGE_LEARN):
-            assert self.quantized_estimation_type != QuantEstimationType.STRAIGHT_THROUGH_ESTIMATION, \
-                'straight through estimation should not used when PACT clip values are being learned as it doesnt backpropagate gradients though quantization'
-        #
-
-
-    def forward(self, x):
-        assert (self.bitwidth_weights is not None) and (self.bitwidth_activations is not None), \
-                        'bitwidth_weights and bitwidth_activations must not be None'
-
-        # the pact range update happens here - but range clipping depends on quantize_enable
-        y = super().forward(x, update_range=self.update_range, enable=self.quantize_enable)
-
-        if not self.quantize_enable:
-            return y
-        #
-
-        # previous intermediate outputs and other infoirmation are avaliable
-        # for example - conv-bn-relu may need to be merged together.
-        is_merged = is_merged_layer(x)
-        if is_merged:
-            qparams = x.qparams
-            xorg = qparams.inputs[0]
-            conv, weight, bias = self.merge_quantize_weights(qparams, is_merged)
-        else:
-            conv, weight, bias = None, None, None
-        #
-
-        if is_merged and utils.is_conv(conv):
-            xq = torch.nn.functional.conv2d(xorg, weight, bias, stride=conv.stride, padding=conv.padding, dilation=conv.dilation, groups=conv.groups)
-        elif is_merged and utils.is_deconv(conv):
-            xq = torch.nn.functional.conv_transpose2d(xorg, weight, bias, stride=conv.stride, padding=conv.padding, output_padding=conv.output_padding,
-                                                      dilation=conv.dilation, groups=conv.groups)
-        else:
-            xq = x
-        #
-
-        if (self.quantize_enable and self.quantize_activations):
-            clip_min, clip_max, scale, scale_inv = self.get_clips_scale_act()
-            width_min, width_max = self.get_widths_act()
-            # no need to call super().forward here as clipping with width_min/windth_max-1 after scaling has the same effect.
-            # currently the gradient is set to 1 in round_up_g. shouldn't the gradient be (y-x)?
-            # see eqn 6 in https://arxiv.org/pdf/1903.08066v2.pdf
-            # yq = layers.clamp_g(layers.round_up_g(xq * scale), width_min, width_max-1, self.training) * scale_inv
-            yq = layers.quantize_dequantize_g(xq, scale, width_min, width_max-1, self.power2, 'round_up')
-        else:
-            yq = super().forward(xq, update_range=False, enable=True)
-        #
-
-        if (self.quantized_estimation_type == QuantEstimationType.STRAIGHT_THROUGH_ESTIMATION):
-            # replace the float output with quantized version
-            # the entire weight merging and quantization process is bypassed in the forward pass
-            # however, the backward gradients flow through only the float path - this is called straight through estimation (STE)
-            with torch.no_grad():
-                y.data.copy_(yq.data)
-            #
-        elif self.training and (self.quantized_estimation_type == QuantEstimationType.ALPHA_BLENDING_ESTIMATION):
-            # TODO: vary the alpha blending factor over the epochs
-            y = y * (1.0-self.alpha_blending_estimation_factor) + yq * self.alpha_blending_estimation_factor
-        elif (self.quantized_estimation_type == QuantEstimationType.QUANTIZED_THROUGH_ESTIMATION):
-            # pass on the quantized output - the backward gradients also flow through quantization.
-            # however, note the gradients of round and ceil operators are forced to be unity (1.0).
-            y = yq
-        else:
-            assert False, f'unsupported value for quantized_estimation_type: {self.quantized_estimation_type}'
-        #
-
-        return y
-    #
-
-    def apply_constrain_weights(self, merged_weight):
-        return constrain_weight(merged_weight)
-
-
-    def merge_quantize_weights(self, qparams, is_merged):
-        # store the quantized weights and biases in-frequently - otherwise learning will be poor
-        # since this may not be done at the of the epoch, there can be a slight mismatch in validation accuracy
-        first_training_iter = self.training and (self.num_batches_tracked == 0)
-        is_store_weight_bias_iter = (self.params_save_frequency is not None) and (torch.remainder(self.num_batches_tracked, self.params_save_frequency) == 0)
-
-        conv, bn = None, None
-        # merge weight and bias (if possible) across layers
-        if len(qparams.modules) == 2 and utils.is_conv_deconv(qparams.modules[-2]) and isinstance(qparams.modules[-1], torch.nn.BatchNorm2d):
-            conv = qparams.modules[-2]
-            conv_bias = conv.bias if (conv.bias is not None) else torch.tensor(0.0).to(conv.weight.device)
-            #
-            bn = qparams.modules[-1]
-            bn_weight = bn.weight if (bn.weight is not None) else torch.tensor(0.0).to(bn.running_mean.device)
-            bn_bias = bn.bias if (bn.bias is not None) else torch.tensor(0.0).to(bn.running_mean.device)
-            #
-            merged_scale = bn_weight / torch.sqrt(bn.running_var + bn.eps)
-            merged_bias = (conv_bias - bn.running_mean) * merged_scale + bn_bias
-            merged_weight = conv.weight * merged_scale.view(-1, 1, 1, 1)
-            #
-            merged_scale_sign = merged_scale.sign()
-            merged_scale_sign = merged_scale_sign + (merged_scale_sign == 0) # make the 0s in sign to 1
-            merged_scale_eps = merged_scale.abs().clamp(min=bn.eps) * merged_scale_sign
-            merged_scale_inv = 1.0 / merged_scale_eps
-            #
-        elif len(qparams.modules) == 1 and utils.is_conv_deconv(qparams.modules[-1]):
-            conv = qparams.modules[-1]
-            merged_weight = conv.weight
-            merged_bias = conv.bias if (conv.bias is not None) else torch.zeros(conv.out_channels).to(conv.weight.device)
-            merged_scale = torch.ones(conv.out_channels).to(conv.weight.device)
-            merged_scale_inv = torch.ones(conv.out_channels).to(conv.weight.device)
-        elif len(qparams.modules) == 1 and isinstance(qparams.modules[-1], torch.nn.BatchNorm2d):
-            assert False, f'quantization: previous layer is a BN without Conv {qparams.modules} - prease inspect the model carefully'
-            bn = qparams.modules[-1]
-            merged_weight = bn.weight if (bn.weight is not None) else torch.zeros(bn.num_features).to(bn.running_mean.device)
-            merged_bias = bn.bias if (bn.bias is not None) else torch.zeros(bn.num_features).to(bn.running_mean.device)
-        else:
-            assert False, f'quantization: previous layer is unrecognized {qparams.modules} - prease inspect the model carefully'
-            merged_weight = 0.0
-            merged_bias = 0.0
-        #
-
-        # quantize weight and bias
-        if (conv is not None):
-            if (self.quantize_enable and self.quantize_weights):
-                if self.constrain_weights and first_training_iter:
-                    with torch.no_grad():
-                        # clamp merged weights, invert the bn and copy to conv weight
-                        constrained_weight = self.apply_constrain_weights(merged_weight.data)
-                        merged_weight.data.copy_(constrained_weight.data)
-                        # store clipped weight after inverting bn
-                        conv.weight.data.copy_(merged_weight.data * merged_scale_inv.view(-1, 1, 1, 1))
-                    #
-                #
-
-                is_dw = utils.is_dwconv(conv)
-                use_per_channel_q = (is_dw and self.per_channel_q is True) or (self.per_channel_q == 'all')
-                if use_per_channel_q:
-                    channels = int(merged_weight.size(0))
-                    scale2 = torch.zeros(channels,1,1,1).to(merged_weight.device)
-                    scale_inv2 = torch.zeros(channels,1,1,1).to(merged_weight.device)
-                    for chan_id in range(channels):
-                        clip_min, clip_max, scale2_value, scale_inv2_value = self.get_clips_scale_w(merged_weight[chan_id])
-                        scale2[chan_id,0,0,0] = scale2_value
-                        scale_inv2[chan_id,0,0,0] = scale_inv2_value
-                    #
-                else:
-                    clip_min, clip_max, scale2, scale_inv2 = self.get_clips_scale_w(merged_weight)
-                #
-                width_min, width_max = self.get_widths_w()
-                # merged_weight = layers.clamp_g(layers.round_sym_g(merged_weight * scale2), width_min, width_max-1, self.training) * scale_inv2
-                merged_weight = layers.quantize_dequantize_g(merged_weight, scale2, width_min, width_max-1, self.power2, 'round_sym')
-            #
-
-            if (self.quantize_enable and self.quantize_bias):
-                bias_width_min, bias_width_max = self.get_widths_bias()
-                bias_clip_min, bias_clip_max, bias_scale2, bias_scale_inv2 = self.get_clips_scale_bias(merged_bias)
-                # merged_bias = layers.clamp_g(layers.round_sym_g(merged_bias * bias_scale2), bias_width_min, bias_width_max-1, self.training) * bias_scale_inv2
-                merged_bias = layers.quantize_dequantize_g(merged_bias, bias_scale2, bias_width_min, bias_width_max - 1, self.power2, 'round_sym')
-            #
-
-            # invert the bn operation and store weights/bias
-            if self.training and is_store_weight_bias_iter:
-                with torch.no_grad():
-                    if self.quantize_enable and self.quantize_weights:
-                        conv.weight.data.copy_(merged_weight.data * merged_scale_inv.view(-1, 1, 1, 1))
-                    #
-                    if self.quantize_enable and self.quantize_bias:
-                        if conv.bias is not None:
-                            if bn is not None:
-                                conv_bias = (merged_bias - bn_bias) * merged_scale_inv.view(-1) + bn.running_mean
-                                conv.bias.data.copy_(conv_bias.data)
-                            else:
-                                conv.bias.data.copy_(merged_bias.data)
-                            #
-                        elif bn is not None and bn.bias is not None:
-                            bn_bias = merged_bias + bn.running_mean * merged_scale.view(-1)
-                            bn.bias.data.copy_(bn_bias.data)
-                        #
-                    #
-                #
-            #
-        #
-        return conv, merged_weight, merged_bias
-
-
-    def get_clips_w(self, tensor):
-        # find the clip values
-        w_min, w_max = utils.extrema_fast(tensor.data, percentile_range_shrink=self.range_shrink_weights)
-        clip_max = torch.max(torch.abs(w_min), torch.abs(w_max))
-        clip_max = torch.clamp(clip_max, min=self.eps)
-        # in range learning mode + training - this power2 is taken care in the quantize function
-        use_power2 = (self.power2 and (not (self.PACT2_RANGE_LEARN and self.training)))
-        clip_max2 = layers.functional.ceil2_g(clip_max) if use_power2 else clip_max
-        clip_min2 = -clip_max2
-        return (clip_min2, clip_max2)
-
-    # bias uses the same kind of clips
-    get_clips_bias = get_clips_w
-
-
-    def get_clips_scale_w(self, weight):
-        # convert to scale
-        clip_min, clip_max = self.get_clips_w(weight)
-        width_min, width_max = self.get_widths_w()
-        scale2 = (width_max / clip_max)
-        scale2 = torch.clamp(scale2, min=self.eps)
-        scale_inv2 = scale2.pow(-1.0)
-        return (clip_min, clip_max, scale2, scale_inv2)
-
-
-    # in reality, bias quantization will also depend on the activation scale
-    # this is not perfect - just a quick and dirty quantization for bias
-    def get_clips_scale_bias(self, bias):
-        # convert to scale
-        clip_min, clip_max = self.get_clips_bias(bias)
-        width_min, width_max = self.get_widths_bias()
-        scale2 = (width_max / clip_max)
-        scale2 = torch.clamp(scale2, min=self.eps)
-        scale_inv2 = scale2.pow(-1.0)
-        return (clip_min, clip_max, scale2, scale_inv2)
-
-
-    def get_widths_w(self):
-        # weights
-        bw = (self.bitwidth_activations - 1)
-        width_max = np.power(2.0, bw)
-        width_min = -width_max
-        # return
-        return (width_min, width_max)
-
-
-    def get_widths_bias(self):
-        # bias
-        bitwidth_bias = (2*self.bitwidth_activations)
-        bias_width_max = np.power(2.0, bitwidth_bias-1)
-        bias_width_min = -bias_width_max
-        # return
-        return (bias_width_min, bias_width_max)
-
-
-    # activation utility functions
-    def get_clips_scale_act(self):
-        # convert to scale
-        clip_min, clip_max = self.get_clips_act()
-        width_min, width_max = self.get_widths_act()
-        scale2 = width_max / clip_max
-        scale2 = torch.clamp(scale2, min=self.eps)
-        scale_inv2 = scale2.pow(-1.0)
-        return (clip_min, clip_max, scale2, scale_inv2)
-
-
-    def get_widths_act(self):
-        if self.signed is None:
-            clip_min, clip_max = self.get_clips_act()
-            signed = (clip_min < 0.0)
-        else:
-            signed = self.signed
-        #
-        bw = (self.bitwidth_activations - 1) if signed else self.bitwidth_activations
-        width_max = np.power(2.0, bw)
-        width_min = -width_max if signed else 0.0
-        return width_min, width_max
-
index 530a039c3939e5fbcbf1315ce16bd1dfffa6b601..81801c8e6be2907d818f1e8b730d04a96cbf9f70 100755 (executable)
@@ -115,7 +115,7 @@ args.histogram_range = True
 
 args.gpu_mode = True
 args.write_layer_ip_op = False
-args.generate_onnx = True
+args.save_onnx = True
 
 ################################
 for key in vars(cmds):
index a161cd7d40f3c043efc877f8f3a4f6ad4e8bba85..a468b1283c782e2324d748e9c9f3ef423875e073 100755 (executable)
@@ -113,7 +113,7 @@ args.weight_decay = 4e-5                #4e-5 #1e-4
 args.rand_scale = (0.2, 1.0)            #(0.08, 1.0)
 
 #args.print_model = True
-#args.generate_onnx = False
+#args.save_onnx = False
 #args.run_soon = True #default(True) #Set to false if only cfs files/onnx  models needed but no training is required
 #args.phase = 'validation'
 # args.evaluate_start = False
index 97a6aed0bfd0dbc0cbb1dc1da55a263a296811ed..561a78a79be4c9e918c9b518345ddc4f8ae8e1da 100755 (executable)
@@ -115,7 +115,7 @@ args.workers = 12                       # more workers may speedup
 #args.phase = 'validation'
 #args.quantize = True
 #args.print_model = True
-#args.generate_onnx = False
+#args.save_onnx = False
 #args.run_soon = False
 #args.evaluate_start = False
 
index d1e190eaeb11f55a563a77ef03247f0f1b0cb63f..00e2d96629e3a430f58c7167334d25d099c6ed27 100755 (executable)
@@ -16,7 +16,7 @@ parser.add_argument('--lr_clips', type=float, default=None, help='Learning rate
 parser.add_argument('--lr_calib', type=float, default=None, help='Learning rate for calibration')
 parser.add_argument('--model_name', type=str, default=None, help='model name')
 parser.add_argument('--dataset_name', type=str, default=None, help='dataset name')
-parser.add_argument('--image_folders', type=str, default=('leftImg8bit_flow_confidence', 'leftImg8bit'), nargs='*', help='image_folders')
+parser.add_argument('--image_folders', type=str, default=('leftImg8bit_flow_confidence_768x384', 'leftImg8bit'), nargs='*', help='image_folders')
 parser.add_argument('--is_flow', type=splitstr2bool, default=[[False, False],[False]] ,nargs='*', help='whether any input or target is optical flow')
 parser.add_argument('--data_path', type=str, default=None, help='data path')
 parser.add_argument('--epoch_size', type=float, default=None, help='epoch size. using a fraction will reduce the data used for one epoch')
@@ -112,10 +112,10 @@ args.model_config.aspp_dil = (2, 4, 6)
 # TODO: this is not clean - fix it later
 args.dataset_config.image_folders = cmds.image_folders
 
-args.generate_onnx = True
+args.save_onnx = True
 #args.evaluate = True
 #args.quantize = True
-#args.generate_onnx = True
+#args.save_onnx = True
 
 
 ################################
index 533831832b2d2218148631cad913ec4cb26039ea..a50550025ba11f49f2b74d484a9e454d47a74e98 100755 (executable)
@@ -16,6 +16,7 @@ parser.add_argument('--lr_clips', type=float, default=None, help='Learning rate
 parser.add_argument('--lr_calib', type=float, default=None, help='Learning rate for calibration')
 parser.add_argument('--model_name', type=str, default=None, help='model name')
 parser.add_argument('--dataset_name', type=str, default=None, help='dataset name')
+parser.add_argument('--image_folders', type=str, default=('leftImg8bit_flow_confidence_768x384', 'leftImg8bit'), nargs='*', help='image_folders')
 parser.add_argument('--data_path', type=str, default=None, help='data path')
 parser.add_argument('--epoch_size', type=float, default=None, help='epoch size. using a fraction will reduce the data used for one epoch')
 parser.add_argument('--epochs', type=int, default=None, help='number of epochs')
@@ -36,6 +37,7 @@ parser.add_argument('--per_channel_q', type=str2bool, default=None, help='run on
 parser.add_argument('--bias_calibration', type=str2bool, default=None, help='run only evaluation and no training')
 parser.add_argument('--bitwidth_weights', type=int, default=None, help='bitwidth for weight quantization')
 parser.add_argument('--bitwidth_activations', type=int, default=None, help='bitwidth for activation quantization')
+parser.add_argument('--multi_task_type', type=str, default=None, help='multi_task_type')
 #
 parser.add_argument('--freeze_bn', type=str2bool, default=None, help='freeze the bn stats or not')
 cmds = parser.parse_args()
@@ -67,15 +69,15 @@ args = train_pixel2pixel.get_config()
 
 #Modify arguments
 
-args.model_name = 'deeplabv3lite_mobilenetv2_ericsun_mi4' #'deeplabv3lite_mobilenetv2_mi4'
+args.model_name = 'deeplabv3lite_mobilenetv2_ericsun' #'deeplabv3lite_mobilenetv2_mi4'
 
-args.dataset_name =  'cityscapes_depth_semantic_five_class_motion_image_dof_conf' #'cityscapes_flow_depth_segmentation_image_pair' #cityscapes_segmentation #'cityscapes_segmentation_dual'
+args.dataset_name =  'cityscapes_depth_semantic_motion_multi_input' #'cityscapes_flow_depth_segmentation_image_pair' #cityscapes_segmentation #'cityscapes_segmentation_dual'
 
 #args.save_path = './data/checkpoints'
 
-args.data_path = './data/datasets/cityscapes_768x384/data'  #./data/pascal-voc/VOCdevkit/VOC2012
+args.data_path = './data/datasets/cityscapes/data'  #./data/pascal-voc/VOCdevkit/VOC2012
 
-args.pretrained = './data/modelzoo/pytorch/semantic_segmentation/cityscapes/jacinto_ai/deeplabv3lite_mobilenetv2_tv_resize768x384_best.pth.tar'
+args.pretrained = './data/modelzoo/pytorch/semantic_segmentation/cityscapes/jacinto_ai/deeplabv3lite_mobilenetv2_ericsun_resize768x384_best.pth.tar'
                             #'./data/checkpoints/cityscapes_depth_semantic_five_class_motion_image_dof_conf/0p9_release/2019-06-27-13-50-10_cityscapes_depth_semantic_five_class_motion_image_dof_conf_deeplabv3lite_mobilenetv2_ericsun_mi4_resize768x384_traincrop768x384/model_best.pth.tar'
                             #'./data/modelzoo/pretrained/pytorch/cityscapes_segmentation/v0.9-2018-12-07-19:38:26_cityscapes_segmentation_deeplabv3lite_mobilenetv2_relu_resize768x384_traincrop768x384_(68.9%)/model_best.pth.tar'
                             #'./data/checkpoints/store/saved/cityscapes_segmentation/v0.7-2018-10-25-13:07:38_cityscapes_segmentation_deeplabv3lite_mobilenetv2_relu_resize1024x512_traincrop512x512_(71.5%)/model_best.pth.tar'
@@ -91,8 +93,11 @@ args.losses = [['supervised_loss', 'scale_loss'], ['segmentation_loss'], ['segme
 args.metrics = [['supervised_relative_error_rng3to80'], ['segmentation_metrics'], ['segmentation_metrics']]
 args.is_flow = [[True,False],[False,False,False]]
 
-args.multi_task_type = 'gradient_norm' #None, 'adaptive', 'learned', 'uncertainty'
-args.multi_task_factors = (0.169, 1.279, 1.553) #None #[1.291, 6.769, 6.852]
+
+# TODO: this is not clean - fix it later
+args.model_config.multi_task_type = cmds.multi_task_type #None, 'adaptive', 'learned', 'uncertainty'
+args.model_config.multi_task = True if cmds.multi_task_type is not None else False
+args.model_config.multi_task_factors = (1.0, 1.0, 1.0) #None #[1.291, 6.769, 6.852] (0.169, 1.279, 1.553)
 args.multi_decoder = True
 
 
@@ -122,7 +127,10 @@ args.transform_rotation = 5             #0  #rotation degrees
 args.model_config.aspp_dil = (2, 4, 6)
 #args.model_config.use_aspp = True
 
-args.generate_onnx = False
+# TODO: this is not clean - fix it later
+args.dataset_config.image_folders = cmds.image_folders
+
+args.save_onnx = False
 #args.phase = 'validation'
 #args.quantize = True
 
@@ -132,7 +140,7 @@ args.pivot_task_idx = 2
 
 ################################
 for key in vars(cmds):
-    if key == 'gpus':
+    if (key == 'gpus')| (key == 'image_folders') | (key == 'multi_task_type'):
         pass # already taken care above, since this has to be done before importing pytorch
     elif hasattr(args, key):
         value = getattr(cmds, key)
index ab54b1cd48d4c662760b12e96b81bdab6eb7748c..dda5c0f271f7057ab8f1847ee7f9dc085abeaf67 100755 (executable)
@@ -114,7 +114,7 @@ args.transform_rotation = 5                                 #rotation degrees
 
 #args.parallel_model=False
 #args.print_model = True
-#args.generate_onnx = False
+#args.save_onnx = False
 #args.run_soon = False
 #args.evaluate_start = False
 args.print_freq = 10