diff --git a/.gitignore b/.gitignore
index f615de4..d0991ff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -132,9 +132,11 @@ dmypy.json
# Pyre type checker
.pyre/
-# testdata
+# test data
tutorials/train/change_detection/DataSet/
tutorials/train/classification/DataSet/
optic_disc_seg.tar
optic_disc_seg/
output/
+
+/log
\ No newline at end of file
diff --git a/paddlers/tasks/__init__.py b/paddlers/tasks/__init__.py
index d7b20d9..5c1f428 100644
--- a/paddlers/tasks/__init__.py
+++ b/paddlers/tasks/__init__.py
@@ -12,9 +12,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import paddlers.tasks.object_detector as det
-import paddlers.tasks.segmenter as seg
-import paddlers.tasks.change_detector as cd
-import paddlers.tasks.classifier as clas
-import paddlers.tasks.image_restorer as res
+import paddlers.tasks.object_detector as detector
+import paddlers.tasks.segmenter as segmenter
+import paddlers.tasks.change_detector as change_detector
+import paddlers.tasks.classifier as classifier
+import paddlers.tasks.image_restorer as restorer
from .load_model import load_model
+
+# Shorter aliases
+det = detector
+seg = segmenter
+cd = change_detector
+clas = classifier
+res = restorer
diff --git a/paddlers/tasks/base.py b/paddlers/tasks/base.py
index 0e2e901..c8642c7 100644
--- a/paddlers/tasks/base.py
+++ b/paddlers/tasks/base.py
@@ -194,10 +194,15 @@ class BaseModel(metaclass=ModelMeta):
info['Transforms'] = list()
for op in self.test_transforms.transforms:
name = op.__class__.__name__
- if name.startswith('Arrange'):
- continue
attr = op.__dict__
info['Transforms'].append({name: attr})
+ arrange = self.test_transforms.arrange
+ if arrange is not None:
+ info['Transforms'].append({
+ arrange.__class__.__name__: {
+ 'mode': 'test'
+ }
+ })
info['completed_epochs'] = self.completed_epochs
return info
diff --git a/paddlers/transforms/batch_operators.py b/paddlers/transforms/batch_operators.py
index c2496c5..2c723d1 100644
--- a/paddlers/transforms/batch_operators.py
+++ b/paddlers/transforms/batch_operators.py
@@ -62,7 +62,10 @@ class BatchCompose(Transform):
for i in range(len(samples)):
tmp_data.append(samples[i][k])
if not 'gt_' in k and not 'is_crowd' in k and not 'difficult' in k:
- tmp_data = np.stack(tmp_data, axis=0)
+ # This if assumes that all elements in tmp_data has the same type.
+ if len(tmp_data) == 0 or not isinstance(tmp_data[0],
+ (str, bytes)):
+ tmp_data = np.stack(tmp_data, axis=0)
batch_data[k] = tmp_data
return batch_data
diff --git a/test_tipc/.gitignore b/test_tipc/.gitignore
new file mode 100644
index 0000000..8edf5d4
--- /dev/null
+++ b/test_tipc/.gitignore
@@ -0,0 +1,3 @@
+/scripts/
+/output/
+/data/
\ No newline at end of file
diff --git a/test_tipc/README.md b/test_tipc/README.md
new file mode 100644
index 0000000..76affc3
--- /dev/null
+++ b/test_tipc/README.md
@@ -0,0 +1,62 @@
+# 飞桨训推一体全流程(TIPC)
+
+## 1. 简介
+
+飞桨除了基本的模型训练和预测,还提供了支持多端多平台的高性能推理部署工具。本文档提供了飞桨训推一体全流程(Training and Inference Pipeline Criterion(TIPC))信息和测试工具,方便用户查阅每种模型的训练推理部署打通情况,并可以进行一键测试。
+
+
+
+
+
+## 2. 汇总信息
+
+打通情况汇总如下,已填写的部分表示可以使用本工具进行一键测试,未填写的表示正在支持中。
+
+**字段说明:**
+- 基础训练预测:指Linux GPU/CPU环境下的模型训练、Paddle Inference Python预测。
+- 更多训练方式:包括多机多卡、混合精度训练。
+- 更多部署方式:包括C++预测、Serving服务化部署、ARM端侧部署等多种部署方式,具体列表见[3.3节](#3.3)
+- Slim训练部署:包括PACT在线量化、离线量化。
+- 更多训练环境:包括Windows GPU/CPU、Linux NPU、Linux DCU等多种环境。
+
+
+| 任务类别 | 模型名称 | 基础
训练预测 | 更多
训练方式 | 更多
部署方式 | Slim
训练部署 | 更多
训练环境 |
+| :--- | :--- | :----: | :--------: | :----: | :----: | :----: | :----: |
+| 变化检测 | BIT | 支持 | - | - | - | - |
+| 场景分类 | HRNet | 支持 | - | - | - | - |
+| 目标检测 | PP-YOLO | 支持 | - | - | - | - |
+| 图像分割 | UNet | 支持 | - | - | - | - |
+
+
+## 3. 测试工具简介
+
+### 3.1 目录介绍
+
+```
+test_tipc
+ |--configs # 配置目录
+ | |--task_name # 任务名称
+ | |--model_name # 模型名称
+ | |--train_infer_python.txt # 基础训练推理测试配置文件
+ |--docs # 文档目录
+ | |--test_train_inference_python.md # 基础训练推理测试说明文档
+ |----README.md # TIPC说明文档
+ |----prepare.sh # TIPC基础训练推理测试数据准备脚本
+ |----test_train_inference_python.sh # TIPC基础训练推理测试解析脚本
+ |----common_func.sh # TIPC基础训练推理测试常用函数
+```
+
+### 3.2 测试流程概述
+
+使用本工具,可以测试不同功能的支持情况。测试过程包含:
+
+1. 准备数据与环境
+2. 运行测试脚本,观察不同配置是否运行成功。
+
+
+### 3.3 开始测试
+
+请参考相应文档,完成指定功能的测试。
+
+- 基础训练预测测试:
+ - [Linux GPU/CPU 基础训练推理测试](docs/test_train_inference_python.md)
diff --git a/test_tipc/common_func.sh b/test_tipc/common_func.sh
new file mode 100644
index 0000000..506ac82
--- /dev/null
+++ b/test_tipc/common_func.sh
@@ -0,0 +1,131 @@
+#!/bin/bash
+
+function func_parser_key() {
+ strs=$1
+ IFS=":"
+ array=(${strs})
+ tmp=${array[0]}
+ echo ${tmp}
+}
+
+function func_parser_value() {
+ strs=$1
+ IFS=":"
+ array=(${strs})
+ tmp=${array[1]}
+ echo ${tmp}
+}
+
+function func_parser_value_lite() {
+ strs=$1
+ IFS=$2
+ array=(${strs})
+ tmp=${array[1]}
+ echo ${tmp}
+}
+
+function func_set_params() {
+ key=$1
+ value=$2
+ if [ ${key}x = "null"x ];then
+ echo " "
+ elif [[ ${value} = "null" ]] || [[ ${value} = " " ]] || [ ${#value} -le 0 ];then
+ echo " "
+ else
+ echo "${key}=${value}"
+ fi
+}
+
+function func_parser_params() {
+ strs=$1
+ IFS=":"
+ array=(${strs})
+ key=${array[0]}
+ tmp=${array[1]}
+ IFS="|"
+ res=""
+ for _params in ${tmp[*]}; do
+ IFS="="
+ array=(${_params})
+ mode=${array[0]}
+ value=${array[1]}
+ if [[ ${mode} = ${MODE} ]]; then
+ IFS="|"
+ #echo $(func_set_params "${mode}" "${value}")
+ echo $value
+ break
+ fi
+ IFS="|"
+ done
+ echo ${res}
+}
+
+function status_check() {
+ local last_status=$1 # the exit code
+ local run_command=$2
+ local run_log=$3
+ local model_name=$4
+
+ if [ $last_status -eq 0 ]; then
+ echo -e "\033[33m Run successfully with command - ${model_name} - ${run_command}! \033[0m" | tee -a ${run_log}
+ else
+ echo -e "\033[33m Run failed with command - ${model_name} - ${run_command}! \033[0m" | tee -a ${run_log}
+ fi
+}
+
+function download_and_unzip_dataset() {
+ local ds_dir="$1"
+ local ds_name="$2"
+ local url="$3"
+ local clear="${4-True}"
+
+ local ds_path="${ds_dir}/${ds_name}"
+ local zip_name="${url##*/}"
+
+ if [ ${clear} = 'True' ]; then
+ rm -rf "${ds_path}"
+ fi
+
+ wget -nc -P "${ds_dir}" "${url}" --no-check-certificate
+ cd "${ds_dir}" && unzip "${zip_name}" && cd - \
+ && echo "Successfully downloaded ${zip_name} from ${url}. File saved in ${ds_path}. "
+}
+
+function parse_extra_args() {
+ local lines=("$@")
+ local last_idx=$((${#lines[@]}-1))
+ local IFS=';'
+ extra_args=(${lines[last_idx]})
+}
+
+function add_suffix() {
+ local ori_path="$1"
+ local suffix=$2
+ local ext="${ori_path##*.}"
+ echo "${ori_path%.*}${suffix}.${ext}"
+}
+
+function parse_first_value() {
+ local key_values=$1
+ local IFS=":"
+ local arr=(${key_values})
+ echo ${arr[1]}
+}
+
+function parse_second_value() {
+ local key_values=$1
+ local IFS=":"
+ local arr=(${key_values})
+ echo ${arr[2]}
+}
+
+function run_command() {
+ local cmd="$1"
+ local log_path="$2"
+ if [ -n "${log_path}" ]; then
+ eval ${cmd} | tee "${log_path}"
+ test ${PIPESTATUS[0]} -eq 0
+ else
+ eval ${cmd}
+ fi
+}
diff --git a/test_tipc/config_utils.py b/test_tipc/config_utils.py
new file mode 100644
index 0000000..fa137f8
--- /dev/null
+++ b/test_tipc/config_utils.py
@@ -0,0 +1,252 @@
+#!/usr/bin/env python
+
+import argparse
+import os.path as osp
+from collections.abc import Mapping
+
+import yaml
+
+
+def _chain_maps(*maps):
+ chained = dict()
+ keys = set().union(*maps)
+ for key in keys:
+ vals = [m[key] for m in maps if key in m]
+ if isinstance(vals[0], Mapping):
+ chained[key] = _chain_maps(*vals)
+ else:
+ chained[key] = vals[0]
+ return chained
+
+
+def read_config(config_path):
+ with open(config_path, 'r', encoding='utf-8') as f:
+ cfg = yaml.safe_load(f)
+ return cfg or {}
+
+
+def parse_configs(cfg_path, inherit=True):
+ if inherit:
+ cfgs = []
+ cfgs.append(read_config(cfg_path))
+ while cfgs[-1].get('_base_'):
+ base_path = cfgs[-1].pop('_base_')
+ curr_dir = osp.dirname(cfg_path)
+ cfgs.append(
+ read_config(osp.normpath(osp.join(curr_dir, base_path))))
+ return _chain_maps(*cfgs)
+ else:
+ return read_config(cfg_path)
+
+
+def _cfg2args(cfg, parser, prefix=''):
+ node_keys = set()
+ for k, v in cfg.items():
+ opt = prefix + k
+ if isinstance(v, list):
+ if len(v) == 0:
+ parser.add_argument(
+ '--' + opt, type=object, nargs='*', default=v)
+ else:
+ # Only apply to homogeneous lists
+ if isinstance(v[0], CfgNode):
+ node_keys.add(opt)
+ parser.add_argument(
+ '--' + opt, type=type(v[0]), nargs='*', default=v)
+ elif isinstance(v, dict):
+ # Recursively parse a dict
+ _, new_node_keys = _cfg2args(v, parser, opt + '.')
+ node_keys.update(new_node_keys)
+ elif isinstance(v, CfgNode):
+ node_keys.add(opt)
+ _, new_node_keys = _cfg2args(v.to_dict(), parser, opt + '.')
+ node_keys.update(new_node_keys)
+ elif isinstance(v, bool):
+ parser.add_argument('--' + opt, action='store_true', default=v)
+ else:
+ parser.add_argument('--' + opt, type=type(v), default=v)
+ return parser, node_keys
+
+
+def _args2cfg(cfg, args, node_keys):
+ args = vars(args)
+ for k, v in args.items():
+ pos = k.find('.')
+ if pos != -1:
+ # Iteratively parse a dict
+ dict_ = cfg
+ while pos != -1:
+ dict_.setdefault(k[:pos], {})
+ dict_ = dict_[k[:pos]]
+ k = k[pos + 1:]
+ pos = k.find('.')
+ dict_[k] = v
+ else:
+ cfg[k] = v
+
+ for k in node_keys:
+ pos = k.find('.')
+ if pos != -1:
+ # Iteratively parse a dict
+ dict_ = cfg
+ while pos != -1:
+ dict_.setdefault(k[:pos], {})
+ dict_ = dict_[k[:pos]]
+ k = k[pos + 1:]
+ pos = k.find('.')
+ v = dict_[k]
+ dict_[k] = [CfgNode(v_) for v_ in v] if isinstance(
+ v, list) else CfgNode(v)
+ else:
+ v = cfg[k]
+ cfg[k] = [CfgNode(v_) for v_ in v] if isinstance(
+ v, list) else CfgNode(v)
+
+ return cfg
+
+
+def parse_args(*args, **kwargs):
+ cfg_parser = argparse.ArgumentParser(add_help=False)
+ cfg_parser.add_argument('--config', type=str, default='')
+ cfg_parser.add_argument('--inherit_off', action='store_true')
+ cfg_args = cfg_parser.parse_known_args()[0]
+ cfg_path = cfg_args.config
+ inherit_on = not cfg_args.inherit_off
+
+ # Main parser
+ parser = argparse.ArgumentParser(
+ conflict_handler='resolve', parents=[cfg_parser])
+ # Global settings
+ parser.add_argument('cmd', choices=['train', 'eval'])
+ parser.add_argument('task', choices=['cd', 'clas', 'det', 'seg'])
+
+ # Data
+ parser.add_argument('--datasets', type=dict, default={})
+ parser.add_argument('--transforms', type=dict, default={})
+ parser.add_argument('--download_on', action='store_true')
+ parser.add_argument('--download_url', type=str, default='')
+ parser.add_argument('--download_path', type=str, default='./')
+
+ # Optimizer
+ parser.add_argument('--optimizer', type=dict, default={})
+
+ # Training related
+ parser.add_argument('--num_epochs', type=int, default=100)
+ parser.add_argument('--train_batch_size', type=int, default=8)
+ parser.add_argument('--save_interval_epochs', type=int, default=1)
+ parser.add_argument('--log_interval_steps', type=int, default=1)
+ parser.add_argument('--save_dir', default='../exp/')
+ parser.add_argument('--learning_rate', type=float, default=0.01)
+ parser.add_argument('--early_stop', action='store_true')
+ parser.add_argument('--early_stop_patience', type=int, default=5)
+ parser.add_argument('--use_vdl', action='store_true')
+ parser.add_argument('--resume_checkpoint', type=str)
+ parser.add_argument('--train', type=dict, default={})
+
+ # Loss
+ parser.add_argument('--losses', type=dict, nargs='+', default={})
+
+ # Model
+ parser.add_argument('--model', type=dict, default={})
+
+ if osp.exists(cfg_path):
+ cfg = parse_configs(cfg_path, inherit_on)
+ parser, node_keys = _cfg2args(cfg, parser, '')
+ args = parser.parse_args(*args, **kwargs)
+ return _args2cfg(dict(), args, node_keys)
+ elif cfg_path != '':
+ raise FileNotFoundError
+ else:
+ args = parser.parse_args()
+ return _args2cfg(dict(), args, set())
+
+
+class _CfgNodeMeta(yaml.YAMLObjectMetaclass):
+ def __call__(cls, obj):
+ if isinstance(obj, CfgNode):
+ return obj
+ return super(_CfgNodeMeta, cls).__call__(obj)
+
+
+class CfgNode(yaml.YAMLObject, metaclass=_CfgNodeMeta):
+ yaml_tag = u'!Node'
+ yaml_loader = yaml.SafeLoader
+ # By default use a lexical scope
+ ctx = globals()
+
+ def __init__(self, dict_):
+ super().__init__()
+ self.type = dict_['type']
+ self.args = dict_.get('args', [])
+ self.module = self._get_module(dict_.get('module', ''))
+
+ @classmethod
+ def set_context(cls, ctx):
+ # TODO: Implement dynamic scope with inspect.stack()
+ old_ctx = cls.ctx
+ cls.ctx = ctx
+ return old_ctx
+
+ def build_object(self, mod=None):
+ if mod is None:
+ mod = self.module
+ cls = getattr(mod, self.type)
+ if isinstance(self.args, list):
+ args = build_objects(self.args)
+ obj = cls(*args)
+ elif isinstance(self.args, dict):
+ args = build_objects(self.args)
+ obj = cls(**args)
+ else:
+ raise NotImplementedError
+ return obj
+
+ def _get_module(self, s):
+ mod = None
+ while s:
+ idx = s.find('.')
+ if idx == -1:
+ next_ = s
+ s = ''
+ else:
+ next_ = s[:idx]
+ s = s[idx + 1:]
+ if mod is None:
+ mod = self.ctx[next_]
+ else:
+ mod = getattr(mod, next_)
+ return mod
+
+ @staticmethod
+ def build_objects(cfg, mod=None):
+ if isinstance(cfg, list):
+ return [CfgNode.build_objects(c, mod=mod) for c in cfg]
+ elif isinstance(cfg, CfgNode):
+ return cfg.build_object(mod=mod)
+ elif isinstance(cfg, dict):
+ return {
+ k: CfgNode.build_objects(
+ v, mod=mod)
+ for k, v in cfg.items()
+ }
+ else:
+ return cfg
+
+ def __repr__(self):
+ return f"(type={self.type}, args={self.args}, module={self.module or ' '})"
+
+ @classmethod
+ def from_yaml(cls, loader, node):
+ map_ = loader.construct_mapping(node)
+ return cls(map_)
+
+ def items(self):
+ yield from [('type', self.type), ('args', self.args), ('module',
+ self.module)]
+
+ def to_dict(self):
+ return dict(self.items())
+
+
+def build_objects(cfg, mod=None):
+ return CfgNode.build_objects(cfg, mod=mod)
diff --git a/test_tipc/configs/cd/_base_/airchange.yaml b/test_tipc/configs/cd/_base_/airchange.yaml
new file mode 100644
index 0000000..38ec406
--- /dev/null
+++ b/test_tipc/configs/cd/_base_/airchange.yaml
@@ -0,0 +1,70 @@
+# Basic configurations of AirChange dataset
+
+datasets:
+ train: !Node
+ type: CDDataset
+ args:
+ data_dir: ./test_tipc/data/airchange/
+ file_list: ./test_tipc/data/airchange/train.txt
+ label_list: null
+ num_workers: 0
+ shuffle: True
+ with_seg_labels: False
+ binarize_labels: True
+ eval: !Node
+ type: CDDataset
+ args:
+ data_dir: ./test_tipc/data/airchange/
+ file_list: ./test_tipc/data/airchange/eval.txt
+ label_list: null
+ num_workers: 0
+ shuffle: False
+ with_seg_labels: False
+ binarize_labels: True
+transforms:
+ train:
+ - !Node
+ type: DecodeImg
+ - !Node
+ type: RandomCrop
+ args:
+ crop_size: 256
+ aspect_ratio: [0.5, 2.0]
+ scaling: [0.2, 1.0]
+ - !Node
+ type: RandomHorizontalFlip
+ args:
+ prob: 0.5
+ - !Node
+ type: Normalize
+ args:
+ mean: [0.5, 0.5, 0.5]
+ std: [0.5, 0.5, 0.5]
+ - !Node
+ type: ArrangeChangeDetector
+ args: ['train']
+ eval:
+ - !Node
+ type: DecodeImg
+ - !Node
+ type: Normalize
+ args:
+ mean: [0.5, 0.5, 0.5]
+ std: [0.5, 0.5, 0.5]
+ - !Node
+ type: ArrangeChangeDetector
+ args: ['eval']
+download_on: False
+download_url: https://paddlers.bj.bcebos.com/datasets/airchange.zip
+download_path: ./test_tipc/data/
+
+num_epochs: 5
+train_batch_size: 4
+save_interval_epochs: 3
+log_interval_steps: 50
+save_dir: ./test_tipc/output/cd/
+learning_rate: 0.01
+early_stop: False
+early_stop_patience: 5
+use_vdl: False
+resume_checkpoint: ''
\ No newline at end of file
diff --git a/test_tipc/configs/cd/bit/bit.yaml b/test_tipc/configs/cd/bit/bit.yaml
new file mode 100644
index 0000000..735a318
--- /dev/null
+++ b/test_tipc/configs/cd/bit/bit.yaml
@@ -0,0 +1,8 @@
+# Basic configurations of BIT
+
+_base_: ../_base_/airchange.yaml
+
+save_dir: ./test_tipc/output/cd/bit/
+
+model: !Node
+ type: BIT
\ No newline at end of file
diff --git a/test_tipc/configs/cd/bit/train_infer_python.txt b/test_tipc/configs/cd/bit/train_infer_python.txt
new file mode 100644
index 0000000..69ddeae
--- /dev/null
+++ b/test_tipc/configs/cd/bit/train_infer_python.txt
@@ -0,0 +1,53 @@
+===========================train_params===========================
+model_name:cd:bit
+python:python
+gpu_list:0|0,1
+use_gpu:null|null
+--precision:null
+--num_epochs:lite_train_lite_infer=5|lite_train_whole_infer=5|whole_train_whole_infer=10
+--save_dir:adaptive
+--train_batch_size:lite_train_lite_infer=4|lite_train_whole_infer=4|whole_train_whole_infer=4
+--model_path:null
+train_model_name:best_model
+train_infer_file_list:./test_tipc/data/airchange/:./test_tipc/data/airchange/eval.txt
+null:null
+##
+trainer:norm
+norm_train:test_tipc/run_task.py train cd --config ./test_tipc/configs/cd/bit/bit.yaml
+pact_train:null
+fpgm_train:null
+distill_train:null
+null:null
+null:null
+##
+===========================eval_params===========================
+eval:null
+null:null
+##
+===========================export_params===========================
+--save_dir:adaptive
+--model_dir:adaptive
+--fixed_input_shape:[-1,3,256,256]
+norm_export:deploy/export/export_model.py
+quant_export:null
+fpgm_export:null
+distill_export:null
+export1:null
+export2:null
+===========================infer_params===========================
+infer_model:null
+infer_export:null
+infer_quant:False
+inference:test_tipc/infer.py
+--device:cpu|gpu
+--enable_mkldnn:True
+--cpu_threads:6
+--batch_size:1
+--use_trt:False
+--precision:fp32
+--model_dir:null
+--file_list:null:null
+--save_log_path:null
+--benchmark:True
+--model_name:bit
+null:null
\ No newline at end of file
diff --git a/test_tipc/configs/clas/_base_/ucmerced.yaml b/test_tipc/configs/clas/_base_/ucmerced.yaml
new file mode 100644
index 0000000..424f45e
--- /dev/null
+++ b/test_tipc/configs/clas/_base_/ucmerced.yaml
@@ -0,0 +1,72 @@
+# Basic configurations of UCMerced dataset
+
+datasets:
+ train: !Node
+ type: ClasDataset
+ args:
+ data_dir: ./test_tipc/data/ucmerced/
+ file_list: ./test_tipc/data/ucmerced/train.txt
+ label_list: ./test_tipc/data/ucmerced/labels.txt
+ num_workers: 0
+ shuffle: True
+ eval: !Node
+ type: ClasDataset
+ args:
+ data_dir: ./test_tipc/data/ucmerced/
+ file_list: ./test_tipc/data/ucmerced/val.txt
+ label_list: ./test_tipc/data/ucmerced/labels.txt
+ num_workers: 0
+ shuffle: False
+transforms:
+ train:
+ - !Node
+ type: DecodeImg
+ - !Node
+ type: Resize
+ args:
+ target_size: 256
+ - !Node
+ type: RandomHorizontalFlip
+ args:
+ prob: 0.5
+ - !Node
+ type: RandomVerticalFlip
+ args:
+ prob: 0.5
+ - !Node
+ type: Normalize
+ args:
+ mean: [0.5, 0.5, 0.5]
+ std: [0.5, 0.5, 0.5]
+ - !Node
+ type: ArrangeClassifier
+ args: ['train']
+ eval:
+ - !Node
+ type: DecodeImg
+ - !Node
+ type: Resize
+ args:
+ target_size: 256
+ - !Node
+ type: Normalize
+ args:
+ mean: [0.5, 0.5, 0.5]
+ std: [0.5, 0.5, 0.5]
+ - !Node
+ type: ArrangeClassifier
+ args: ['eval']
+download_on: False
+download_url: https://paddlers.bj.bcebos.com/datasets/ucmerced.zip
+download_path: ./test_tipc/data/
+
+num_epochs: 2
+train_batch_size: 16
+save_interval_epochs: 5
+log_interval_steps: 50
+save_dir: e./test_tipc/output/clas/
+learning_rate: 0.01
+early_stop: False
+early_stop_patience: 5
+use_vdl: False
+resume_checkpoint: ''
\ No newline at end of file
diff --git a/test_tipc/configs/clas/hrnet/hrnet.yaml b/test_tipc/configs/clas/hrnet/hrnet.yaml
new file mode 100644
index 0000000..2f0a000
--- /dev/null
+++ b/test_tipc/configs/clas/hrnet/hrnet.yaml
@@ -0,0 +1,10 @@
+# Basic configurations of HRNet
+
+_base_: ../_base_/ucmerced.yaml
+
+save_dir: ./test_tipc/output/clas/hrnet/
+
+model: !Node
+ type: HRNet_W18_C
+ args:
+ num_classes: 21
\ No newline at end of file
diff --git a/test_tipc/configs/clas/hrnet/train_infer_python.txt b/test_tipc/configs/clas/hrnet/train_infer_python.txt
new file mode 100644
index 0000000..23f3820
--- /dev/null
+++ b/test_tipc/configs/clas/hrnet/train_infer_python.txt
@@ -0,0 +1,53 @@
+===========================train_params===========================
+model_name:clas:hrnet
+python:python
+gpu_list:0|0,1
+use_gpu:null|null
+--precision:null
+--num_epochs:lite_train_lite_infer=3|lite_train_whole_infer=3|whole_train_whole_infer=10
+--save_dir:adaptive
+--train_batch_size:lite_train_lite_infer=16|lite_train_whole_infer=16|whole_train_whole_infer=16
+--model_path:null
+train_model_name:best_model
+train_infer_file_list:./test_tipc/data/ucmerced/:./test_tipc/data/ucmerced/val.txt
+null:null
+##
+trainer:norm
+norm_train:test_tipc/run_task.py train clas --config ./test_tipc/configs/clas/hrnet/hrnet.yaml
+pact_train:null
+fpgm_train:null
+distill_train:null
+null:null
+null:null
+##
+===========================eval_params===========================
+eval:null
+null:null
+##
+===========================export_params===========================
+--save_dir:adaptive
+--model_dir:adaptive
+--fixed_input_shape:[-1,3,256,256]
+norm_export:deploy/export/export_model.py
+quant_export:null
+fpgm_export:null
+distill_export:null
+export1:null
+export2:null
+===========================infer_params===========================
+infer_model:null
+infer_export:null
+infer_quant:False
+inference:test_tipc/infer.py
+--device:cpu|gpu
+--enable_mkldnn:True
+--cpu_threads:6
+--batch_size:1
+--use_trt:False
+--precision:fp32
+--model_dir:null
+--file_list:null:null
+--save_log_path:null
+--benchmark:True
+--model_name:hrnet
+null:null
\ No newline at end of file
diff --git a/test_tipc/configs/det/_base_/sarship.yaml b/test_tipc/configs/det/_base_/sarship.yaml
new file mode 100644
index 0000000..c7c6afe
--- /dev/null
+++ b/test_tipc/configs/det/_base_/sarship.yaml
@@ -0,0 +1,74 @@
+# Basic configurations of SARShip dataset
+
+datasets:
+ train: !Node
+ type: VOCDetDataset
+ args:
+ data_dir: ./test_tipc/data/sarship/
+ file_list: ./test_tipc/data/sarship/train.txt
+ label_list: ./test_tipc/data/sarship/labels.txt
+ shuffle: True
+ eval: !Node
+ type: VOCDetDataset
+ args:
+ data_dir: ./test_tipc/data/sarship/
+ file_list: ./test_tipc/data/sarship/eval.txt
+ label_list: ./test_tipc/data/sarship/labels.txt
+ shuffle: False
+transforms:
+ train:
+ - !Node
+ type: DecodeImg
+ - !Node
+ type: RandomDistort
+ - !Node
+ type: RandomExpand
+ - !Node
+ type: RandomCrop
+ - !Node
+ type: RandomHorizontalFlip
+ - !Node
+ type: BatchRandomResize
+ args:
+ target_sizes: [320, 352, 384, 416, 448, 480, 512, 544, 576, 608]
+ interp: RANDOM
+ - !Node
+ type: Normalize
+ args:
+ mean: [0.485, 0.456, 0.406]
+ std: [0.229, 0.224, 0.225]
+ - !Node
+ type: ArrangeDetector
+ args: ['train']
+ eval:
+ - !Node
+ type: DecodeImg
+ - !Node
+ type: Resize
+ args:
+ target_size: 608
+ interp: CUBIC
+ - !Node
+ type: Normalize
+ args:
+ mean: [0.485, 0.456, 0.406]
+ std: [0.229, 0.224, 0.225]
+ - !Node
+ type: ArrangeDetector
+ args: ['eval']
+download_on: False
+download_url: https://paddlers.bj.bcebos.com/datasets/sarship.zip
+download_path: ./test_tipc/data/
+
+num_epochs: 10
+train_batch_size: 4
+save_interval_epochs: 5
+log_interval_steps: 4
+save_dir: ./test_tipc/output/det/
+learning_rate: 0.0005
+use_vdl: False
+resume_checkpoint: ''
+train:
+ pretrain_weights: COCO
+ warmup_steps: 0
+ warmup_start_lr: 0.0
\ No newline at end of file
diff --git a/test_tipc/configs/det/ppyolo/ppyolo.yaml b/test_tipc/configs/det/ppyolo/ppyolo.yaml
new file mode 100644
index 0000000..6d9ef3d
--- /dev/null
+++ b/test_tipc/configs/det/ppyolo/ppyolo.yaml
@@ -0,0 +1,10 @@
+# Basic configurations of PP-YOLO
+
+_base_: ../_base_/sarship.yaml
+
+save_dir: ./test_tipc/output/det/ppyolo/
+
+model: !Node
+ type: PPYOLO
+ args:
+ num_classes: 1
\ No newline at end of file
diff --git a/test_tipc/configs/det/ppyolo/train_infer_python.txt b/test_tipc/configs/det/ppyolo/train_infer_python.txt
new file mode 100644
index 0000000..43a47fa
--- /dev/null
+++ b/test_tipc/configs/det/ppyolo/train_infer_python.txt
@@ -0,0 +1,53 @@
+===========================train_params===========================
+model_name:det:ppyolo
+python:python
+gpu_list:0|0,1
+use_gpu:null|null
+--precision:null
+--num_epochs:lite_train_lite_infer=3|lite_train_whole_infer=3|whole_train_whole_infer=10
+--save_dir:adaptive
+--train_batch_size:lite_train_lite_infer=4|lite_train_whole_infer=4|whole_train_whole_infer=4
+--model_path:null
+train_model_name:best_model
+train_infer_file_list:./test_tipc/data/sarship/:./test_tipc/data/sarship/eval.txt
+null:null
+##
+trainer:norm
+norm_train:test_tipc/run_task.py train det --config ./test_tipc/configs/det/ppyolo/ppyolo.yaml
+pact_train:null
+fpgm_train:null
+distill_train:null
+null:null
+null:null
+##
+===========================eval_params===========================
+eval:null
+null:null
+##
+===========================export_params===========================
+--save_dir:adaptive
+--model_dir:adaptive
+--fixed_input_shape:[-1,3,608,608]
+norm_export:deploy/export/export_model.py
+quant_export:null
+fpgm_export:null
+distill_export:null
+export1:null
+export2:null
+===========================infer_params===========================
+infer_model:null
+infer_export:null
+infer_quant:False
+inference:test_tipc/infer.py
+--device:cpu|gpu
+--enable_mkldnn:True
+--cpu_threads:6
+--batch_size:1
+--use_trt:False
+--precision:fp32
+--model_dir:null
+--file_list:null:null
+--save_log_path:null
+--benchmark:True
+--model_name:ppyolo
+null:null
\ No newline at end of file
diff --git a/test_tipc/configs/seg/_base_/rsseg.yaml b/test_tipc/configs/seg/_base_/rsseg.yaml
new file mode 100644
index 0000000..2f1d588
--- /dev/null
+++ b/test_tipc/configs/seg/_base_/rsseg.yaml
@@ -0,0 +1,68 @@
+# Basic configurations of RSSeg dataset
+
+datasets:
+ train: !Node
+ type: SegDataset
+ args:
+ data_dir: ./test_tipc/data/rsseg/
+ file_list: ./test_tipc/data/rsseg/train.txt
+ label_list: ./test_tipc/data/rsseg/labels.txt
+ num_workers: 0
+ shuffle: True
+ eval: !Node
+ type: SegDataset
+ args:
+ data_dir: ./test_tipc/data/rsseg/
+ file_list: ./test_tipc/data/rsseg/val.txt
+ label_list: ./test_tipc/data/rsseg/labels.txt
+ num_workers: 0
+ shuffle: False
+transforms:
+ train:
+ - !Node
+ type: DecodeImg
+ - !Node
+ type: Resize
+ args:
+ target_size: 512
+ - !Node
+ type: RandomHorizontalFlip
+ args:
+ prob: 0.5
+ - !Node
+ type: Normalize
+ args:
+ mean: [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
+ std: [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
+ - !Node
+ type: ArrangeSegmenter
+ args: ['train']
+ eval:
+ - !Node
+ type: DecodeImg
+ - !Node
+ type: Resize
+ args:
+ target_size: 512
+ - !Node
+ type: Normalize
+ args:
+ mean: [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
+ std: [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
+ - !Node
+ type: ArrangeSegmenter
+ args: ['eval']
+download_on: False
+download_url: https://paddlers.bj.bcebos.com/datasets/rsseg.zip
+download_path: ./test_tipc/data/
+
+num_epochs: 10
+train_batch_size: 4
+save_interval_epochs: 5
+log_interval_steps: 4
+save_dir: ./test_tipc/output/seg/
+learning_rate: 0.001
+early_stop: False
+early_stop_patience: 5
+use_vdl: False
+resume_checkpoint: ''
\ No newline at end of file
diff --git a/test_tipc/configs/seg/unet/train_infer_python.txt b/test_tipc/configs/seg/unet/train_infer_python.txt
new file mode 100644
index 0000000..1a548e1
--- /dev/null
+++ b/test_tipc/configs/seg/unet/train_infer_python.txt
@@ -0,0 +1,53 @@
+===========================train_params===========================
+model_name:seg:unet
+python:python
+gpu_list:0|0,1
+use_gpu:null|null
+--precision:null
+--num_epochs:lite_train_lite_infer=3|lite_train_whole_infer=3|whole_train_whole_infer=10
+--save_dir:adaptive
+--train_batch_size:lite_train_lite_infer=4|lite_train_whole_infer=4|whole_train_whole_infer=4
+--model_path:null
+train_model_name:best_model
+train_infer_file_list:./test_tipc/data/rsseg/:./test_tipc/data/rsseg/val.txt
+null:null
+##
+trainer:norm
+norm_train:test_tipc/run_task.py train seg --config ./test_tipc/configs/seg/unet/unet.yaml
+pact_train:null
+fpgm_train:null
+distill_train:null
+null:null
+null:null
+##
+===========================eval_params===========================
+eval:null
+null:null
+##
+===========================export_params===========================
+--save_dir:adaptive
+--model_dir:adaptive
+--fixed_input_shape:[-1,10,512,512]
+norm_export:deploy/export/export_model.py
+quant_export:null
+fpgm_export:null
+distill_export:null
+export1:null
+export2:null
+===========================infer_params===========================
+infer_model:null
+infer_export:null
+infer_quant:False
+inference:test_tipc/infer.py
+--device:cpu|gpu
+--enable_mkldnn:True
+--cpu_threads:6
+--batch_size:1
+--use_trt:False
+--precision:fp32
+--model_dir:null
+--file_list:null:null
+--save_log_path:null
+--benchmark:True
+--model_name:unet
+null:null
\ No newline at end of file
diff --git a/test_tipc/configs/seg/unet/unet.yaml b/test_tipc/configs/seg/unet/unet.yaml
new file mode 100644
index 0000000..8d2af9c
--- /dev/null
+++ b/test_tipc/configs/seg/unet/unet.yaml
@@ -0,0 +1,11 @@
+# Basic configurations of UNet
+
+_base_: ../_base_/rsseg.yaml
+
+save_dir: ./test_tipc/output/seg/unet/
+
+model: !Node
+ type: UNet
+ args:
+ input_channel: 10
+ num_classes: 5
\ No newline at end of file
diff --git a/test_tipc/docs/overview.png b/test_tipc/docs/overview.png
new file mode 100644
index 0000000..319ac81
Binary files /dev/null and b/test_tipc/docs/overview.png differ
diff --git a/test_tipc/docs/test_train_inference_python.md b/test_tipc/docs/test_train_inference_python.md
new file mode 100644
index 0000000..4d98215
--- /dev/null
+++ b/test_tipc/docs/test_train_inference_python.md
@@ -0,0 +1,89 @@
+# Linux GPU/CPU 基础训练推理测试
+
+Linux GPU/CPU 基础训练推理测试的主程序为`test_train_inference_python.sh`,可以测试基于Python的模型训练、评估、推理等基本功能。
+
+## 1. 测试结论汇总
+
+- 训练相关:
+
+| 任务类别 | 模型名称 | 单机单卡 | 单机多卡 |
+| :----: | :----: | :----: | :----: |
+| 变化检测 | BIT | 正常训练 | 正常训练 |
+| 场景分类 | HRNet | 正常训练 | 正常训练 |
+| 目标检测 | PP-YOLO | 正常训练 | 正常训练 |
+| 图像分割 | UNet | 正常训练 | 正常训练 |
+
+- 推理相关:
+
+| 任务类别 | 模型名称 | device_CPU | device_GPU | batchsize |
+| :----: | :----: | :----: | :----: | :----: |
+| 变化检测 | BIT | 支持 | 支持 | 1 |
+| 场景分类 | HRNet | 支持 | 支持 | 1 |
+| 目标检测 | YOLO | 支持 | 支持 | 1 |
+| 图像分割 | UNet | 支持 | 支持 | 1 |
+
+
+## 2. 测试流程
+
+### 2.1 环境配置
+
+除了安装PaddleRS以外,您还需要安装规范化日志输出工具AutoLog:
+```
+pip install https://paddleocr.bj.bcebos.com/libs/auto_log-1.2.0-py3-none-any.whl
+```
+
+### 2.2 功能测试
+
+先运行`test_tipc/prepare.sh`准备数据和模型,然后运行`test_tipc/test_train_inference_python.sh`进行测试。测试过程中生成的日志文件均存储在`test_tipc/output/`目录。
+
+`test_tipc/test_train_inference_python.sh`支持4种运行模式,分别是:
+
+- 模式1:lite_train_lite_infer,使用少量数据训练,用于快速验证训练到预测的流程是否能走通,不验证精度和速度;
+```shell
+bash ./test_tipc/prepare.sh test_tipc/configs/clas/hrnet/train_infer_python.txt lite_train_lite_infer
+bash ./test_tipc/test_train_inference.sh test_tipc/configs/clas/hrnet/train_infer_python.txt lite_train_lite_infer
+```
+
+- 模式2:lite_train_whole_infer,使用少量数据训练,全量数据预测,用于验证训练后的模型执行预测时预测速度是否合理;
+```shell
+bash ./test_tipc/prepare.sh test_tipc/configs/clas/hrnet/train_infer_python.txt lite_train_whole_infer
+bash ./test_tipc/test_train_inference.sh test_tipc/configs/clas/hrnet/train_infer_python.txt lite_train_whole_infer
+```
+
+- 模式3:whole_infer,不训练,使用全量数据预测,验证模型动转静是否正常,检查模型的预测时间和精度;
+```shell
+bash ./test_tipc/prepare.sh test_tipc/configs/clas/hrnet/train_infer_python.txt whole_infer
+# 用法1:
+bash ./test_tipc/test_train_inference.sh test_tipc/configs/clas/hrnet/train_infer_python.txt whole_infer
+# 用法2: 在指定GPU上执行预测,第三个传入参数为GPU编号
+bash ./test_tipc/test_train_inference.sh test_tipc/configs/clas/hrnet/train_infer_python.txt whole_infer '1'
+```
+
+- 模式4:whole_train_whole_infer,CE: 全量数据训练,全量数据预测,验证模型训练精度、预测精度、预测速度;
+```shell
+bash ./test_tipc/prepare.sh test_tipc/configs/clas/hrnet/train_infer_python.txt whole_train_whole_infer
+bash ./test_tipc/test_train_inference.sh test_tipc/configs/clas/hrnet/train_infer_python.txt whole_train_whole_infer
+```
+
+运行相应指令后,在`test_tipc/output`目录中会自动保存运行日志。如lite_train_lite_infer模式下,该目录中可能存在以下文件:
+```
+test_tipc/output/[task name]/[model name]/
+|- results_python.log # 存储指令执行状态的日志
+|- norm_gpus_0_autocast_null/ # GPU 0号卡上的训练日志和模型保存目录
+......
+|- python_infer_cpu_usemkldnn_True_threads_6_precision_fp32_batchsize_1.log # CPU上开启mkldnn,线程数设置为6,测试batch_size=1条件下的预测运行日志
+|- python_infer_gpu_usetrt_True_precision_fp16_batchsize_1.log # GPU上开启TensorRT,测试batch_size=1的半精度预测运行日志
+......
+```
+
+其中`results_python.log`中保存了每条指令的执行状态。如果指令运行成功,输出信息如下所示:
+```
+ Run successfully with command - hrnet - python test_tipc/infer.py --file_list ./test_tipc/data/ucmerced/ ./test_tipc/data/ucmerced/val.txt --device=gpu --use_trt=False --precision=fp32 --model_dir=./test_tipc/output/clas/hrnet/lite_train_lite_infer/norm_gpus_0,1_autocast_null/static/ --batch_size=1 --benchmark=True !
+......
+```
+
+如果运行失败,输出信息如下所示:
+```
+ Run failed with command - hrnet - python test_tipc/infer.py --file_list ./test_tipc/data/ucmerced/ ./test_tipc/data/ucmerced/val.txt --device=gpu --use_trt=False --precision=fp32 --model_dir=./test_tipc/output/clas/hrnet/lite_train_lite_infer/norm_gpus_0,1_autocast_null/static/ --batch_size=1 --benchmark=True !
+......
+```
diff --git a/test_tipc/infer.py b/test_tipc/infer.py
new file mode 100644
index 0000000..9ad6123
--- /dev/null
+++ b/test_tipc/infer.py
@@ -0,0 +1,316 @@
+#!/usr/bin/env python
+
+import os
+import os.path as osp
+import argparse
+from operator import itemgetter
+
+import numpy as np
+import paddle
+from paddle.inference import Config
+from paddle.inference import create_predictor
+from paddle.inference import PrecisionType
+from paddlers.tasks import load_model
+from paddlers.utils import logging
+
+
+class _bool(object):
+ def __new__(cls, x):
+ if isinstance(x, str):
+ if x.lower() == 'false':
+ return False
+ elif x.lower() == 'true':
+ return True
+ return bool.__new__(x)
+
+
+class TIPCPredictor(object):
+ def __init__(self,
+ model_dir,
+ device='cpu',
+ gpu_id=0,
+ cpu_thread_num=1,
+ use_mkl=True,
+ mkl_thread_num=4,
+ use_trt=False,
+ memory_optimize=True,
+ trt_precision_mode='fp32',
+ benchmark=False,
+ model_name='',
+ batch_size=1):
+ self.model_dir = model_dir
+ self._model = load_model(model_dir, with_net=False)
+
+ if trt_precision_mode.lower() == 'fp32':
+ trt_precision_mode = PrecisionType.Float32
+ elif trt_precision_mode.lower() == 'fp16':
+ trt_precision_mode = PrecisionType.Float16
+ else:
+ logging.error(
+ "TensorRT precision mode {} is invalid. Supported modes are fp32 and fp16."
+ .format(trt_precision_mode),
+ exit=True)
+
+ self.config = self.get_config(
+ device=device,
+ gpu_id=gpu_id,
+ cpu_thread_num=cpu_thread_num,
+ use_mkl=use_mkl,
+ mkl_thread_num=mkl_thread_num,
+ use_trt=use_trt,
+ use_glog=False,
+ memory_optimize=memory_optimize,
+ max_trt_batch_size=1,
+ trt_precision_mode=trt_precision_mode)
+ self.predictor = create_predictor(self.config)
+
+ self.batch_size = batch_size
+
+ if benchmark:
+ import auto_log
+ pid = os.getpid()
+ self.autolog = auto_log.AutoLogger(
+ model_name=model_name,
+ model_precision=trt_precision_mode,
+ batch_size=batch_size,
+ data_shape='dynamic',
+ save_path=None,
+ inference_config=self.config,
+ pids=pid,
+ process_name=None,
+ gpu_ids=0,
+ time_keys=[
+ 'preprocess_time', 'inference_time', 'postprocess_time'
+ ],
+ warmup=0,
+ logger=logging)
+ self.benchmark = benchmark
+
+ def get_config(self, device, gpu_id, cpu_thread_num, use_mkl,
+ mkl_thread_num, use_trt, use_glog, memory_optimize,
+ max_trt_batch_size, trt_precision_mode):
+ config = Config(
+ osp.join(self.model_dir, 'model.pdmodel'),
+ osp.join(self.model_dir, 'model.pdiparams'))
+
+ if device == 'gpu':
+ config.enable_use_gpu(200, gpu_id)
+ config.switch_ir_optim(True)
+ if use_trt:
+ if self._model.model_type == 'segmenter':
+ logging.warning(
+ "Semantic segmentation models do not support TensorRT acceleration, "
+ "TensorRT is forcibly disabled.")
+ elif 'RCNN' in self._model.__class__.__name__:
+ logging.warning(
+ "RCNN models do not support TensorRT acceleration, "
+ "TensorRT is forcibly disabled.")
+ else:
+ config.enable_tensorrt_engine(
+ workspace_size=1 << 10,
+ max_batch_size=max_trt_batch_size,
+ min_subgraph_size=3,
+ precision_mode=trt_precision_mode,
+ use_static=False,
+ use_calib_mode=False)
+ else:
+ config.disable_gpu()
+ config.set_cpu_math_library_num_threads(cpu_thread_num)
+ if use_mkl:
+ if self._model.__class__.__name__ == 'MaskRCNN':
+ logging.warning(
+ "MaskRCNN does not support MKL-DNN, MKL-DNN is forcibly disabled"
+ )
+ else:
+ try:
+ # Cache 10 different shapes for mkldnn to avoid memory leak
+ config.set_mkldnn_cache_capacity(10)
+ config.enable_mkldnn()
+ config.set_cpu_math_library_num_threads(mkl_thread_num)
+ except Exception as e:
+ logging.warning(
+ "The current environment does not support MKL-DNN, MKL-DNN is disabled."
+ )
+ pass
+
+ if not use_glog:
+ config.disable_glog_info()
+ if memory_optimize:
+ config.enable_memory_optim()
+ config.switch_use_feed_fetch_ops(False)
+ return config
+
+ def preprocess(self, images, transforms):
+ preprocessed_samples = self._model._preprocess(
+ images, transforms, to_tensor=False)
+ if self._model.model_type == 'classifier':
+ preprocessed_samples = {'image': preprocessed_samples[0]}
+ elif self._model.model_type == 'segmenter':
+ preprocessed_samples = {
+ 'image': preprocessed_samples[0],
+ 'ori_shape': preprocessed_samples[1]
+ }
+ elif self._model.model_type == 'detector':
+ pass
+ elif self._model.model_type == 'change_detector':
+ preprocessed_samples = {
+ 'image': preprocessed_samples[0],
+ 'image2': preprocessed_samples[1],
+ 'ori_shape': preprocessed_samples[2]
+ }
+ else:
+ logging.error(
+ "Invalid model type {}".format(self._model.model_type),
+ exit=True)
+ return preprocessed_samples
+
+ def postprocess(self, net_outputs, topk=1, ori_shape=None, transforms=None):
+ if self._model.model_type == 'classifier':
+ true_topk = min(self._model.num_classes, topk)
+ if self._model._postprocess is None:
+ self._model.build_postprocess_from_labels(topk)
+ # XXX: Convert ndarray to tensor as self._model._postprocess requires
+ assert len(net_outputs) == 1
+ net_outputs = paddle.to_tensor(net_outputs[0])
+ outputs = self._model._postprocess(net_outputs)
+ class_ids = map(itemgetter('class_ids'), outputs)
+ scores = map(itemgetter('scores'), outputs)
+ label_names = map(itemgetter('label_names'), outputs)
+ preds = [{
+ 'class_ids_map': l,
+ 'scores_map': s,
+ 'label_names_map': n,
+ } for l, s, n in zip(class_ids, scores, label_names)]
+ elif self._model.model_type in ('segmenter', 'change_detector'):
+ label_map, score_map = self._model._postprocess(
+ net_outputs,
+ batch_origin_shape=ori_shape,
+ transforms=transforms.transforms)
+ preds = [{
+ 'label_map': l,
+ 'score_map': s
+ } for l, s in zip(label_map, score_map)]
+ elif self._model.model_type == 'detector':
+ net_outputs = {
+ k: v
+ for k, v in zip(['bbox', 'bbox_num', 'mask'], net_outputs)
+ }
+ preds = self._model._postprocess(net_outputs)
+ else:
+ logging.error(
+ "Invalid model type {}.".format(self._model.model_type),
+ exit=True)
+
+ return preds
+
+ def _run(self, images, topk=1, transforms=None, time_it=False):
+ if self.benchmark and time_it:
+ self.autolog.times.start()
+
+ preprocessed_input = self.preprocess(images, transforms)
+
+ input_names = self.predictor.get_input_names()
+ for name in input_names:
+ input_tensor = self.predictor.get_input_handle(name)
+ input_tensor.copy_from_cpu(preprocessed_input[name])
+
+ if self.benchmark and time_it:
+ self.autolog.times.stamp()
+
+ self.predictor.run()
+
+ output_names = self.predictor.get_output_names()
+ net_outputs = []
+ for name in output_names:
+ output_tensor = self.predictor.get_output_handle(name)
+ net_outputs.append(output_tensor.copy_to_cpu())
+
+ if self.benchmark and time_it:
+ self.autolog.times.stamp()
+
+ res = self.postprocess(
+ net_outputs,
+ topk,
+ ori_shape=preprocessed_input.get('ori_shape', None),
+ transforms=transforms)
+
+ if self.benchmark and time_it:
+ self.autolog.times.end(stamp=True)
+
+ return res
+
+ def predict(self, data_dir, file_list, topk=1, warmup_iters=5):
+ transforms = self._model.test_transforms
+
+ # Warm up
+ iters = 0
+ while True:
+ for images in self._parse_lines(data_dir, file_list):
+ if iters >= warmup_iters:
+ break
+ self._run(
+ images=images,
+ topk=topk,
+ transforms=transforms,
+ time_it=False)
+ iters += 1
+ else:
+ continue
+ break
+
+ results = []
+ for images in self._parse_lines(data_dir, file_list):
+ res = self._run(
+ images=images, topk=topk, transforms=transforms, time_it=True)
+ results.append(res)
+ return results
+
+ def _parse_lines(self, data_dir, file_list):
+ with open(file_list, 'r') as f:
+ batch = []
+ for line in f:
+ items = line.strip().split()
+ items = [osp.join(data_dir, item) for item in items]
+ if self._model.model_type == 'change_detector':
+ batch.append((items[0], items[1]))
+ else:
+ batch.append(items[0])
+ if len(batch) == self.batch_size:
+ yield batch
+ batch.clear()
+ if 0 < len(batch) < self.batch_size:
+ yield batch
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+
+ parser.add_argument('--file_list', type=str, nargs=2)
+ parser.add_argument('--model_dir', type=str, default='./')
+ parser.add_argument(
+ '--device', type=str, choices=['cpu', 'gpu'], default='cpu')
+ parser.add_argument('--enable_mkldnn', type=_bool, default=False)
+ parser.add_argument('--cpu_threads', type=int, default=10)
+ parser.add_argument('--use_trt', type=_bool, default=False)
+ parser.add_argument(
+ '--precision', type=str, choices=['fp32', 'fp16'], default='fp16')
+ parser.add_argument('--batch_size', type=int, default=1)
+ parser.add_argument('--benchmark', type=_bool, default=False)
+ parser.add_argument('--model_name', type=str, default='')
+
+ args = parser.parse_args()
+
+ predictor = TIPCPredictor(
+ args.model_dir,
+ device=args.device,
+ cpu_thread_num=args.cpu_threads,
+ use_mkl=args.enable_mkldnn,
+ mkl_thread_num=args.cpu_threads,
+ use_trt=args.use_trt,
+ trt_precision_mode=args.precision,
+ benchmark=args.benchmark)
+
+ predictor.predict(args.file_list[0], args.file_list[1])
+
+ if args.benchmark:
+ predictor.autolog.report()
diff --git a/test_tipc/prepare.sh b/test_tipc/prepare.sh
new file mode 100644
index 0000000..cc4c807
--- /dev/null
+++ b/test_tipc/prepare.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+
+source test_tipc/common_func.sh
+
+set -o errexit
+set -o nounset
+
+FILENAME=$1
+# $MODE must be one of ('lite_train_lite_infer' 'lite_train_whole_infer' 'whole_train_whole_infer', 'whole_infer')
+MODE=$2
+
+dataline=$(cat ${FILENAME})
+
+# Parse params
+IFS=$'\n'
+lines=(${dataline})
+task_name=$(parse_first_value "${lines[1]}")
+model_name=$(parse_second_value "${lines[1]}")
+
+# Download pretrained weights
+if [ ${MODE} = 'whole_infer' ]; then
+ :
+fi
+
+# Download datasets
+DATA_DIR='./test_tipc/data/'
+mkdir -p "${DATA_DIR}"
+if [[ ${MODE} == 'lite_train_lite_infer' \
+ || ${MODE} == 'lite_train_whole_infer' \
+ || ${MODE} == 'whole_train_whole_infer' \
+ || ${MODE} == 'whole_infer' ]]; then
+
+ if [[ ${task_name} == 'cd' ]]; then
+ download_and_unzip_dataset "${DATA_DIR}" airchange https://paddlers.bj.bcebos.com/datasets/airchange.zip
+ elif [[ ${task_name} == 'clas' ]]; then
+ download_and_unzip_dataset "${DATA_DIR}" ucmerced https://paddlers.bj.bcebos.com/datasets/ucmerced.zip
+ elif [[ ${task_name} == 'det' ]]; then
+ download_and_unzip_dataset "${DATA_DIR}" sarship https://paddlers.bj.bcebos.com/datasets/sarship.zip
+ elif [[ ${task_name} == 'seg' ]]; then
+ download_and_unzip_dataset "${DATA_DIR}" rsseg https://paddlers.bj.bcebos.com/datasets/rsseg_mini.zip
+ fi
+
+fi
diff --git a/test_tipc/run_task.py b/test_tipc/run_task.py
new file mode 100644
index 0000000..c4cf6a1
--- /dev/null
+++ b/test_tipc/run_task.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+
+import os
+
+# Import cv2 and sklearn before paddlers to solve the
+# "ImportError: dlopen: cannot load any more object with static TLS" issue.
+import cv2
+import sklearn
+import paddle
+import paddlers
+from paddlers import transforms as T
+
+from config_utils import parse_args, build_objects, CfgNode
+
+
+def format_cfg(cfg, indent=0):
+ s = ''
+ if isinstance(cfg, dict):
+ for i, (k, v) in enumerate(sorted(cfg.items())):
+ s += ' ' * indent + str(k) + ': '
+ if isinstance(v, (dict, list, CfgNode)):
+ s += '\n' + format_cfg(v, indent=indent + 1)
+ else:
+ s += str(v)
+ if i != len(cfg) - 1:
+ s += '\n'
+ elif isinstance(cfg, list):
+ for i, v in enumerate(cfg):
+ s += ' ' * indent + '- '
+ if isinstance(v, (dict, list, CfgNode)):
+ s += '\n' + format_cfg(v, indent=indent + 1)
+ else:
+ s += str(v)
+ if i != len(cfg) - 1:
+ s += '\n'
+ elif isinstance(cfg, CfgNode):
+ s += ' ' * indent + f"type: {cfg.type}" + '\n'
+ s += ' ' * indent + f"module: {cfg.module}" + '\n'
+ s += ' ' * indent + 'args: \n' + format_cfg(cfg.args, indent + 1)
+ return s
+
+
+if __name__ == '__main__':
+ CfgNode.set_context(globals())
+
+ cfg = parse_args()
+ print(format_cfg(cfg))
+
+ # Automatically download data
+ if cfg['download_on']:
+ paddlers.utils.download_and_decompress(
+ cfg['download_url'], path=cfg['download_path'])
+
+ if cfg['cmd'] == 'train':
+ train_dataset = build_objects(
+ cfg['datasets']['train'], mod=paddlers.datasets)
+ train_transforms = T.Compose(
+ build_objects(
+ cfg['transforms']['train'], mod=T))
+ # XXX: Late binding of transforms
+ train_dataset.transforms = train_transforms
+ eval_dataset = build_objects(cfg['datasets']['eval'], mod=paddlers.datasets)
+ eval_transforms = T.Compose(build_objects(cfg['transforms']['eval'], mod=T))
+ # XXX: Late binding of transforms
+ eval_dataset.transforms = eval_transforms
+
+ model = build_objects(
+ cfg['model'], mod=getattr(paddlers.tasks, cfg['task']))
+
+ if cfg['cmd'] == 'train':
+ if cfg['optimizer']:
+ if len(cfg['optimizer'].args) == 0:
+ cfg['optimizer'].args = {}
+ if not isinstance(cfg['optimizer'].args, dict):
+ raise TypeError
+ if cfg['optimizer'].args.get('parameters', None) is not None:
+ raise ValueError
+ cfg['optimizer'].args['parameters'] = model.net.parameters()
+ optimizer = build_objects(cfg['optimizer'], mod=paddle.optimizer)
+ else:
+ optimizer = None
+
+ model.train(
+ num_epochs=cfg['num_epochs'],
+ train_dataset=train_dataset,
+ train_batch_size=cfg['train_batch_size'],
+ eval_dataset=eval_dataset,
+ optimizer=optimizer,
+ save_interval_epochs=cfg['save_interval_epochs'],
+ log_interval_steps=cfg['log_interval_steps'],
+ save_dir=cfg['save_dir'],
+ learning_rate=cfg['learning_rate'],
+ early_stop=cfg['early_stop'],
+ early_stop_patience=cfg['early_stop_patience'],
+ use_vdl=cfg['use_vdl'],
+ resume_checkpoint=cfg['resume_checkpoint'] or None,
+ **cfg['train'])
+ elif cfg['cmd'] == 'eval':
+ state_dict = paddle.load(
+ os.path.join(cfg['resume_checkpoint'], 'model.pdparams'))
+ model.net.set_state_dict(state_dict)
+ res = model.evaluate(eval_dataset)
+ print(res)
diff --git a/test_tipc/test_train_inference.sh b/test_tipc/test_train_inference.sh
new file mode 100644
index 0000000..3fb300b
--- /dev/null
+++ b/test_tipc/test_train_inference.sh
@@ -0,0 +1,369 @@
+#!/usr/bin/env bash
+
+source test_tipc/common_func.sh
+
+FILENAME=$1
+# $MODE be one of {'lite_train_lite_infer' 'lite_train_whole_infer' 'whole_train_whole_infer', 'whole_infer'}
+MODE=$2
+
+dataline=$(awk 'NR>=1{print}' $FILENAME)
+
+# Parse params
+IFS=$'\n'
+lines=(${dataline})
+
+# Training params
+task_name=$(parse_first_value "${lines[1]}")
+model_name=$(parse_second_value "${lines[1]}")
+python=$(func_parser_value "${lines[2]}")
+gpu_list=$(func_parser_value "${lines[3]}")
+train_use_gpu_key=$(func_parser_key "${lines[4]}")
+train_use_gpu_value=$(func_parser_value "${lines[4]}")
+autocast_list=$(func_parser_value "${lines[5]}")
+autocast_key=$(func_parser_key "${lines[5]}")
+epoch_key=$(func_parser_key "${lines[6]}")
+epoch_num=$(func_parser_params "${lines[6]}")
+save_model_key=$(func_parser_key "${lines[7]}")
+train_batch_key=$(func_parser_key "${lines[8]}")
+train_batch_value=$(func_parser_params "${lines[8]}")
+pretrain_model_key=$(func_parser_key "${lines[9]}")
+pretrain_model_value=$(func_parser_value "${lines[9]}")
+train_model_name=$(func_parser_value "${lines[10]}")
+train_infer_img_dir=$(parse_first_value "${lines[11]}")
+train_infer_img_file_list=$(parse_second_value "${lines[11]}")
+train_param_key1=$(func_parser_key "${lines[12]}")
+train_param_value1=$(func_parser_value "${lines[12]}")
+
+trainer_list=$(func_parser_value "${lines[14]}")
+trainer_norm=$(func_parser_key "${lines[15]}")
+norm_trainer=$(func_parser_value "${lines[15]}")
+pact_key=$(func_parser_key "${lines[16]}")
+pact_trainer=$(func_parser_value "${lines[16]}")
+fpgm_key=$(func_parser_key "${lines[17]}")
+fpgm_trainer=$(func_parser_value "${lines[17]}")
+distill_key=$(func_parser_key "${lines[18]}")
+distill_trainer=$(func_parser_value "${lines[18]}")
+trainer_key1=$(func_parser_key "${lines[19]}")
+trainer_value1=$(func_parser_value "${lines[19]}")
+trainer_key2=$(func_parser_key "${lines[20]}")
+trainer_value2=$(func_parser_value "${lines[20]}")
+
+eval_py=$(func_parser_value "${lines[23]}")
+eval_key1=$(func_parser_key "${lines[24]}")
+eval_value1=$(func_parser_value "${lines[24]}")
+
+save_infer_key=$(func_parser_key "${lines[27]}")
+export_weight=$(func_parser_key "${lines[28]}")
+export_shape_key=$(func_parser_key "${lines[29]}")
+export_shape_value=$(func_parser_value "${lines[29]}")
+norm_export=$(func_parser_value "${lines[30]}")
+pact_export=$(func_parser_value "${lines[31]}")
+fpgm_export=$(func_parser_value "${lines[32]}")
+distill_export=$(func_parser_value "${lines[33]}")
+export_key1=$(func_parser_key "${lines[34]}")
+export_value1=$(func_parser_value "${lines[34]}")
+export_key2=$(func_parser_key "${lines[35]}")
+export_value2=$(func_parser_value "${lines[35]}")
+inference_dir=$(func_parser_value "${lines[36]}")
+
+# Params of inference model
+infer_model_dir_list=$(func_parser_value "${lines[37]}")
+infer_export_list=$(func_parser_value "${lines[38]}")
+infer_is_quant=$(func_parser_value "${lines[39]}")
+# Inference params
+inference_py=$(func_parser_value "${lines[40]}")
+use_gpu_key=$(func_parser_key "${lines[41]}")
+use_gpu_list=$(func_parser_value "${lines[41]}")
+use_mkldnn_key=$(func_parser_key "${lines[42]}")
+use_mkldnn_list=$(func_parser_value "${lines[42]}")
+cpu_threads_key=$(func_parser_key "${lines[43]}")
+cpu_threads_list=$(func_parser_value "${lines[43]}")
+batch_size_key=$(func_parser_key "${lines[44]}")
+batch_size_list=$(func_parser_value "${lines[44]}")
+use_trt_key=$(func_parser_key "${lines[45]}")
+use_trt_list=$(func_parser_value "${lines[45]}")
+precision_key=$(func_parser_key "${lines[46]}")
+precision_list=$(func_parser_value "${lines[46]}")
+infer_model_key=$(func_parser_key "${lines[47]}")
+file_list_key=$(func_parser_key "${lines[48]}")
+infer_img_dir=$(parse_first_value "${lines[48]}")
+infer_img_file_list=$(parse_second_value "${lines[48]}")
+save_log_key=$(func_parser_key "${lines[49]}")
+benchmark_key=$(func_parser_key "${lines[50]}")
+benchmark_value=$(func_parser_value "${lines[50]}")
+infer_key1=$(func_parser_key "${lines[51]}")
+infer_value1=$(func_parser_value "${lines[51]}")
+infer_key2=$(func_parser_key "${lines[52]}")
+infer_value2=$(func_parser_value "${lines[52]}")
+
+OUT_PATH="./test_tipc/output/${task_name}/${model_name}/${MODE}"
+mkdir -p ${OUT_PATH}
+status_log="${OUT_PATH}/results_python.log"
+echo "------------------------ ${MODE} ------------------------" >> "${status_log}"
+
+# Parse extra args
+parse_extra_args "${lines[@]}"
+for params in ${extra_args[*]}; do
+ IFS=':'
+ arr=(${params})
+ key=${arr[0]}
+ value=${arr[1]}
+ :
+done
+
+function func_inference() {
+ local IFS='|'
+ local _python=$1
+ local _script="$2"
+ local _model_dir="$3"
+ local _log_path="$4"
+ local _img_dir="$5"
+ local _file_list="$6"
+
+ # Do inference
+ for use_gpu in ${use_gpu_list[*]}; do
+ if [ ${use_gpu} = 'False' ] || [ ${use_gpu} = 'cpu' ]; then
+ for use_mkldnn in ${use_mkldnn_list[*]}; do
+ if [ ${use_mkldnn} = 'False' ]; then
+ continue
+ fi
+ for threads in ${cpu_threads_list[*]}; do
+ for batch_size in ${batch_size_list[*]}; do
+ for precision in ${precision_list[*]}; do
+ if [ ${use_mkldnn} = 'False' ] && [ ${precision} = 'fp16' ]; then
+ continue
+ fi # Skip when enable fp16 but disable mkldnn
+
+ set_precision=$(func_set_params "${precision_key}" "${precision}")
+
+ _save_log_path="${_log_path}/python_infer_cpu_usemkldnn_${use_mkldnn}_threads_${threads}_precision_${precision}_batchsize_${batch_size}.log"
+ infer_value1="${_log_path}/python_infer_cpu_usemkldnn_${use_mkldnn}_threads_${threads}_precision_${precision}_batchsize_${batch_size}_results"
+ set_device=$(func_set_params "${use_gpu_key}" "${use_gpu}")
+ set_mkldnn=$(func_set_params "${use_mkldnn_key}" "${use_mkldnn}")
+ set_benchmark=$(func_set_params "${benchmark_key}" "${benchmark_value}")
+ set_batchsize=$(func_set_params "${batch_size_key}" "${batch_size}")
+ set_cpu_threads=$(func_set_params "${cpu_threads_key}" "${threads}")
+ set_model_dir=$(func_set_params "${infer_model_key}" "${_model_dir}")
+ set_infer_params1=$(func_set_params "${infer_key1}" "${infer_value1}")
+ set_infer_params2=$(func_set_params "${infer_key2}" "${infer_value2}")
+
+ cmd="${_python} ${_script} ${file_list_key} ${_img_dir} ${_file_list} ${set_device} ${set_mkldnn} ${set_cpu_threads} ${set_model_dir} ${set_batchsize} ${set_benchmark} ${set_precision} ${set_infer_params1} ${set_infer_params2}"
+ echo ${cmd}
+ run_command "${cmd}" "${_save_log_path}"
+
+ last_status=${PIPESTATUS[0]}
+ status_check ${last_status} "${cmd}" "${status_log}" "${model_name}"
+ done
+ done
+ done
+ done
+ elif [ ${use_gpu} = 'True' ] || [ ${use_gpu} = 'gpu' ]; then
+ for use_trt in ${use_trt_list[*]}; do
+ for precision in ${precision_list[*]}; do
+ if [ ${precision} = 'fp16' ] && [ ${use_trt} = 'False' ]; then
+ continue
+ fi # Skip when enable fp16 but disable trt
+
+ for batch_size in ${batch_size_list[*]}; do
+ _save_log_path="${_log_path}/python_infer_gpu_usetrt_${use_trt}_precision_${precision}_batchsize_${batch_size}.log"
+ infer_value1="${_log_path}/python_infer_gpu_usetrt_${use_trt}_precision_${precision}_batchsize_${batch_size}_results"
+ set_device=$(func_set_params "${use_gpu_key}" "${use_gpu}")
+ set_benchmark=$(func_set_params "${benchmark_key}" "${benchmark_value}")
+ set_batchsize=$(func_set_params "${batch_size_key}" "${batch_size}")
+ set_tensorrt=$(func_set_params "${use_trt_key}" "${use_trt}")
+ set_precision=$(func_set_params "${precision_key}" "${precision}")
+ set_model_dir=$(func_set_params "${infer_model_key}" "${_model_dir}")
+ set_infer_params1=$(func_set_params "${infer_key1}" "${infer_value1}")
+ set_infer_params2=$(func_set_params "${infer_key2}" "${infer_value2}")
+
+ cmd="${_python} ${_script} ${file_list_key} ${_img_dir} ${_file_list} ${set_device} ${set_tensorrt} ${set_precision} ${set_model_dir} ${set_batchsize} ${set_benchmark} ${set_infer_params2}"
+ echo ${cmd}
+ run_command "${cmd}" "${_save_log_path}"
+
+ last_status=${PIPESTATUS[0]}
+ status_check $last_status "${cmd}" "${status_log}" "${model_name}"
+
+ done
+ done
+ done
+ else
+ echo "Currently, hardwares other than CPU and GPU are not supported!"
+ fi
+ done
+}
+
+if [ ${MODE} = 'whole_infer' ]; then
+ GPUID=$3
+ if [ ${#GPUID} -le 0 ]; then
+ env=""
+ else
+ env="export CUDA_VISIBLE_DEVICES=${GPUID}"
+ fi
+ if [ ${infer_model_dir_list} == 'null' ]; then
+ echo -e "\033[33m No inference model is specified! \033[0m"
+ exit 1
+ fi
+ # Set CUDA_VISIBLE_DEVICES
+ eval ${env}
+ export count=0
+ IFS='|'
+ infer_run_exports=(${infer_export_list})
+ for infer_model in ${infer_model_dir_list[*]}; do
+ # Run export
+ if [ ${infer_run_exports[count]} != 'null' ]; then
+ save_infer_dir="${infer_model}/static"
+ set_export_weight=$(func_set_params "${export_weight}" "${infer_model}")
+ set_export_shape=$(func_set_params "${export_shape_key}" "${export_shape_value}")
+ set_save_infer_key=$(func_set_params "${save_infer_key}" "${save_infer_dir}")
+
+ export_cmd="${python} ${infer_run_exports[count]} ${set_export_weight} ${set_save_infer_key} ${set_export_shape}"
+ echo ${infer_run_exports[count]}
+ eval ${export_cmd}
+
+ status_export=$?
+ status_check ${status_export} "${export_cmd}" "${status_log}" "${model_name}"
+ else
+ save_infer_dir=${infer_model}
+ fi
+ # Run inference
+ func_inference "${python}" "${inference_py}" "${save_infer_dir}" "${OUT_PATH}" "${infer_img_dir}" "${infer_img_file_list}"
+ count=$((${count} + 1))
+ done
+else
+ IFS='|'
+ export count=0
+ USE_GPU_KEY=(${train_use_gpu_value})
+ for gpu in ${gpu_list[*]}; do
+ train_use_gpu=${USE_GPU_KEY[count]}
+ count=$((${count} + 1))
+ ips=""
+ if [ ${gpu} = '-1' ]; then
+ env=""
+ elif [ ${#gpu} -le 1 ]; then
+ env="export CUDA_VISIBLE_DEVICES=${gpu}"
+ eval ${env}
+ elif [ ${#gpu} -le 15 ]; then
+ IFS=','
+ array=(${gpu})
+ env="export CUDA_VISIBLE_DEVICES=${array[0]}"
+ IFS='|'
+ else
+ IFS=';'
+ array=(${gpu})
+ ips=${array[0]}
+ gpu=${array[1]}
+ IFS='|'
+ env=""
+ fi
+ for autocast in ${autocast_list[*]}; do
+ if [ ${autocast} = 'amp' ]; then
+ set_amp_config="Global.use_amp=True Global.scale_loss=1024.0 Global.use_dynamic_loss_scaling=True"
+ else
+ set_amp_config=""
+ fi
+ for trainer in ${trainer_list[*]}; do
+ if [ ${trainer} = ${pact_key} ]; then
+ run_train=${pact_trainer}
+ run_export=${pact_export}
+ elif [ ${trainer} = "${fpgm_key}" ]; then
+ run_train=${fpgm_trainer}
+ run_export=${fpgm_export}
+ elif [ ${trainer} = "${distill_key}" ]; then
+ run_train=${distill_trainer}
+ run_export=${distill_export}
+ elif [ ${trainer} = ${trainer_key1} ]; then
+ run_train=${trainer_value1}
+ run_export=${export_value1}
+ elif [[ ${trainer} = ${trainer_key2} ]]; then
+ run_train=${trainer_value2}
+ run_export=${export_value2}
+ else
+ run_train=${norm_trainer}
+ run_export=${norm_export}
+ fi
+
+ if [ ${run_train} = 'null' ]; then
+ continue
+ fi
+ set_autocast=$(func_set_params "${autocast_key}" "${autocast}")
+ set_epoch=$(func_set_params "${epoch_key}" "${epoch_num}")
+ set_pretrain=$(func_set_params "${pretrain_model_key}" "${pretrain_model_value}")
+ set_batchsize=$(func_set_params "${train_batch_key}" "${train_batch_value}")
+ set_train_params1=$(func_set_params "${train_param_key1}" "${train_param_value1}")
+ set_use_gpu=$(func_set_params "${train_use_gpu_key}" "${train_use_gpu}")
+ # If length of ips >= 15, then it is seen as multi-machine.
+ # 15 is the min length of ips info for multi-machine: 0.0.0.0,0.0.0.0
+ if [ ${#ips} -le 15 ]; then
+ save_dir="${OUT_PATH}/${trainer}_gpus_${gpu}_autocast_${autocast}"
+ nodes=1
+ else
+ IFS=','
+ ips_array=(${ips})
+ IFS='|'
+ nodes=${#ips_array[@]}
+ save_dir="${OUT_PATH}/${trainer}_gpus_${gpu}_autocast_${autocast}_nodes_${nodes}"
+ fi
+ log_path="${OUT_PATH}/${trainer}_gpus_${gpu}_autocast_${autocast}_nodes_${nodes}.log"
+
+ # Load pretrained model from norm training if current trainer is pact or fpgm trainer.
+ if ([ ${trainer} = ${pact_key} ] || [ ${trainer} = ${fpgm_key} ]) && [ ${nodes} -le 1 ]; then
+ set_pretrain="${load_norm_train_model}"
+ fi
+
+ set_save_model=$(func_set_params "${save_model_key}" "${save_dir}")
+ if [ ${#gpu} -le 2 ]; then # Train with cpu or single gpu
+ cmd="${python} ${run_train} ${set_use_gpu} ${set_save_model} ${set_epoch} ${set_pretrain} ${set_autocast} ${set_batchsize} ${set_train_params1} ${set_amp_config}"
+ elif [ ${#ips} -le 15 ]; then # Train with multi-gpu
+ cmd="${python} -m paddle.distributed.launch --gpus=${gpu} ${run_train} ${set_use_gpu} ${set_save_model} ${set_epoch} ${set_pretrain} ${set_autocast} ${set_batchsize} ${set_train_params1} ${set_amp_config}"
+ else # Train with multi-machine
+ cmd="${python} -m paddle.distributed.launch --ips=${ips} --gpus=${gpu} ${run_train} ${set_use_gpu} ${set_save_model} ${set_pretrain} ${set_epoch} ${set_autocast} ${set_batchsize} ${set_train_params1} ${set_amp_config}"
+ fi
+
+ echo ${cmd}
+ # Run train
+ run_command "${cmd}" "${log_path}"
+ status_check $? "${cmd}" "${status_log}" "${model_name}"
+
+ if [[ "${cmd}" == *'paddle.distributed.launch'* ]]; then
+ cat log/workerlog.0 >> ${log_path}
+ fi
+
+ set_eval_pretrain=$(func_set_params "${pretrain_model_key}" "${save_dir}/${train_model_name}/model.pdparams")
+ # Save norm trained models to set pretrain for pact training and fpgm training
+ if [ ${trainer} = ${trainer_norm} ] && [ ${nodes} -le 1 ]; then
+ load_norm_train_model=${set_eval_pretrain}
+ fi
+ # Run evaluation
+ if [ ${eval_py} != 'null' ]; then
+ log_path="${OUT_PATH}/${trainer}_gpus_${gpu}_autocast_${autocast}_nodes_${nodes}_eval.log"
+ set_eval_params1=$(func_set_params "${eval_key1}" "${eval_value1}")
+ eval_cmd="${python} ${eval_py} ${set_eval_pretrain} ${set_use_gpu} ${set_eval_params1}"
+ run_command "${eval_cmd}" "${log_path}"
+ status_check $? "${eval_cmd}" "${status_log}" "${model_name}"
+ fi
+ # Run export model
+ if [ ${run_export} != 'null' ]; then
+ log_path="${OUT_PATH}/${trainer}_gpus_${gpu}_autocast_${autocast}_nodes_${nodes}_export.log"
+ save_infer_path="${save_dir}/static"
+ set_export_weight=$(func_set_params "${export_weight}" "${save_dir}/${train_model_name}")
+ set_export_shape=$(func_set_params "${export_shape_key}" "${export_shape_value}")
+ set_save_infer_key=$(func_set_params "${save_infer_key}" "${save_infer_path}")
+ export_cmd="${python} ${run_export} ${set_export_weight} ${set_save_infer_key} ${set_export_shape}"
+ run_command "${export_cmd}" "${log_path}"
+ status_check $? "${export_cmd}" "${status_log}" "${model_name}"
+
+ # Run inference
+ eval ${env}
+ if [[ ${inference_dir} != 'null' ]] && [[ ${inference_dir} != '##' ]]; then
+ infer_model_dir="${save_infer_path}/${inference_dir}"
+ else
+ infer_model_dir=${save_infer_path}
+ fi
+ func_inference "${python}" "${inference_py}" "${infer_model_dir}" "${OUT_PATH}" "${train_infer_img_dir}" "${train_infer_img_file_list}"
+
+ eval "unset CUDA_VISIBLE_DEVICES"
+ fi
+ done # Done with: for trainer in ${trainer_list[*]}; do
+ done # Done with: for autocast in ${autocast_list[*]}; do
+ done # Done with: for gpu in ${gpu_list[*]}; do
+fi # End if [ ${MODE} = 'infer' ]; then
\ No newline at end of file