Skip to content

Commit 5c48872

Browse files
authored
Merge pull request #71 from xiaomoguhzz/unknown-task-process
2 parents 24f74d0 + 7111198 commit 5c48872

52 files changed

Lines changed: 4917 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

benchmarking.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Copyright 2022 The KubeEdge Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""main"""
16+
17+
import sys
18+
import argparse
19+
20+
from core.common.log import LOGGER
21+
from core.common import utils
22+
from core.cmd.obj import BenchmarkingJob
23+
from core.__version__ import __version__
24+
25+
26+
def main():
27+
""" main command-line interface to ianvs"""
28+
try:
29+
parser = _generate_parser()
30+
args = parser.parse_args()
31+
config_file = args.benchmarking_config_file
32+
if not utils.is_local_file(config_file):
33+
raise SystemExit(f"not found benchmarking config({config_file}) file in local")
34+
35+
config = utils.yaml2dict(args.benchmarking_config_file)
36+
job = BenchmarkingJob(config[str.lower(BenchmarkingJob.__name__)])
37+
job.run()
38+
39+
LOGGER.info("benchmarkingjob runs successfully.")
40+
except Exception as err:
41+
raise RuntimeError(f"benchmarkingjob runs failed, error: {err}.") from err
42+
43+
44+
def _generate_parser():
45+
parser = argparse.ArgumentParser(description='AI Benchmarking Tool')
46+
parser.prog = "ianvs"
47+
48+
parser.add_argument("-f",
49+
"--benchmarking_config_file",
50+
nargs="?",
51+
type=str,
52+
help="run a benchmarking job, "
53+
"and the benchmarking config file must be yaml/yml file.")
54+
55+
parser.add_argument('-v',
56+
'--version',
57+
action='version',
58+
version=__version__,
59+
help='show program version info and exit.')
60+
61+
if len(sys.argv) == 1:
62+
parser.print_help(sys.stderr)
63+
sys.exit(1)
64+
65+
return parser
66+
67+
68+
if __name__ == '__main__':
69+
main()
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import json
2+
import os
3+
from core.common.constant import ParadigmType
4+
from examples.yaoba.singletask_learning_boost.resource.utils.infer_and_error import infer_anno, merge_predict_results, \
5+
compute_error, gen_txt_according_json, get_new_train_json
6+
from examples.yaoba.singletask_learning_boost.resource.utils.transform_unkonwn import aug_image_bboxes
7+
from .singletask_learning import SingleTaskLearning
8+
import os.path as osp
9+
10+
11+
class SingleTaskLearningACBoost(SingleTaskLearning):
12+
13+
def __init__(self, workspace, **kwargs):
14+
super(SingleTaskLearningACBoost, self).__init__(workspace, **kwargs)
15+
16+
def run(self):
17+
job = self.build_paradigm_job(str(ParadigmType.SINGLE_TASK_LEARNING.value))
18+
known_dataset_json, unknown_dataset_json, img_path = self._prepare_for_calculate_weights()
19+
base_config_path = osp.join(job.resource_dir, "base_config.py")
20+
train_script_path = osp.join(job.resource_dir, "train.py")
21+
ac_boost_training_json, aug_img_folder = self._calculate_weights_for_training(
22+
base_config=base_config_path,
23+
known_json_path=known_dataset_json,
24+
unknown_json_path=unknown_dataset_json,
25+
img_path=img_path,
26+
tmp_path=os.path.join(job.work_dir, "tmp_folder"),
27+
train_script_path=train_script_path
28+
)
29+
trained_model = self._ac_boost_train(job, ac_boost_training_json, aug_img_folder)
30+
inference_result = self._inference(job, trained_model)
31+
self.system_metric_info['use_raw'] = True
32+
return inference_result, self.system_metric_info
33+
34+
def _ac_boost_train(self, job, training_anno, training_img_folder):
35+
train_output_model_path = job.train((training_img_folder, training_anno))
36+
trained_model_path = job.save(train_output_model_path)
37+
return trained_model_path
38+
39+
def _inference(self, job, trained_model):
40+
# Load test set data
41+
img_prefix = self.dataset.image_folder_url
42+
ann_file_path = self.dataset.test_url
43+
ann_file = json.load(open(ann_file_path, mode="r", encoding="utf-8"))
44+
test_set = []
45+
for i in ann_file['images']:
46+
test_set.append(os.path.join(img_prefix, i['file_name']))
47+
48+
job.load(trained_model)
49+
infer_res = job.predict(test_set)
50+
return infer_res
51+
52+
def _prepare_for_calculate_weights(self):
53+
known_dataset_json = self.dataset.known_dataset_url
54+
unknown_dataset_json = self.dataset.unknown_dataset_url
55+
img_path = self.dataset.image_folder_url
56+
return known_dataset_json, unknown_dataset_json, img_path
57+
58+
def _calculate_weights_for_training(self,
59+
base_config,
60+
known_json_path,
61+
unknown_json_path,
62+
img_path,
63+
tmp_path,
64+
train_script_path):
65+
r"""Generate instance weights required for unknown task training. In object detection,
66+
an instance means a bounding box, i.e., generating training weights for each bounding box.
67+
Args:
68+
base_config (str): path of config file for training known/unknown model
69+
known_json_path (str): path of JSON file for training known model
70+
unknown_json_path (str): path of JSON file for training unknown model
71+
img_path (str): image path of training, validation, and test set.
72+
tmp_path (str): path to save temporary files, including augmented images, training JSON files, etc.
73+
train_script_path (str): path of mmdet training script
74+
Return:
75+
new_training_weight (str): JSON file with instance weights for unknown task training,
76+
which contains both the known and unknown training sets.
77+
aug_img_folder (str): the image paths required for training the model using the JSON file with instance weights.
78+
"""
79+
if not os.path.exists(tmp_path):
80+
os.mkdir(tmp_path)
81+
# Define necessary path
82+
aug_img_folder = osp.join(tmp_path, "aug_img_folder") # The directory for saving augmented images
83+
known_model_folder = osp.join(tmp_path, "known_model") # The directory for saving known model training results
84+
unknown_model_folder = osp.join(tmp_path, "unknown_model") # The directory for saving unknown model training results
85+
aug_unknown_json = osp.join(tmp_path, 'aug_unknown.json') # The JSON file path of the unknown data after augmentation
86+
87+
# Augmenting the unknown data and returning the paths of the augmented images
88+
aug_image_bboxes(
89+
anno=unknown_json_path,
90+
augs=[('flip', 1), ('brightness', 0.6), ('flip', -1)],
91+
image_path=img_path,
92+
out_path=tmp_path
93+
)
94+
95+
# Train the known model
96+
known_model_training_task = f"python {train_script_path} " \
97+
f"{base_config} --seed 1 --deterministic --cfg-options " \
98+
f"data.train.ann_file={known_json_path} " \
99+
f"data.train.img_prefix={img_path} " \
100+
f"work_dir={known_model_folder}"
101+
os.system(known_model_training_task)
102+
103+
# Train the unknown model
104+
unknown_model_training_task = f"python {train_script_path} " \
105+
f"{base_config} --seed 1 --deterministic --cfg-options " \
106+
f"data.train.ann_file={aug_unknown_json} " \
107+
f"data.train.img_prefix={aug_img_folder} " \
108+
f"work_dir={unknown_model_folder}"
109+
os.system(unknown_model_training_task)
110+
111+
# using above known model to infer unknown data
112+
infer_anno(
113+
config_file=base_config,
114+
checkpoint_file=osp.join(known_model_folder, 'latest.pth'),
115+
img_path=aug_img_folder,
116+
anno_path=aug_unknown_json,
117+
out_path=osp.join(tmp_path, 'unknown_infer_results.json')
118+
)
119+
120+
# using above unknown model to infer known data
121+
infer_anno(
122+
config_file=base_config,
123+
checkpoint_file=osp.join(unknown_model_folder, 'latest.pth'),
124+
img_path=aug_img_folder,
125+
anno_path=known_json_path,
126+
out_path=osp.join(tmp_path, 'known_infer_results.json')
127+
)
128+
129+
# merging the prediction results and computing error
130+
merge_predict_results(
131+
result1=osp.join(tmp_path, 'unknown_infer_results.json'),
132+
result2=osp.join(tmp_path, 'known_infer_results.json'),
133+
out_dir=osp.join(tmp_path, "merge_predict_result.json")
134+
)
135+
new_json = compute_error(osp.join(tmp_path, "merge_predict_result.json"))
136+
137+
# generating the weights of the overall training sample based on the prediction error.
138+
gen_txt_according_json(known_json_path, osp.join(tmp_path, 'known.txt'))
139+
gen_txt_according_json(aug_unknown_json, osp.join(tmp_path, 'aug_unknown.txt'))
140+
get_new_train_json(
141+
new_json,
142+
aug_img_folder,
143+
osp.join(tmp_path, 'known.txt'),
144+
osp.join(tmp_path, 'aug_unknown.txt'),
145+
out_dir=osp.join(tmp_path, 'new_training_weight.json'))
146+
147+
return osp.join(tmp_path, 'new_training_weight.json'), aug_img_folder
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import json
2+
import os
3+
import torch
4+
from mmdet.apis import init_detector
5+
from core.common.constant import ParadigmType
6+
from examples.yaoba.singletask_learning_yolox_tta.resource.utils.TTA_strategy import TTA_Strategy
7+
from .singletask_learning import SingleTaskLearning
8+
9+
10+
class SingleTaskLearningTTA(SingleTaskLearning):
11+
12+
def __init__(self, workspace, **kwargs):
13+
super(SingleTaskLearningTTA, self).__init__(workspace, **kwargs)
14+
15+
def run(self):
16+
# Build an experimental task
17+
job = self.build_paradigm_job(str(ParadigmType.SINGLE_TASK_LEARNING.value))
18+
19+
# If there are no initialized model weights, then train a new model from scratch
20+
if self.initial_model != "":
21+
trained_model = self.initial_model
22+
else:
23+
trained_model = self._train(job, None)
24+
25+
# Search for the optimal test-time augmentation policies
26+
searched_strategy = self._search_tta_strategy(job, trained_model)
27+
28+
# Merging the optimal policies with original default policy
29+
merged_strategy = self._prepare_infer_strategy(job, searched_strategy)
30+
31+
# infer the test set with searched policies
32+
inference_result = self._inference_w_tta(job, trained_model, merged_strategy)
33+
self.system_metric_info['use_raw']=True
34+
return inference_result, self.system_metric_info
35+
36+
def _inference_w_tta(self, job, trained_model, strategy):
37+
# Load test set data
38+
img_prefix = self.dataset.image_folder_url
39+
ann_file_path = self.dataset.test_url
40+
ann_file = json.load(open(ann_file_path, mode="r", encoding="utf-8"))
41+
test_set = []
42+
for i in ann_file['images']:
43+
test_set.append(os.path.join(img_prefix, i['file_name']))
44+
45+
# Perform inference with data augmentation policy.
46+
job.load(trained_model)
47+
print(f"Total infer strategy is :{strategy}")
48+
infer_res = job.tta_predict(test_set, strategy)
49+
50+
return infer_res
51+
52+
def _prepare_infer_strategy(self, job, searched_strategy):
53+
default_img_size = None
54+
# The default inference policy
55+
for p in job.cfg.data.test.pipeline:
56+
if p['type'] == 'MultiScaleFlipAug':
57+
default_img_size = p['img_scale']
58+
if default_img_size:
59+
combined_strategy = [[("TTA_Resize", default_img_size), ]]
60+
else:
61+
raise ValueError("can not find img_scale model cfg")
62+
combined_strategy.append(searched_strategy[0])
63+
64+
return combined_strategy
65+
66+
def _search_tta_strategy(self, job, model_url):
67+
# Load validation dataset
68+
img_prefix = self.dataset.image_folder_url
69+
ann_file = self.dataset.val_url
70+
71+
# Create a search agent to search for the best data augmentation strategy.
72+
model_cfg = job.cfg
73+
model = init_detector(model_cfg, model_url)
74+
torch.multiprocessing.set_start_method("spawn", force=True)
75+
search_agent = TTA_Strategy(
76+
model=model,
77+
val_image_path=img_prefix,
78+
val_anno_path=ann_file,
79+
log_dir=os.path.join(model_cfg.work_dir, "log"),
80+
worker=6,
81+
nms_thr=0.5
82+
)
83+
# Search for single policies for TTA
84+
single_strategies = search_agent.search_single_strategy(top_num=3)
85+
86+
# Search for Cascade policies for TTA, which based on single policies
87+
cascade_strategies = search_agent.search_cascade_strategy(
88+
single_strategies,
89+
cascade_num=3,
90+
top_num=5
91+
)
92+
return cascade_strategies
93+
94+
def _train(self, job, initial_model):
95+
img_prefix = self.dataset.image_folder_url
96+
ann_file = self.dataset.train_url
97+
checkpoint_path = job.train((img_prefix, ann_file))
98+
return checkpoint_path

examples/yaoba/__init__.py

Whitespace-only changes.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
benchmarkingjob:
2+
# job name of bechmarking; string type;
3+
name: "benchmarkingjob"
4+
# the url address of job workspace that will reserve the output of tests; string type;
5+
workspace: "examples/yaoba/singletask_learning_boost/workspace"
6+
# the url address of test environment configuration file; string type;
7+
# the file format supports yaml/yml;
8+
testenv: "examples/yaoba/singletask_learning_boost/testenv/testenv.yaml"
9+
# the configuration of test object
10+
test_object:
11+
# test type; string type;
12+
# currently the option of value is "algorithms",the others will be added in succession.
13+
type: "algorithms"
14+
# test algorithm configuration files; list type;
15+
algorithms:
16+
# algorithm name; string type;
17+
- name: "mmlab-model"
18+
# the url address of test algorithm configuration file; string type;
19+
# the file format supports yaml/yml;
20+
url: "examples/yaoba/singletask_learning_boost/testalgorithms/algorithm.yaml"
21+
22+
# the configuration of ranking leaderboard
23+
rank:
24+
# rank leaderboard with metric of test case's evaluation and order ; list type;
25+
# the sorting priority is based on the sequence of metrics in the list from front to back;
26+
sort_by: [ { "map": "descend" } ]
27+
28+
# visualization configuration
29+
visualization:
30+
# mode of visualization in the leaderboard; string type;
31+
# There are quite a few possible dataitems in the leaderboard. Not all of them can be shown simultaneously on the screen.
32+
# In the leaderboard, we provide the "selected_only" mode for the user to configure what is shown or is not shown.
33+
mode: "selected_only"
34+
# method of visualization for selected dataitems; string type;
35+
# currently the options of value are as follows:
36+
# 1> "print_table": print selected dataitems;
37+
method: "print_table"
38+
39+
# selected dataitem configuration
40+
# The user can add his/her interested dataitems in terms of "paradigms", "modules", "hyperparameters" and "metrics",
41+
# so that the selected columns will be shown.
42+
selected_dataitem:
43+
# currently the options of value are as follows:
44+
# 1> "all": select all paradigms in the leaderboard;
45+
# 2> paradigms in the leaderboard, e.g., "singletasklearning"
46+
paradigms: [ "all" ]
47+
# currently the options of value are as follows:
48+
# 1> "all": select all modules in the leaderboard;
49+
# 2> modules in the leaderboard, e.g., "basemodel"
50+
modules: [ "all" ]
51+
# currently the options of value are as follows:
52+
# 1> "all": select all hyperparameters in the leaderboard;
53+
# 2> hyperparameters in the leaderboard, e.g., "momentum"
54+
hyperparameters: [ "all" ]
55+
# currently the options of value are as follows:
56+
# 1> "all": select all metrics in the leaderboard;
57+
# 2> metrics in the leaderboard, e.g., "f1_score"
58+
metrics: [ "map" ]
59+
60+
# model of save selected and all dataitems in workspace; string type;
61+
# currently the options of value are as follows:
62+
# 1> "selected_and_all": save selected and all dataitems;
63+
# 2> "selected_only": save selected dataitems;
64+
save_mode: "selected_and_all"
65+
66+
67+
68+
69+
70+

0 commit comments

Comments
 (0)