supervisely 6.73.390__py3-none-any.whl → 6.73.392__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.
- supervisely/app/widgets/experiment_selector/experiment_selector.py +21 -3
- supervisely/app/widgets/experiment_selector/template.html +49 -70
- supervisely/app/widgets/report_thumbnail/report_thumbnail.py +19 -4
- supervisely/decorators/profile.py +20 -0
- supervisely/nn/benchmark/utils/detection/utlis.py +7 -0
- supervisely/nn/experiments.py +4 -0
- supervisely/nn/inference/gui/serving_gui_template.py +71 -11
- supervisely/nn/inference/inference.py +108 -6
- supervisely/nn/training/gui/classes_selector.py +246 -27
- supervisely/nn/training/gui/gui.py +318 -234
- supervisely/nn/training/gui/hyperparameters_selector.py +2 -2
- supervisely/nn/training/gui/model_selector.py +42 -1
- supervisely/nn/training/gui/tags_selector.py +1 -1
- supervisely/nn/training/gui/train_val_splits_selector.py +8 -7
- supervisely/nn/training/gui/training_artifacts.py +10 -1
- supervisely/nn/training/gui/training_process.py +17 -1
- supervisely/nn/training/train_app.py +227 -72
- supervisely/template/__init__.py +2 -0
- supervisely/template/base_generator.py +90 -0
- supervisely/template/experiment/__init__.py +0 -0
- supervisely/template/experiment/experiment.html.jinja +537 -0
- supervisely/template/experiment/experiment_generator.py +996 -0
- supervisely/template/experiment/header.html.jinja +154 -0
- supervisely/template/experiment/sidebar.html.jinja +240 -0
- supervisely/template/experiment/sly-style.css +397 -0
- supervisely/template/experiment/template.html.jinja +18 -0
- supervisely/template/extensions.py +172 -0
- supervisely/template/template_renderer.py +253 -0
- {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/METADATA +3 -1
- {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/RECORD +34 -23
- {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/LICENSE +0 -0
- {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/WHEEL +0 -0
- {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/top_level.txt +0 -0
|
@@ -14,7 +14,7 @@ from supervisely.app.widgets import (
|
|
|
14
14
|
class HyperparametersSelector:
|
|
15
15
|
title = "Hyperparameters"
|
|
16
16
|
description = "Set hyperparameters for training"
|
|
17
|
-
lock_message = "Select
|
|
17
|
+
lock_message = "Select previous step to unlock"
|
|
18
18
|
|
|
19
19
|
def __init__(self, hyperparameters: dict, app_options: dict = {}):
|
|
20
20
|
# Init widgets
|
|
@@ -60,7 +60,7 @@ class HyperparametersSelector:
|
|
|
60
60
|
f"Learn more about Model Benchmark in the {docs_link}.", status="info"
|
|
61
61
|
)
|
|
62
62
|
self.model_benchmark_auto_convert_warning = Text(
|
|
63
|
-
text="Project will be automatically converted according to CV task for Model Evaluation.",
|
|
63
|
+
text="Project will be automatically converted according to CV task and uploaded for Model Evaluation.",
|
|
64
64
|
status="warning",
|
|
65
65
|
)
|
|
66
66
|
self.model_benchmark_auto_convert_warning.hide()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Literal
|
|
2
2
|
|
|
3
3
|
import supervisely.io.env as sly_env
|
|
4
|
+
import supervisely.io.fs as sly_fs
|
|
4
5
|
from supervisely import logger
|
|
5
6
|
from supervisely.api.api import Api
|
|
6
7
|
from supervisely.app.widgets import (
|
|
@@ -15,12 +16,13 @@ from supervisely.app.widgets import (
|
|
|
15
16
|
from supervisely.nn.artifacts.utils import FrameworkMapper
|
|
16
17
|
from supervisely.nn.experiments import get_experiment_infos
|
|
17
18
|
from supervisely.nn.utils import ModelSource, _get_model_name
|
|
19
|
+
from supervisely._utils import get_filename_from_headers
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
class ModelSelector:
|
|
21
23
|
title = "Select Model"
|
|
22
24
|
description = "Select a model for training"
|
|
23
|
-
lock_message = "Select
|
|
25
|
+
lock_message = "Select previous step to unlock"
|
|
24
26
|
|
|
25
27
|
def __init__(self, api: Api, framework: str, models: list, app_options: dict = {}):
|
|
26
28
|
# Init widgets
|
|
@@ -125,6 +127,45 @@ class ModelSelector:
|
|
|
125
127
|
else:
|
|
126
128
|
return self.experiment_selector.get_selected_experiment_info()
|
|
127
129
|
|
|
130
|
+
def get_checkpoint_name(self) -> str:
|
|
131
|
+
if self.get_model_source() == ModelSource.PRETRAINED:
|
|
132
|
+
selected_row = self.pretrained_models_table.get_selected_row()
|
|
133
|
+
meta = selected_row.get("meta", None)
|
|
134
|
+
if meta is not None:
|
|
135
|
+
model_files = meta.get("model_files", None)
|
|
136
|
+
if model_files is not None:
|
|
137
|
+
checkpoint_name = model_files.get("checkpoint", None)
|
|
138
|
+
if checkpoint_name is not None:
|
|
139
|
+
is_url = sly_fs.str_is_url(checkpoint_name)
|
|
140
|
+
if (not is_url) or checkpoint_name.lower().endswith((".pth", ".pt")):
|
|
141
|
+
checkpoint_name = sly_fs.get_file_name_with_ext(checkpoint_name)
|
|
142
|
+
else:
|
|
143
|
+
checkpoint_name = get_filename_from_headers(checkpoint_name)
|
|
144
|
+
return checkpoint_name
|
|
145
|
+
return None
|
|
146
|
+
else:
|
|
147
|
+
checkpoint_name = self.experiment_selector.get_selected_checkpoint_name()
|
|
148
|
+
return checkpoint_name
|
|
149
|
+
|
|
150
|
+
def get_checkpoint_link(self) -> str:
|
|
151
|
+
if self.get_model_source() == ModelSource.PRETRAINED:
|
|
152
|
+
selected_row = self.pretrained_models_table.get_selected_row()
|
|
153
|
+
meta = selected_row.get("meta", None)
|
|
154
|
+
if meta is not None:
|
|
155
|
+
model_files = meta.get("model_files", None)
|
|
156
|
+
if model_files is not None:
|
|
157
|
+
checkpoint_link = model_files.get("checkpoint", None)
|
|
158
|
+
if checkpoint_link is not None:
|
|
159
|
+
is_url = sly_fs.str_is_url(checkpoint_link)
|
|
160
|
+
if checkpoint_link.startswith("/experiments/"):
|
|
161
|
+
is_url = True
|
|
162
|
+
if is_url:
|
|
163
|
+
return checkpoint_link
|
|
164
|
+
return None
|
|
165
|
+
else:
|
|
166
|
+
checkpoint_link = self.experiment_selector.get_selected_checkpoint_path()
|
|
167
|
+
return checkpoint_link
|
|
168
|
+
|
|
128
169
|
def validate_step(self) -> bool:
|
|
129
170
|
self.validator_text.hide()
|
|
130
171
|
model_info = self.get_model_info()
|
|
@@ -5,7 +5,7 @@ from supervisely.app.widgets import Button, Card, Container, TagsTable, Text
|
|
|
5
5
|
class TagsSelector:
|
|
6
6
|
title = "Tags Selector"
|
|
7
7
|
description = "Select tags that will be used for training"
|
|
8
|
-
lock_message = "Select
|
|
8
|
+
lock_message = "Select previous step to unlock"
|
|
9
9
|
|
|
10
10
|
def __init__(self, project_id: int, tags: list, app_options: dict = {}):
|
|
11
11
|
# Init widgets
|
|
@@ -2,12 +2,12 @@ from typing import List
|
|
|
2
2
|
|
|
3
3
|
from supervisely import Api, Project
|
|
4
4
|
from supervisely.app.widgets import Button, Card, Container, Text, TrainValSplits
|
|
5
|
-
|
|
5
|
+
from supervisely.api.module_api import ApiField
|
|
6
6
|
|
|
7
7
|
class TrainValSplitsSelector:
|
|
8
8
|
title = "Train / Val Splits"
|
|
9
9
|
description = "Select train and val splits for training"
|
|
10
|
-
lock_message = "Select
|
|
10
|
+
lock_message = "Select previous step to unlock"
|
|
11
11
|
|
|
12
12
|
def __init__(self, api: Api, project_id: int, app_options: dict = {}):
|
|
13
13
|
# Init widgets
|
|
@@ -222,12 +222,13 @@ class TrainValSplitsSelector:
|
|
|
222
222
|
return False
|
|
223
223
|
|
|
224
224
|
# Check if datasets are not empty
|
|
225
|
-
|
|
225
|
+
filters = [{ ApiField.FIELD: ApiField.ID, ApiField.OPERATOR: "in", ApiField.VALUE: train_dataset_id + val_dataset_id}]
|
|
226
|
+
selected_datasets = self.api.dataset.get_list(self.project_id, filters, recursive=True)
|
|
226
227
|
datasets_count = {}
|
|
227
|
-
for dataset in
|
|
228
|
-
datasets_count[dataset
|
|
229
|
-
"name": dataset
|
|
230
|
-
"total": dataset
|
|
228
|
+
for dataset in selected_datasets:
|
|
229
|
+
datasets_count[dataset.id] = {
|
|
230
|
+
"name": dataset.name,
|
|
231
|
+
"total": dataset.images_count,
|
|
231
232
|
}
|
|
232
233
|
|
|
233
234
|
empty_dataset_names = []
|
|
@@ -64,7 +64,16 @@ class TrainingArtifacts:
|
|
|
64
64
|
self.display_widgets.extend([self.validator_text])
|
|
65
65
|
|
|
66
66
|
# Outputs
|
|
67
|
-
|
|
67
|
+
need_generate_report = self.app_options.get("generate_report", True)
|
|
68
|
+
if need_generate_report:
|
|
69
|
+
self.artifacts_thumbnail = ReportThumbnail(
|
|
70
|
+
title="Experiment Report",
|
|
71
|
+
color="#5fa8ff",
|
|
72
|
+
bg_color="#e6f3ff",
|
|
73
|
+
report_type="experiment",
|
|
74
|
+
)
|
|
75
|
+
else:
|
|
76
|
+
self.artifacts_thumbnail = FolderThumbnail()
|
|
68
77
|
self.artifacts_thumbnail.hide()
|
|
69
78
|
|
|
70
79
|
self.artifacts_field = Field(
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
from typing import Any, Dict
|
|
2
2
|
|
|
3
|
+
# Safe optional import for torch to prevent pylint import-error when the library is absent.
|
|
4
|
+
try:
|
|
5
|
+
import torch # type: ignore
|
|
6
|
+
except ImportError: # pragma: no cover
|
|
7
|
+
torch = None # type: ignore
|
|
8
|
+
|
|
3
9
|
from supervisely.app.widgets import (
|
|
4
10
|
Button,
|
|
5
11
|
Card,
|
|
@@ -15,7 +21,7 @@ from supervisely.app.widgets import (
|
|
|
15
21
|
class TrainingProcess:
|
|
16
22
|
title = "Training Process"
|
|
17
23
|
description = "Manage training process"
|
|
18
|
-
lock_message = "Select
|
|
24
|
+
lock_message = "Select previous step to unlock"
|
|
19
25
|
|
|
20
26
|
def __init__(self, app_options: Dict[str, Any]):
|
|
21
27
|
# Initialize widgets to None
|
|
@@ -93,6 +99,16 @@ class TrainingProcess:
|
|
|
93
99
|
else:
|
|
94
100
|
return "cuda:0"
|
|
95
101
|
|
|
102
|
+
def get_device_name(self) -> str:
|
|
103
|
+
device = self.get_device()
|
|
104
|
+
|
|
105
|
+
if torch is not None and device.startswith("cuda"):
|
|
106
|
+
device_name = torch.cuda.get_device_name(device)
|
|
107
|
+
else:
|
|
108
|
+
device_name = "CPU"
|
|
109
|
+
|
|
110
|
+
return device_name
|
|
111
|
+
|
|
96
112
|
def get_experiment_name(self) -> str:
|
|
97
113
|
return self.experiment_name_input.get_value()
|
|
98
114
|
|