supervisely 6.73.279__py3-none-any.whl → 6.73.280__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of supervisely might be problematic. Click here for more details.
- supervisely/nn/training/gui/gui.py +27 -17
- supervisely/nn/training/train_app.py +58 -29
- {supervisely-6.73.279.dist-info → supervisely-6.73.280.dist-info}/METADATA +1 -1
- {supervisely-6.73.279.dist-info → supervisely-6.73.280.dist-info}/RECORD +8 -8
- {supervisely-6.73.279.dist-info → supervisely-6.73.280.dist-info}/LICENSE +0 -0
- {supervisely-6.73.279.dist-info → supervisely-6.73.280.dist-info}/WHEEL +0 -0
- {supervisely-6.73.279.dist-info → supervisely-6.73.280.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.279.dist-info → supervisely-6.73.280.dist-info}/top_level.txt +0 -0
|
@@ -64,6 +64,7 @@ class TrainGUI:
|
|
|
64
64
|
self.hyperparameters = hyperparameters
|
|
65
65
|
self.app_options = app_options
|
|
66
66
|
self.collapsable = app_options.get("collapsable", False)
|
|
67
|
+
self.need_convert_shapes_for_bm = False
|
|
67
68
|
|
|
68
69
|
self.team_id = sly_env.team_id(raise_not_found=False)
|
|
69
70
|
self.workspace_id = sly_env.workspace_id(raise_not_found=False)
|
|
@@ -141,24 +142,33 @@ class TrainGUI:
|
|
|
141
142
|
self.training_process.set_experiment_name(experiment_name)
|
|
142
143
|
|
|
143
144
|
def need_convert_class_shapes() -> bool:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
def _need_convert(shape):
|
|
147
|
-
if task_type == TaskType.OBJECT_DETECTION:
|
|
148
|
-
return shape != Rectangle.geometry_name()
|
|
149
|
-
elif task_type in [TaskType.INSTANCE_SEGMENTATION, TaskType.SEMANTIC_SEGMENTATION]:
|
|
150
|
-
return shape == Polygon.geometry_name()
|
|
151
|
-
return
|
|
152
|
-
|
|
153
|
-
data = self.classes_selector.classes_table._table_data
|
|
154
|
-
selected_classes = set(self.classes_selector.classes_table.get_selected_classes())
|
|
155
|
-
empty = set(r[0]["data"] for r in data if r[2]["data"] == 0 and r[3]["data"] == 0)
|
|
156
|
-
need_convert = set(r[0]["data"] for r in data if _need_convert(r[1]["data"]))
|
|
157
|
-
|
|
158
|
-
if need_convert.intersection(selected_classes - empty):
|
|
159
|
-
self.hyperparameters_selector.model_benchmark_auto_convert_warning.show()
|
|
160
|
-
else:
|
|
145
|
+
if not self.hyperparameters_selector.run_model_benchmark_checkbox.is_checked():
|
|
161
146
|
self.hyperparameters_selector.model_benchmark_auto_convert_warning.hide()
|
|
147
|
+
self.need_convert_shapes_for_bm = False
|
|
148
|
+
else:
|
|
149
|
+
task_type = self.model_selector.get_selected_task_type()
|
|
150
|
+
|
|
151
|
+
def _need_convert(shape):
|
|
152
|
+
if task_type == TaskType.OBJECT_DETECTION:
|
|
153
|
+
return shape != Rectangle.geometry_name()
|
|
154
|
+
elif task_type in [
|
|
155
|
+
TaskType.INSTANCE_SEGMENTATION,
|
|
156
|
+
TaskType.SEMANTIC_SEGMENTATION,
|
|
157
|
+
]:
|
|
158
|
+
return shape == Polygon.geometry_name()
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
data = self.classes_selector.classes_table._table_data
|
|
162
|
+
selected_classes = set(self.classes_selector.classes_table.get_selected_classes())
|
|
163
|
+
empty = set(r[0]["data"] for r in data if r[2]["data"] == 0 and r[3]["data"] == 0)
|
|
164
|
+
need_convert = set(r[0]["data"] for r in data if _need_convert(r[1]["data"]))
|
|
165
|
+
|
|
166
|
+
if need_convert.intersection(selected_classes - empty):
|
|
167
|
+
self.hyperparameters_selector.model_benchmark_auto_convert_warning.show()
|
|
168
|
+
self.need_convert_shapes_for_bm = True
|
|
169
|
+
else:
|
|
170
|
+
self.hyperparameters_selector.model_benchmark_auto_convert_warning.hide()
|
|
171
|
+
self.need_convert_shapes_for_bm = False
|
|
162
172
|
|
|
163
173
|
# ------------------------------------------------- #
|
|
164
174
|
|
|
@@ -482,7 +482,6 @@ class TrainApp:
|
|
|
482
482
|
downloading project and model data.
|
|
483
483
|
"""
|
|
484
484
|
logger.info("Preparing for training")
|
|
485
|
-
self.gui.disable_select_buttons()
|
|
486
485
|
|
|
487
486
|
# Step 1. Workflow Input
|
|
488
487
|
if is_production():
|
|
@@ -503,40 +502,40 @@ class TrainApp:
|
|
|
503
502
|
:type experiment_info: dict
|
|
504
503
|
"""
|
|
505
504
|
logger.info("Finalizing training")
|
|
505
|
+
# Step 1. Validate experiment TaskType
|
|
506
|
+
experiment_info = self._validate_experiment_task_type(experiment_info)
|
|
506
507
|
|
|
507
|
-
# Step
|
|
508
|
+
# Step 2. Validate experiment_info
|
|
508
509
|
success, reason = self._validate_experiment_info(experiment_info)
|
|
509
510
|
if not success:
|
|
510
511
|
raise ValueError(f"{reason}. Failed to upload artifacts")
|
|
511
512
|
|
|
512
|
-
# Step
|
|
513
|
+
# Step 3. Preprocess artifacts
|
|
513
514
|
experiment_info = self._preprocess_artifacts(experiment_info)
|
|
514
515
|
|
|
515
|
-
#
|
|
516
|
+
# Step 4. Postprocess splits
|
|
516
517
|
train_splits_data = self._postprocess_splits()
|
|
517
518
|
|
|
518
|
-
# Step
|
|
519
|
+
# Step 5. Upload artifacts
|
|
519
520
|
self._set_text_status("uploading")
|
|
520
521
|
remote_dir, file_info = self._upload_artifacts()
|
|
521
522
|
|
|
522
|
-
# Step
|
|
523
|
+
# Step 6. Create model meta according to model CV task type
|
|
523
524
|
model_meta = self.create_model_meta(experiment_info["task_type"])
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
{},
|
|
529
|
-
)
|
|
525
|
+
|
|
526
|
+
# Step 7. [Optional] Run Model Benchmark
|
|
527
|
+
mb_eval_lnk_file_info, mb_eval_report = None, None
|
|
528
|
+
mb_eval_report_id, eval_metrics = None, {}
|
|
530
529
|
if self.is_model_benchmark_enabled:
|
|
531
530
|
try:
|
|
532
531
|
# Convert GT project
|
|
532
|
+
gt_project_id, bm_splits_data = None, train_splits_data
|
|
533
533
|
if self._app_options.get("auto_convert_classes", True):
|
|
534
|
-
self.
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
gt_project_id, bm_splits_data = None, train_splits_data
|
|
534
|
+
if self.gui.need_convert_shapes_for_bm:
|
|
535
|
+
self._set_text_status("convert_gt_project")
|
|
536
|
+
gt_project_id, bm_splits_data = self._convert_and_split_gt_project(
|
|
537
|
+
experiment_info["task_type"]
|
|
538
|
+
)
|
|
540
539
|
|
|
541
540
|
self._set_text_status("benchmark")
|
|
542
541
|
(
|
|
@@ -555,7 +554,7 @@ class TrainApp:
|
|
|
555
554
|
except Exception as e:
|
|
556
555
|
logger.error(f"Model benchmark failed: {e}")
|
|
557
556
|
|
|
558
|
-
# Step
|
|
557
|
+
# Step 8. [Optional] Convert weights
|
|
559
558
|
export_weights = {}
|
|
560
559
|
if self.gui.hyperparameters_selector.is_export_required():
|
|
561
560
|
try:
|
|
@@ -564,7 +563,7 @@ class TrainApp:
|
|
|
564
563
|
except Exception as e:
|
|
565
564
|
logger.error(f"Export weights failed: {e}")
|
|
566
565
|
|
|
567
|
-
# Step
|
|
566
|
+
# Step 9. Generate and upload additional files
|
|
568
567
|
self._set_text_status("metadata")
|
|
569
568
|
self._generate_experiment_info(
|
|
570
569
|
remote_dir, experiment_info, eval_metrics, mb_eval_report_id, export_weights
|
|
@@ -575,12 +574,12 @@ class TrainApp:
|
|
|
575
574
|
self._generate_model_meta(remote_dir, model_meta)
|
|
576
575
|
self._upload_demo_files(remote_dir)
|
|
577
576
|
|
|
578
|
-
# Step
|
|
577
|
+
# Step 10. Set output widgets
|
|
579
578
|
self._set_text_status("reset")
|
|
580
579
|
self._set_training_output(remote_dir, file_info, mb_eval_report)
|
|
581
580
|
self._set_ws_progress_status("completed")
|
|
582
581
|
|
|
583
|
-
# Step
|
|
582
|
+
# Step 11. Workflow output
|
|
584
583
|
if is_production():
|
|
585
584
|
self._workflow_output(remote_dir, file_info, mb_eval_lnk_file_info, mb_eval_report_id)
|
|
586
585
|
|
|
@@ -1120,6 +1119,24 @@ class TrainApp:
|
|
|
1120
1119
|
# ----------------------------------------- #
|
|
1121
1120
|
|
|
1122
1121
|
# Postprocess
|
|
1122
|
+
def _validate_experiment_task_type(self, experiment_info: dict) -> dict:
|
|
1123
|
+
"""
|
|
1124
|
+
Checks if the task_type key if returned from the user's training function.
|
|
1125
|
+
If not, it will be set to the task type of the model selected in the model selector.
|
|
1126
|
+
|
|
1127
|
+
:param experiment_info: Information about the experiment results.
|
|
1128
|
+
:type experiment_info: dict
|
|
1129
|
+
:return: Experiment info with task_type key.
|
|
1130
|
+
:rtype: dict
|
|
1131
|
+
"""
|
|
1132
|
+
task_type = experiment_info.get("task_type", None)
|
|
1133
|
+
if task_type is None:
|
|
1134
|
+
logger.debug(
|
|
1135
|
+
"Task type not found in experiment_info. Task type from model config will be used."
|
|
1136
|
+
)
|
|
1137
|
+
task_type = self.gui.model_selector.get_selected_task_type()
|
|
1138
|
+
experiment_info["task_type"] = task_type
|
|
1139
|
+
return experiment_info
|
|
1123
1140
|
|
|
1124
1141
|
def _validate_experiment_info(self, experiment_info: dict) -> tuple:
|
|
1125
1142
|
"""
|
|
@@ -2218,6 +2235,7 @@ class TrainApp:
|
|
|
2218
2235
|
Wrapper function to wrap the training process.
|
|
2219
2236
|
"""
|
|
2220
2237
|
experiment_info = None
|
|
2238
|
+
check_logs_text = "Please check the logs for more details."
|
|
2221
2239
|
|
|
2222
2240
|
try:
|
|
2223
2241
|
self._set_train_widgets_state_on_start()
|
|
@@ -2226,7 +2244,7 @@ class TrainApp:
|
|
|
2226
2244
|
self._prepare_working_dir()
|
|
2227
2245
|
self._init_logger()
|
|
2228
2246
|
except Exception as e:
|
|
2229
|
-
message = "Error occurred during training initialization.
|
|
2247
|
+
message = f"Error occurred during training initialization. {check_logs_text}"
|
|
2230
2248
|
self._show_error(message, e)
|
|
2231
2249
|
self._restore_train_widgets_state_on_error()
|
|
2232
2250
|
self._set_ws_progress_status("reset")
|
|
@@ -2237,9 +2255,7 @@ class TrainApp:
|
|
|
2237
2255
|
self._set_ws_progress_status("preparing")
|
|
2238
2256
|
self._prepare()
|
|
2239
2257
|
except Exception as e:
|
|
2240
|
-
message =
|
|
2241
|
-
"Error occurred during data preparation. Please check the logs for more details."
|
|
2242
|
-
)
|
|
2258
|
+
message = f"Error occurred during data preparation. {check_logs_text}"
|
|
2243
2259
|
self._show_error(message, e)
|
|
2244
2260
|
self._restore_train_widgets_state_on_error()
|
|
2245
2261
|
self._set_ws_progress_status("reset")
|
|
@@ -2250,8 +2266,18 @@ class TrainApp:
|
|
|
2250
2266
|
if self._app_options.get("train_logger", None) is None:
|
|
2251
2267
|
self._set_ws_progress_status("training")
|
|
2252
2268
|
experiment_info = self._train_func()
|
|
2269
|
+
except ZeroDivisionError as e:
|
|
2270
|
+
message = (
|
|
2271
|
+
"'ZeroDivisionError' occurred during training. "
|
|
2272
|
+
"The error was caused by an insufficient dataset size relative to the specified batch size in hyperparameters. "
|
|
2273
|
+
"Please check input data and hyperparameters."
|
|
2274
|
+
)
|
|
2275
|
+
self._show_error(message, e)
|
|
2276
|
+
self._restore_train_widgets_state_on_error()
|
|
2277
|
+
self._set_ws_progress_status("reset")
|
|
2278
|
+
return
|
|
2253
2279
|
except Exception as e:
|
|
2254
|
-
message = "Error occurred during training.
|
|
2280
|
+
message = f"Error occurred during training. {check_logs_text}"
|
|
2255
2281
|
self._show_error(message, e)
|
|
2256
2282
|
self._restore_train_widgets_state_on_error()
|
|
2257
2283
|
self._set_ws_progress_status("reset")
|
|
@@ -2263,7 +2289,7 @@ class TrainApp:
|
|
|
2263
2289
|
self._finalize(experiment_info)
|
|
2264
2290
|
self.gui.training_process.start_button.loading = False
|
|
2265
2291
|
except Exception as e:
|
|
2266
|
-
message = "Error occurred during finalizing and uploading training artifacts
|
|
2292
|
+
message = f"Error occurred during finalizing and uploading training artifacts. {check_logs_text}"
|
|
2267
2293
|
self._show_error(message, e)
|
|
2268
2294
|
self._restore_train_widgets_state_on_error()
|
|
2269
2295
|
self._set_ws_progress_status("reset")
|
|
@@ -2280,6 +2306,7 @@ class TrainApp:
|
|
|
2280
2306
|
self._restore_train_widgets_state_on_error()
|
|
2281
2307
|
|
|
2282
2308
|
def _set_train_widgets_state_on_start(self):
|
|
2309
|
+
self.gui.disable_select_buttons()
|
|
2283
2310
|
self.gui.training_artifacts.validator_text.hide()
|
|
2284
2311
|
self._validate_experiment_name()
|
|
2285
2312
|
self.gui.training_process.experiment_name_input.disable()
|
|
@@ -2305,6 +2332,7 @@ class TrainApp:
|
|
|
2305
2332
|
if self._app_options.get("device_selector", False):
|
|
2306
2333
|
self.gui.training_process.select_device._select.enable()
|
|
2307
2334
|
self.gui.training_process.select_device.enable()
|
|
2335
|
+
self.gui.enable_select_buttons()
|
|
2308
2336
|
|
|
2309
2337
|
def _validate_experiment_name(self) -> bool:
|
|
2310
2338
|
experiment_name = self.gui.training_process.get_experiment_name()
|
|
@@ -2475,7 +2503,7 @@ class TrainApp:
|
|
|
2475
2503
|
change_name_if_conflict=True,
|
|
2476
2504
|
)
|
|
2477
2505
|
|
|
2478
|
-
# 3. Upload gt project
|
|
2506
|
+
# 3. Upload converted gt project
|
|
2479
2507
|
project = Project("tmp_project", OpenMode.READ)
|
|
2480
2508
|
self._api.project.update_meta(gt_project_info.id, project.meta)
|
|
2481
2509
|
for dataset in project.datasets:
|
|
@@ -2491,6 +2519,7 @@ class TrainApp:
|
|
|
2491
2519
|
img_infos = self._api.image.copy_batch(ds_info.id, img_ids)
|
|
2492
2520
|
img_ids = [img_info.id for img_info in img_infos]
|
|
2493
2521
|
self._api.annotation.upload_anns(img_ids, anns)
|
|
2522
|
+
sly_fs.remove_dir(project.directory)
|
|
2494
2523
|
|
|
2495
2524
|
# 4. Match splits with original project
|
|
2496
2525
|
gt_split_data = self._postprocess_splits(gt_project_info.id)
|
|
@@ -968,10 +968,10 @@ supervisely/nn/tracker/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
|
|
|
968
968
|
supervisely/nn/tracker/utils/gmc.py,sha256=3JX8979H3NA-YHNaRQyj9Z-xb9qtyMittPEjGw8y2Jo,11557
|
|
969
969
|
supervisely/nn/tracker/utils/kalman_filter.py,sha256=eSFmCjM0mikHCAFvj-KCVzw-0Jxpoc3Cfc2NWEjJC1Q,17268
|
|
970
970
|
supervisely/nn/training/__init__.py,sha256=gY4PCykJ-42MWKsqb9kl-skemKa8yB6t_fb5kzqR66U,111
|
|
971
|
-
supervisely/nn/training/train_app.py,sha256=
|
|
971
|
+
supervisely/nn/training/train_app.py,sha256=PZ4zWMYRvOFj97vy2rOofCBYqnpkDtmouzFTjs9UyN4,101747
|
|
972
972
|
supervisely/nn/training/gui/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
|
|
973
973
|
supervisely/nn/training/gui/classes_selector.py,sha256=8UgzA4aogOAr1s42smwEcDbgaBj_i0JLhjwlZ9bFdIA,3772
|
|
974
|
-
supervisely/nn/training/gui/gui.py,sha256=
|
|
974
|
+
supervisely/nn/training/gui/gui.py,sha256=CnT_QhihrxdSHKybpI0pXhPLwCaXEana_qdn0DhXByg,25558
|
|
975
975
|
supervisely/nn/training/gui/hyperparameters_selector.py,sha256=UAXZYyhuUOY7d2ZKAx4R5Kz-KQaiFZ7AnY8BDoj3_30,7071
|
|
976
976
|
supervisely/nn/training/gui/input_selector.py,sha256=Jp9PnVVADv1fhndPuZdMlKuzWTOBQZogrOks5dwATlc,2179
|
|
977
977
|
supervisely/nn/training/gui/model_selector.py,sha256=n2Xn6as60bNPtSlImJtyrVEo0gjKnvHLT3yq_m39TXk,4334
|
|
@@ -1070,9 +1070,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
1070
1070
|
supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
|
|
1071
1071
|
supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
|
|
1072
1072
|
supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
|
|
1073
|
-
supervisely-6.73.
|
|
1074
|
-
supervisely-6.73.
|
|
1075
|
-
supervisely-6.73.
|
|
1076
|
-
supervisely-6.73.
|
|
1077
|
-
supervisely-6.73.
|
|
1078
|
-
supervisely-6.73.
|
|
1073
|
+
supervisely-6.73.280.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
1074
|
+
supervisely-6.73.280.dist-info/METADATA,sha256=xY-ujb2oWVk6XMCZER18NgoGnfZYef8Lt6UAzVtDvkI,33573
|
|
1075
|
+
supervisely-6.73.280.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
1076
|
+
supervisely-6.73.280.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
|
|
1077
|
+
supervisely-6.73.280.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
|
|
1078
|
+
supervisely-6.73.280.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|