code-loader 1.0.41__py3-none-any.whl → 1.0.42a0__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.
- code_loader/contract/datasetclasses.py +38 -1
- code_loader/contract/enums.py +6 -0
- code_loader/contract/responsedataclasses.py +13 -1
- code_loader/contract/visualizer_classes.py +70 -0
- code_loader/inner_leap_binder/leapbinder.py +238 -3
- code_loader/leaploader.py +17 -17
- {code_loader-1.0.41.dist-info → code_loader-1.0.42a0.dist-info}/METADATA +1 -1
- code_loader-1.0.42a0.dist-info/RECORD +18 -0
- code_loader-1.0.41.dist-info/RECORD +0 -18
- {code_loader-1.0.41.dist-info → code_loader-1.0.42a0.dist-info}/LICENSE +0 -0
- {code_loader-1.0.41.dist-info → code_loader-1.0.42a0.dist-info}/WHEEL +0 -0
@@ -4,7 +4,7 @@ from typing import Any, Callable, List, Optional, Dict, Union, Type
|
|
4
4
|
import numpy as np
|
5
5
|
import numpy.typing as npt
|
6
6
|
|
7
|
-
from code_loader.contract.enums import DataStateType, DataStateEnum, LeapDataType, ConfusionMatrixValue, MetricDirection
|
7
|
+
from code_loader.contract.enums import DataStateType, DataStateEnum, LeapDataType, ConfusionMatrixValue, MetricDirection, InstanceAnalysisType
|
8
8
|
from code_loader.contract.visualizer_classes import LeapImage, LeapText, LeapGraph, LeapHorizontalBar, \
|
9
9
|
LeapTextMask, LeapImageMask, LeapImageWithBBox, LeapImageWithHeatmap
|
10
10
|
|
@@ -13,12 +13,39 @@ custom_latent_space_attribute = "custom_latent_space"
|
|
13
13
|
|
14
14
|
@dataclass
|
15
15
|
class PreprocessResponse:
|
16
|
+
"""
|
17
|
+
An object that holds the preprocessed data for use within the Tensorleap platform.
|
18
|
+
|
19
|
+
This class is used to encapsulate the results of data preprocessing, including inputs, metadata, labels, and other relevant information.
|
20
|
+
It facilitates handling and integration of the processed data within Tensorleap.
|
21
|
+
|
22
|
+
Attributes:
|
23
|
+
length (int): The length of the preprocessed data.
|
24
|
+
data (Any): The preprocessed data itself. This can be any data type depending on the preprocessing logic.
|
25
|
+
|
26
|
+
Example:
|
27
|
+
# Example usage of PreprocessResponse
|
28
|
+
preprocessed_data = {
|
29
|
+
'images': ['path/to/image1.jpg', 'path/to/image2.jpg'],
|
30
|
+
'labels': ['SUV', 'truck'],
|
31
|
+
'metadata': [{'id': 1, 'source': 'camera1'}, {'id': 2, 'source': 'camera2'}]
|
32
|
+
}
|
33
|
+
response = PreprocessResponse(length=len(preprocessed_data), data=preprocessed_data)
|
34
|
+
"""
|
16
35
|
length: int
|
17
36
|
data: Any
|
18
37
|
|
19
38
|
|
39
|
+
@dataclass
|
40
|
+
class ElementInstance:
|
41
|
+
name: str
|
42
|
+
mask: npt.NDArray[np.float32]
|
43
|
+
|
44
|
+
|
20
45
|
SectionCallableInterface = Callable[[int, PreprocessResponse], npt.NDArray[np.float32]]
|
21
46
|
|
47
|
+
InstanceCallableInterface = Callable[[int, PreprocessResponse], List[ElementInstance]]
|
48
|
+
|
22
49
|
MetadataSectionCallableInterface = Union[
|
23
50
|
Callable[[int, PreprocessResponse], int],
|
24
51
|
Callable[[int, PreprocessResponse], Dict[str, int]],
|
@@ -90,6 +117,7 @@ class MetricHandler:
|
|
90
117
|
arg_names: List[str]
|
91
118
|
direction: Optional[MetricDirection] = MetricDirection.Downward
|
92
119
|
|
120
|
+
|
93
121
|
@dataclass
|
94
122
|
class RawInputsForHeatmap:
|
95
123
|
raw_input_by_vizualizer_arg_name: Dict[str, npt.NDArray[np.float32]]
|
@@ -115,6 +143,14 @@ class InputHandler(DatasetBaseHandler):
|
|
115
143
|
shape: Optional[List[int]] = None
|
116
144
|
|
117
145
|
|
146
|
+
@dataclass
|
147
|
+
class ElementInstanceHandler:
|
148
|
+
input_name: str
|
149
|
+
instance_function: InstanceCallableInterface
|
150
|
+
analysis_type: InstanceAnalysisType
|
151
|
+
|
152
|
+
|
153
|
+
|
118
154
|
@dataclass
|
119
155
|
class GroundTruthHandler(DatasetBaseHandler):
|
120
156
|
shape: Optional[List[int]] = None
|
@@ -148,6 +184,7 @@ class DatasetIntegrationSetup:
|
|
148
184
|
unlabeled_data_preprocess: Optional[UnlabeledDataPreprocessHandler] = None
|
149
185
|
visualizers: List[VisualizerHandler] = field(default_factory=list)
|
150
186
|
inputs: List[InputHandler] = field(default_factory=list)
|
187
|
+
element_instances: List[ElementInstanceHandler] = field(default_factory=list)
|
151
188
|
ground_truths: List[GroundTruthHandler] = field(default_factory=list)
|
152
189
|
metadata: List[MetadataHandler] = field(default_factory=list)
|
153
190
|
prediction_types: List[PredictionTypeHandler] = field(default_factory=list)
|
code_loader/contract/enums.py
CHANGED
@@ -95,7 +95,19 @@ class DatasetTestResultPayload:
|
|
95
95
|
|
96
96
|
@dataclass
|
97
97
|
class BoundingBox:
|
98
|
-
|
98
|
+
"""
|
99
|
+
Represents a bounding box for an object in an image.
|
100
|
+
|
101
|
+
Attributes:
|
102
|
+
x (float): The x-coordinate of the center of the bounding box, a value between [0, 1] representing the percentage according to the image width.
|
103
|
+
y (float): The y-coordinate of the center of the bounding box, a value between [0, 1] representing the percentage according to the image height.
|
104
|
+
width (float): The width of the bounding box, a value between [0, 1] representing the percentage according to the image width.
|
105
|
+
height (float): The height of the bounding box, a value between [0, 1] representing the percentage according to the image height.
|
106
|
+
confidence (float): The confidence score of the bounding box. For predictions, this is a score typically between [0, 1]. For ground truth data, this can be 1.
|
107
|
+
label (str): The label or class name associated with the bounding box.
|
108
|
+
rotation (float): The rotation of the bounding box, a value between [0, 360] representing the degree of rotation. Default is 0.0.
|
109
|
+
metadata (Optional[Dict[str, Union[str, int, float]]]): Optional metadata associated with the bounding box.
|
110
|
+
"""
|
99
111
|
x: float # value between [0, 1], represent the percentage according to the image size.
|
100
112
|
y: float # value between [0, 1], represent the percentage according to the image size.
|
101
113
|
|
@@ -28,6 +28,13 @@ def validate_type(actual: Any, expected: Any, prefix_message: str = '') -> None:
|
|
28
28
|
|
29
29
|
@dataclass
|
30
30
|
class LeapImage:
|
31
|
+
"""
|
32
|
+
Visualizer representing an image for Tensorleap.
|
33
|
+
|
34
|
+
Attributes:
|
35
|
+
data (npt.NDArray[np.float32] | npt.NDArray[np.uint8]): The image data.
|
36
|
+
type (LeapDataType): The data type, default is LeapDataType.Image.
|
37
|
+
"""
|
31
38
|
data: Union[npt.NDArray[np.float32], npt.NDArray[np.uint8]]
|
32
39
|
type: LeapDataType = LeapDataType.Image
|
33
40
|
|
@@ -41,6 +48,14 @@ class LeapImage:
|
|
41
48
|
|
42
49
|
@dataclass
|
43
50
|
class LeapImageWithBBox:
|
51
|
+
"""
|
52
|
+
Visualizer representing an image with bounding boxes for Tensorleap, used for object detection tasks.
|
53
|
+
|
54
|
+
Attributes:
|
55
|
+
data (npt.NDArray[np.float32] | npt.NDArray[np.uint8]): The image data, shaped [H, W, 3] or [H, W, 1].
|
56
|
+
bounding_boxes (List[BoundingBox]): List of Tensorleap bounding boxes objects in relative size to image size.
|
57
|
+
type (LeapDataType): The data type, default is LeapDataType.ImageWithBBox.
|
58
|
+
"""
|
44
59
|
data: Union[npt.NDArray[np.float32], npt.NDArray[np.uint8]]
|
45
60
|
bounding_boxes: List[BoundingBox]
|
46
61
|
type: LeapDataType = LeapDataType.ImageWithBBox
|
@@ -55,6 +70,13 @@ class LeapImageWithBBox:
|
|
55
70
|
|
56
71
|
@dataclass
|
57
72
|
class LeapGraph:
|
73
|
+
"""
|
74
|
+
Visualizer representing a line chart data for Tensorleap.
|
75
|
+
|
76
|
+
Attributes:
|
77
|
+
data (npt.NDArray[np.float32]): The array data, shaped [M, N] where M is the number of data points and N is the number of variables.
|
78
|
+
type (LeapDataType): The data type, default is LeapDataType.Graph.
|
79
|
+
"""
|
58
80
|
data: npt.NDArray[np.float32]
|
59
81
|
type: LeapDataType = LeapDataType.Graph
|
60
82
|
|
@@ -67,6 +89,14 @@ class LeapGraph:
|
|
67
89
|
|
68
90
|
@dataclass
|
69
91
|
class LeapText:
|
92
|
+
"""
|
93
|
+
Visualizer representing text data for Tensorleap.
|
94
|
+
|
95
|
+
Attributes:
|
96
|
+
data (List[str]): The text data, consisting of a list of text tokens. If the model requires fixed-length inputs,
|
97
|
+
it is recommended to maintain the fixed length, using empty strings ('') instead of padding tokens ('PAD') e.g., ['I', 'ate', 'a', 'banana', '', '', '', ...]
|
98
|
+
type (LeapDataType): The data type, default is LeapDataType.Text.
|
99
|
+
"""
|
70
100
|
data: List[str]
|
71
101
|
type: LeapDataType = LeapDataType.Text
|
72
102
|
|
@@ -79,6 +109,16 @@ class LeapText:
|
|
79
109
|
|
80
110
|
@dataclass
|
81
111
|
class LeapHorizontalBar:
|
112
|
+
"""
|
113
|
+
Visualizer representing horizontal bar data for Tensorleap.
|
114
|
+
For example, this can be used to visualize the model's prediction scores in a classification problem.
|
115
|
+
|
116
|
+
Attributes:
|
117
|
+
body (npt.NDArray[np.float32]): The data for the bar, shaped [C], where C is the number of data points.
|
118
|
+
labels (List[str]): Labels for the horizontal bar; e.g., when visualizing the model's classification output, labels are the class names.
|
119
|
+
Length of `body` should match the length of `labels`, C.
|
120
|
+
type (LeapDataType): The data type, default is LeapDataType.HorizontalBar.
|
121
|
+
"""
|
82
122
|
body: npt.NDArray[np.float32]
|
83
123
|
labels: List[str]
|
84
124
|
type: LeapDataType = LeapDataType.HorizontalBar
|
@@ -96,6 +136,16 @@ class LeapHorizontalBar:
|
|
96
136
|
|
97
137
|
@dataclass
|
98
138
|
class LeapImageMask:
|
139
|
+
"""
|
140
|
+
Visualizer representing an image with a mask for Tensorleap.
|
141
|
+
This can be used for tasks such as segmentation, and other applications where it is important to highlight specific regions within an image.
|
142
|
+
|
143
|
+
Attributes:
|
144
|
+
mask (npt.NDArray[np.uint8]): The mask data, shaped [H, W].
|
145
|
+
image (npt.NDArray[np.float32] | npt.NDArray[np.uint8]): The image data, shaped [H, W, 3] or shaped [H, W, 1].
|
146
|
+
labels (List[str]): Labels associated with the mask regions; e.g., class names for segmented objects. The length of `labels` should match the number of unique values in `mask`.
|
147
|
+
type (LeapDataType): The data type, default is LeapDataType.ImageMask.
|
148
|
+
"""
|
99
149
|
mask: npt.NDArray[np.uint8]
|
100
150
|
image: Union[npt.NDArray[np.float32], npt.NDArray[np.uint8]]
|
101
151
|
labels: List[str]
|
@@ -117,6 +167,16 @@ class LeapImageMask:
|
|
117
167
|
|
118
168
|
@dataclass
|
119
169
|
class LeapTextMask:
|
170
|
+
"""
|
171
|
+
Visualizer representing text data with a mask for Tensorleap.
|
172
|
+
This can be used for tasks such as named entity recognition (NER), sentiment analysis, and other applications where it is important to highlight specific tokens or parts of the text.
|
173
|
+
|
174
|
+
Attributes:
|
175
|
+
mask (npt.NDArray[np.uint8]): The mask data, shaped [L].
|
176
|
+
text (List[str]): The text data, consisting of a list of text tokens, length of L.
|
177
|
+
labels (List[str]): Labels associated with the masked tokens; e.g., named entities or sentiment categories. The length of `labels` should match the number of unique values in `mask`.
|
178
|
+
type (LeapDataType): The data type, default is LeapDataType.TextMask.
|
179
|
+
"""
|
120
180
|
mask: npt.NDArray[np.uint8]
|
121
181
|
text: List[str]
|
122
182
|
labels: List[str]
|
@@ -137,6 +197,16 @@ class LeapTextMask:
|
|
137
197
|
|
138
198
|
@dataclass
|
139
199
|
class LeapImageWithHeatmap:
|
200
|
+
"""
|
201
|
+
Visualizer representing an image with heatmaps for Tensorleap.
|
202
|
+
This can be used for tasks such as highlighting important regions in an image, visualizing attention maps, and other applications where it is important to overlay heatmaps on images.
|
203
|
+
|
204
|
+
Attributes:
|
205
|
+
image (npt.NDArray[np.float32]): The image data, shaped [H, W, C], where C is the number of channels.
|
206
|
+
heatmaps (npt.NDArray[np.float32]): The heatmap data, shaped [N, H, W], where N is the number of heatmaps.
|
207
|
+
labels (List[str]): Labels associated with the heatmaps; e.g., feature names or attention regions. The length of `labels` should match the number of heatmaps, N.
|
208
|
+
type (LeapDataType): The data type, default is LeapDataType.ImageWithHeatmap.
|
209
|
+
"""
|
140
210
|
image: npt.NDArray[np.float32]
|
141
211
|
heatmaps: npt.NDArray[np.float32]
|
142
212
|
labels: List[str]
|
@@ -9,8 +9,9 @@ from code_loader.contract.datasetclasses import SectionCallableInterface, InputH
|
|
9
9
|
PreprocessHandler, VisualizerCallableInterface, CustomLossHandler, CustomCallableInterface, PredictionTypeHandler, \
|
10
10
|
MetadataSectionCallableInterface, UnlabeledDataPreprocessHandler, CustomLayerHandler, MetricHandler, \
|
11
11
|
CustomCallableInterfaceMultiArgs, ConfusionMatrixCallableInterfaceMultiArgs, VisualizerCallableReturnType, \
|
12
|
-
CustomMultipleReturnCallableInterfaceMultiArgs, DatasetBaseHandler, custom_latent_space_attribute,
|
13
|
-
|
12
|
+
CustomMultipleReturnCallableInterfaceMultiArgs, DatasetBaseHandler, custom_latent_space_attribute, \
|
13
|
+
RawInputsForHeatmap, InstanceCallableInterface, ElementInstanceHandler
|
14
|
+
from code_loader.contract.enums import LeapDataType, DataStateEnum, DataStateType, MetricDirection, InstanceAnalysisType
|
14
15
|
from code_loader.contract.responsedataclasses import DatasetTestResultPayload
|
15
16
|
from code_loader.contract.visualizer_classes import map_leap_data_type_to_visualizer_class
|
16
17
|
from code_loader.utils import to_numpy_return_wrapper, get_shape
|
@@ -21,6 +22,15 @@ from code_loader.visualizers.default_visualizers import DefaultVisualizer, \
|
|
21
22
|
|
22
23
|
|
23
24
|
class LeapBinder:
|
25
|
+
"""
|
26
|
+
Interface to the Tensorleap platform. Provides methods to set up preprocessing,
|
27
|
+
visualization, custom loss functions, metrics, and other essential components for integrating the dataset and model
|
28
|
+
with Tensorleap.
|
29
|
+
|
30
|
+
Attributes:
|
31
|
+
setup_container (DatasetIntegrationSetup): Container to hold setup configurations.
|
32
|
+
cache_container (Dict[str, Any]): Cache container to store intermediate data.
|
33
|
+
"""
|
24
34
|
def __init__(self) -> None:
|
25
35
|
self.setup_container = DatasetIntegrationSetup()
|
26
36
|
self.cache_container: Dict[str, Any] = {"word_to_index": {}}
|
@@ -48,6 +58,36 @@ class LeapBinder:
|
|
48
58
|
name: str,
|
49
59
|
visualizer_type: LeapDataType,
|
50
60
|
heatmap_visualizer: Optional[Callable[..., npt.NDArray[np.float32]]] = None) -> None:
|
61
|
+
"""
|
62
|
+
Set a visualizer for a specific data type.
|
63
|
+
|
64
|
+
Args:
|
65
|
+
function (VisualizerCallableInterface): The visualizer function to be used for visualizing the data.
|
66
|
+
name (str): The name of the visualizer.
|
67
|
+
visualizer_type (LeapDataType): The type of data the visualizer handles (e.g., LeapDataType.Image, LeapDataType.Graph, LeapDataType.Text).
|
68
|
+
heatmap_visualizer (Optional[Callable[..., npt.NDArray[np.float32]]]): An optional heatmap visualizer function.
|
69
|
+
This is used when a heatmap must be reshaped to overlay correctly on the transformed data within the visualizer
|
70
|
+
function i.e., if the visualizer changes the shape or scale of the input data, the heatmap visualizer
|
71
|
+
adjusts the heatmap accordingly to ensure it aligns properly with the visualized data.
|
72
|
+
|
73
|
+
Example:
|
74
|
+
def image_resize_visualizer(data: np.ndarray) -> LeapImage:
|
75
|
+
# Resize the image to a fixed size
|
76
|
+
resized_image = resize_image(data, (224, 224))
|
77
|
+
return LeapImage(data=resized_image)
|
78
|
+
|
79
|
+
def image_resize_heatmap_visualizer(heatmap: RawInputsForHeatmap) -> np.ndarray:
|
80
|
+
# Resize the heatmap to match the resized image
|
81
|
+
resized_heatmap = resize_heatmap(heatmap, (224, 224))
|
82
|
+
return resized_heatmap
|
83
|
+
|
84
|
+
leap_binder.set_visualizer(
|
85
|
+
function=image_resize_visualizer,
|
86
|
+
name='image_resize_visualizer',
|
87
|
+
visualizer_type=LeapDataType.Image,
|
88
|
+
heatmap_visualizer=image_resize_heatmap_visualizer
|
89
|
+
)
|
90
|
+
"""
|
51
91
|
arg_names = inspect.getfullargspec(function)[0]
|
52
92
|
if heatmap_visualizer:
|
53
93
|
visualizer_arg_names_set = set(arg_names)
|
@@ -90,18 +130,103 @@ class LeapBinder:
|
|
90
130
|
self._visualizer_names.append(name)
|
91
131
|
|
92
132
|
def set_preprocess(self, function: Callable[[], List[PreprocessResponse]]) -> None:
|
133
|
+
"""
|
134
|
+
Set the preprocessing function for the dataset. That is the function that returns a list of PreprocessResponse objects for use within the Tensorleap platform.
|
135
|
+
|
136
|
+
Args:
|
137
|
+
function (Callable[[], List[PreprocessResponse]]): The preprocessing function.
|
138
|
+
|
139
|
+
Example:
|
140
|
+
def preprocess_func() -> List[PreprocessResponse]:
|
141
|
+
# Preprocess the dataset
|
142
|
+
train_data = {
|
143
|
+
'subset': 'train',
|
144
|
+
'images': ['path/to/train/image1.jpg', 'path/to/train/image2.jpg'],
|
145
|
+
'labels': ['SUV', 'truck'],
|
146
|
+
'metadata': [{'id': 1, 'source': 'camera1'}, {'id': 2, 'source': 'camera2'}]}
|
147
|
+
|
148
|
+
val_data = {
|
149
|
+
'subset': 'val',
|
150
|
+
'images': ['path/to/val/image1.jpg', 'path/to/va;/image2.jpg'],
|
151
|
+
'labels': ['truck', 'truck'],
|
152
|
+
'metadata': [{'id': 1, 'source': 'camera1'}, {'id': 2, 'source': 'camera2'}]}
|
153
|
+
|
154
|
+
return [PreprocessResponse(length=len(train_data['images']), data=train_data),
|
155
|
+
PreprocessResponse(length=len(val_data['images']), data=val_data)]
|
156
|
+
|
157
|
+
leap_binder.set_preprocess(preprocess_func)
|
158
|
+
"""
|
93
159
|
self.setup_container.preprocess = PreprocessHandler(function)
|
94
160
|
|
95
161
|
def set_unlabeled_data_preprocess(self, function: Callable[[], PreprocessResponse]) -> None:
|
162
|
+
"""
|
163
|
+
Set the preprocessing function for unlabeled dataset. This function returns a PreprocessResponse object for use within the Tensorleap platform for sample data that does not contain labels.
|
164
|
+
|
165
|
+
Args:
|
166
|
+
function (Callable[[], PreprocessResponse]): The preprocessing function for unlabeled data.
|
167
|
+
|
168
|
+
Example:
|
169
|
+
def unlabeled_preprocess_func() -> List[PreprocessResponse]:
|
170
|
+
|
171
|
+
# Preprocess the dataset
|
172
|
+
ul_data = {
|
173
|
+
'subset': 'unlabeled',
|
174
|
+
'images': ['path/to/train/image1.jpg', 'path/to/train/image2.jpg'],
|
175
|
+
'metadata': [{'id': 1, 'source': 'camera1'}, {'id': 2, 'source': 'camera2'}]}
|
176
|
+
|
177
|
+
return [PreprocessResponse(length=len(train_data['images']), data=train_data)]
|
178
|
+
|
179
|
+
leap_binder.set_preprocess(unlabeled_preprocess_func)
|
180
|
+
"""
|
96
181
|
self.setup_container.unlabeled_data_preprocess = UnlabeledDataPreprocessHandler(function)
|
97
182
|
|
98
183
|
def set_input(self, function: SectionCallableInterface, name: str) -> None:
|
184
|
+
"""
|
185
|
+
Set the input handler function.
|
186
|
+
|
187
|
+
Args:
|
188
|
+
function (SectionCallableInterface): The input handler function.
|
189
|
+
name (str): The name of the input section.
|
190
|
+
|
191
|
+
Example:
|
192
|
+
def input_encoder(subset: PreprocessResponse, index: int) -> np.ndarray:
|
193
|
+
# Return the processed input data for the given index and given subset response
|
194
|
+
img_path = subset.`data["images"][idx]
|
195
|
+
img = read_img(img_path)
|
196
|
+
img = normalize(img)
|
197
|
+
return img
|
198
|
+
|
199
|
+
leap_binder.set_input(input_encoder, name='input_encoder')
|
200
|
+
"""
|
99
201
|
function = to_numpy_return_wrapper(function)
|
100
202
|
self.setup_container.inputs.append(InputHandler(name, function))
|
101
203
|
|
102
204
|
self._encoder_names.append(name)
|
103
205
|
|
206
|
+
def set_instance_element(self, input_name: str, instance_function: Optional[InstanceCallableInterface] = None,
|
207
|
+
analysis_type: InstanceAnalysisType = InstanceAnalysisType.MaskInput) -> None:
|
208
|
+
self.setup_container.element_instances.append(ElementInstanceHandler(input_name, instance_function, analysis_type))
|
209
|
+
|
104
210
|
def add_custom_loss(self, function: CustomCallableInterface, name: str) -> None:
|
211
|
+
"""
|
212
|
+
Add a custom loss function to the setup.
|
213
|
+
|
214
|
+
Args:
|
215
|
+
function (CustomCallableInterface): The custom loss function.
|
216
|
+
This function receives:
|
217
|
+
- y_true: The true labels or values.
|
218
|
+
- y_pred: The predicted labels or values.
|
219
|
+
This function should return:
|
220
|
+
- A numeric value representing the loss.
|
221
|
+
name (str): The name of the custom loss function.
|
222
|
+
|
223
|
+
Example:
|
224
|
+
def custom_loss_function(y_true, y_pred):
|
225
|
+
# Calculate mean squared error as custom loss
|
226
|
+
return np.mean(np.square(y_true - y_pred))
|
227
|
+
|
228
|
+
leap_binder.add_custom_loss(custom_loss_function, name='custom_loss')
|
229
|
+
"""
|
105
230
|
arg_names = inspect.getfullargspec(function)[0]
|
106
231
|
self.setup_container.custom_loss_handlers.append(CustomLossHandler(name, function, arg_names))
|
107
232
|
|
@@ -111,28 +236,138 @@ class LeapBinder:
|
|
111
236
|
ConfusionMatrixCallableInterfaceMultiArgs],
|
112
237
|
name: str,
|
113
238
|
direction: Optional[MetricDirection] = MetricDirection.Downward) -> None:
|
239
|
+
"""
|
240
|
+
Add a custom metric to the setup.
|
241
|
+
|
242
|
+
Args:
|
243
|
+
function (Union[CustomCallableInterfaceMultiArgs, CustomMultipleReturnCallableInterfaceMultiArgs, ConfusionMatrixCallableInterfaceMultiArgs]): The custom metric function.
|
244
|
+
name (str): The name of the custom metric.
|
245
|
+
direction (Optional[MetricDirection]): The direction of the metric, either MetricDirection.Upward or MetricDirection.Downward.
|
246
|
+
- MetricDirection.Upward: Indicates that higher values of the metric are better and should be maximized.
|
247
|
+
- MetricDirection.Downward: Indicates that lower values of the metric are better and should be minimized.
|
248
|
+
|
249
|
+
|
250
|
+
Example:
|
251
|
+
def custom_metric_function(y_true, y_pred):
|
252
|
+
return np.mean(np.abs(y_true - y_pred))
|
253
|
+
|
254
|
+
leap_binder.add_custom_metric(custom_metric_function, name='custom_metric', direction=MetricDirection.Downward)
|
255
|
+
"""
|
114
256
|
arg_names = inspect.getfullargspec(function)[0]
|
115
257
|
self.setup_container.metrics.append(MetricHandler(name, function, arg_names, direction))
|
116
258
|
|
117
259
|
def add_prediction(self, name: str, labels: List[str], channel_dim: int = -1) -> None:
|
260
|
+
"""
|
261
|
+
Add prediction labels to the setup.
|
262
|
+
|
263
|
+
Args:
|
264
|
+
name (str): The name of the prediction.
|
265
|
+
labels (List[str]): The list of labels for the prediction.
|
266
|
+
channel_dim (int): The axis along which the prediction scores are located, default is -1.
|
267
|
+
|
268
|
+
Must satisfy len(labels) == len(output[channel_dim]).
|
269
|
+
|
270
|
+
Example:
|
271
|
+
leap_binder.add_prediction(name='class_labels', labels=['cat', 'dog'])
|
272
|
+
"""
|
118
273
|
self.setup_container.prediction_types.append(PredictionTypeHandler(name, labels, channel_dim))
|
119
274
|
|
120
275
|
def set_ground_truth(self, function: SectionCallableInterface, name: str) -> None:
|
276
|
+
"""
|
277
|
+
Set the ground truth handler function.
|
278
|
+
|
279
|
+
Args:
|
280
|
+
function: The ground truth handler function.
|
281
|
+
This function receives two parameters:
|
282
|
+
- subset: A `PreprocessResponse` object that contains the preprocessed data.
|
283
|
+
- index: The index of the sample within the subset.
|
284
|
+
This function should return:
|
285
|
+
- A numpy array representing the ground truth for the given sample.
|
286
|
+
|
287
|
+
name (str): The name of the ground truth section.
|
288
|
+
|
289
|
+
Example:
|
290
|
+
def ground_truth_handler(subset, index):
|
291
|
+
label = subset.data['labels'][index]
|
292
|
+
# Assuming labels are integers starting from 0
|
293
|
+
num_classes = 10 # Example number of classes
|
294
|
+
one_hot_label = np.zeros(num_classes)
|
295
|
+
one_hot_label[label] = 1
|
296
|
+
return one_hot_label
|
297
|
+
|
298
|
+
leap_binder.set_ground_truth(ground_truth_handler, name='ground_truth')
|
299
|
+
"""
|
300
|
+
|
121
301
|
function = to_numpy_return_wrapper(function)
|
122
302
|
self.setup_container.ground_truths.append(GroundTruthHandler(name, function))
|
123
303
|
|
124
304
|
self._encoder_names.append(name)
|
125
305
|
|
126
306
|
def set_metadata(self, function: MetadataSectionCallableInterface, name: str) -> None:
|
307
|
+
"""
|
308
|
+
Set the metadata handler function. This function is used for measuring and analyzing external variable values per sample, which is recommended for analysis within the Tensorleap platform.
|
309
|
+
|
310
|
+
Args:
|
311
|
+
function (MetadataSectionCallableInterface): The metadata handler function.
|
312
|
+
This function receives:
|
313
|
+
subset (PreprocessResponse): The subset of the data.
|
314
|
+
index (int): The index of the sample within the subset.
|
315
|
+
This function should return one of the following:
|
316
|
+
int: A single integer value.
|
317
|
+
Dict[str, int]: A dictionary with string keys and integer values.
|
318
|
+
str: A single string value.
|
319
|
+
Dict[str, str]: A dictionary with string keys and string values.
|
320
|
+
bool: A single boolean value.
|
321
|
+
Dict[str, bool]: A dictionary with string keys and boolean values.
|
322
|
+
float: A single float value.
|
323
|
+
Dict[str, float]: A dictionary with string keys and float values.
|
324
|
+
|
325
|
+
name (str): The name of the metadata section.
|
326
|
+
|
327
|
+
Example:
|
328
|
+
def metadata_handler_index(subset: PreprocessResponse, index: int) -> int:
|
329
|
+
return subset.data['metadata'][index]
|
330
|
+
|
331
|
+
|
332
|
+
def metadata_handler_image_mean(subset: PreprocessResponse, index: int) -> float:
|
333
|
+
fpath = subset.data['images'][index]
|
334
|
+
image = load_image(fpath)
|
335
|
+
mean_value = np.mean(image)
|
336
|
+
return mean_value
|
337
|
+
|
338
|
+
leap_binder.set_metadata(metadata_handler_index, name='metadata_index')
|
339
|
+
leap_binder.set_metadata(metadata_handler_image_mean, name='metadata_image_mean')
|
340
|
+
"""
|
127
341
|
self.setup_container.metadata.append(MetadataHandler(name, function))
|
128
342
|
|
129
343
|
def set_custom_layer(self, custom_layer: Type[Any], name: str, inspect_layer: bool = False,
|
130
344
|
kernel_index: Optional[int] = None, use_custom_latent_space: bool = False) -> None:
|
345
|
+
"""
|
346
|
+
Set a custom layer for the model.
|
347
|
+
|
348
|
+
Args:
|
349
|
+
custom_layer (Type[Any]): The custom layer class.
|
350
|
+
name (str): The name of the custom layer.
|
351
|
+
inspect_layer (bool): Whether to inspect the layer, default is False.
|
352
|
+
kernel_index (Optional[int]): The index of the kernel to inspect, if inspect_layer is True.
|
353
|
+
use_custom_latent_space (bool): Whether to use a custom latent space, default is False.
|
354
|
+
|
355
|
+
Example:
|
356
|
+
class CustomLayer:
|
357
|
+
def __init__(self, units: int):
|
358
|
+
self.units = units
|
359
|
+
|
360
|
+
def call(self, inputs):
|
361
|
+
return inputs * self.units
|
362
|
+
|
363
|
+
leap_binder.set_custom_layer(CustomLayer, name='custom_layer', inspect_layer=True, kernel_index=0)
|
364
|
+
"""
|
131
365
|
if inspect_layer and kernel_index is not None:
|
132
366
|
custom_layer.kernel_index = kernel_index
|
133
367
|
|
134
368
|
if use_custom_latent_space and not hasattr(custom_layer, custom_latent_space_attribute):
|
135
|
-
raise Exception(
|
369
|
+
raise Exception(
|
370
|
+
f"{custom_latent_space_attribute} function has not been set for custom layer: {custom_layer.__name__}")
|
136
371
|
|
137
372
|
init_args = inspect.getfullargspec(custom_layer.__init__)[0][1:]
|
138
373
|
call_args = inspect.getfullargspec(custom_layer.call)[0][1:]
|
code_loader/leaploader.py
CHANGED
@@ -5,15 +5,16 @@ import sys
|
|
5
5
|
from contextlib import redirect_stdout
|
6
6
|
from functools import lru_cache
|
7
7
|
from pathlib import Path
|
8
|
-
from typing import Dict, List, Iterable, Union, Any
|
8
|
+
from typing import Dict, List, Iterable, Union, Any, Optional, Tuple
|
9
9
|
|
10
10
|
import numpy as np
|
11
11
|
import numpy.typing as npt
|
12
12
|
|
13
13
|
from code_loader.contract.datasetclasses import DatasetSample, DatasetBaseHandler, GroundTruthHandler, \
|
14
14
|
PreprocessResponse, VisualizerHandler, VisualizerCallableReturnType, CustomLossHandler, \
|
15
|
-
PredictionTypeHandler, MetadataHandler, CustomLayerHandler, MetricHandler
|
16
|
-
from code_loader.contract.enums import DataStateEnum, TestingSectionEnum, DataStateType, DatasetMetadataType
|
15
|
+
PredictionTypeHandler, MetadataHandler, CustomLayerHandler, MetricHandler, ElementInstance
|
16
|
+
from code_loader.contract.enums import DataStateEnum, TestingSectionEnum, DataStateType, DatasetMetadataType, \
|
17
|
+
InstanceAnalysisType
|
17
18
|
from code_loader.contract.exceptions import DatasetScriptException
|
18
19
|
from code_loader.contract.responsedataclasses import DatasetIntegParseResult, DatasetTestResultPayload, \
|
19
20
|
DatasetPreprocess, DatasetSetup, DatasetInputInstance, DatasetOutputInstance, DatasetMetadataInstance, \
|
@@ -30,7 +31,6 @@ class LeapLoader:
|
|
30
31
|
@lru_cache()
|
31
32
|
def exec_script(self) -> None:
|
32
33
|
try:
|
33
|
-
print("executing script")
|
34
34
|
self.evaluate_module()
|
35
35
|
except TypeError as e:
|
36
36
|
import traceback
|
@@ -42,34 +42,25 @@ class LeapLoader:
|
|
42
42
|
raise DatasetScriptException(getattr(e, 'message', repr(e))) from e
|
43
43
|
|
44
44
|
def evaluate_module(self) -> None:
|
45
|
-
print("evaluate_module")
|
46
|
-
|
47
45
|
def append_path_recursively(full_path: str) -> None:
|
48
46
|
if '/' not in full_path or full_path == '/':
|
49
47
|
return
|
50
48
|
|
51
49
|
parent_path = str(Path(full_path).parent)
|
52
|
-
print(f"evaluate_module.append_path_recursively full_path: {full_path}, parent_path: {parent_path}")
|
53
50
|
append_path_recursively(parent_path)
|
54
|
-
|
55
51
|
sys.path.append(parent_path)
|
56
52
|
|
57
53
|
file_path = Path(self.code_path, self.code_entry_name)
|
58
|
-
print(f"evaluate_module: self.code_path: {self.code_path} self.code_entry_name: {self.code_entry_name}, "
|
59
|
-
f"file_path for append_path_recursively: {str(file_path)}")
|
60
54
|
append_path_recursively(str(file_path))
|
61
55
|
|
62
56
|
spec = importlib.util.spec_from_file_location(self.code_path, file_path)
|
63
|
-
print(f"evaluate_module: spec: {str(spec)}")
|
64
57
|
if spec is None or spec.loader is None:
|
65
58
|
raise DatasetScriptException(f'Something is went wrong with spec file from: {file_path}')
|
66
59
|
|
67
60
|
file = importlib.util.module_from_spec(spec)
|
68
|
-
print(f"evaluate_module: file module_from_spec: {str(file)}")
|
69
61
|
if file is None:
|
70
62
|
raise DatasetScriptException(f'Something is went wrong with import module from: {file_path}')
|
71
63
|
|
72
|
-
print(f"evaluate_module: spec.loader.exec_module")
|
73
64
|
spec.loader.exec_module(file)
|
74
65
|
|
75
66
|
@lru_cache()
|
@@ -181,8 +172,7 @@ class LeapLoader:
|
|
181
172
|
preprocess_response, test_result, dataset_base_handler)
|
182
173
|
except Exception as e:
|
183
174
|
line_number, file_name, stacktrace = get_root_exception_file_and_line_number()
|
184
|
-
test_result[0].display[
|
185
|
-
state_name] = f"{repr(e)} in file {file_name}, line_number: {line_number}\nStacktrace:\n{stacktrace}"
|
175
|
+
test_result[0].display[state_name] = f"{repr(e)} in file {file_name}, line_number: {line_number}\nStacktrace:\n{stacktrace}"
|
186
176
|
test_result[0].is_passed = False
|
187
177
|
|
188
178
|
result_payloads.extend(test_result)
|
@@ -309,6 +299,17 @@ class LeapLoader:
|
|
309
299
|
def _get_inputs(self, state: DataStateEnum, idx: int) -> Dict[str, npt.NDArray[np.float32]]:
|
310
300
|
return self._get_dataset_handlers(global_leap_binder.setup_container.inputs, state, idx)
|
311
301
|
|
302
|
+
def get_instance_elements(self, state: DataStateEnum, idx: int, input_name: str) \
|
303
|
+
-> Tuple[Optional[List[ElementInstance]], Optional[InstanceAnalysisType]]:
|
304
|
+
preprocess_result = self._preprocess_result()
|
305
|
+
preprocess_state = preprocess_result[state]
|
306
|
+
for element_instance in global_leap_binder.setup_container.element_instances:
|
307
|
+
if element_instance.input_name == input_name:
|
308
|
+
return element_instance.instance_function(idx, preprocess_state), element_instance.analysis_type
|
309
|
+
|
310
|
+
return None, None
|
311
|
+
|
312
|
+
|
312
313
|
def _get_gt(self, state: DataStateEnum, idx: int) -> Dict[str, npt.NDArray[np.float32]]:
|
313
314
|
return self._get_dataset_handlers(global_leap_binder.setup_container.ground_truths, state, idx)
|
314
315
|
|
@@ -354,8 +355,7 @@ class LeapLoader:
|
|
354
355
|
if isinstance(handler_result, dict):
|
355
356
|
for single_metadata_name, single_metadata_result in handler_result.items():
|
356
357
|
handler_name = f'{handler.name}_{single_metadata_name}'
|
357
|
-
result_agg[handler_name] = self._convert_metadata_to_correct_type(handler_name,
|
358
|
-
single_metadata_result)
|
358
|
+
result_agg[handler_name] = self._convert_metadata_to_correct_type(handler_name, single_metadata_result)
|
359
359
|
else:
|
360
360
|
handler_name = handler.name
|
361
361
|
result_agg[handler_name] = self._convert_metadata_to_correct_type(handler_name, handler_result)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
|
2
|
+
code_loader/__init__.py,sha256=V3DEXSN6Ie6PlGeSAbzjp9ufRj0XPJLpD7pDLLYxk6M,122
|
3
|
+
code_loader/contract/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
code_loader/contract/datasetclasses.py,sha256=eoDxCGZzvogp440dhWZBBm8oTs6XiqcHxE-JXD4txeA,6128
|
5
|
+
code_loader/contract/enums.py,sha256=2tKXamabooQjCe3EBkeBcZMA8vBbeGjDAbACvUTGqLE,1707
|
6
|
+
code_loader/contract/exceptions.py,sha256=jWqu5i7t-0IG0jGRsKF4DjJdrsdpJjIYpUkN1F4RiyQ,51
|
7
|
+
code_loader/contract/responsedataclasses.py,sha256=w7xVOv2S8Hyb5lqyomMGiKAWXDTSOG-FX1YW39bXD3A,3969
|
8
|
+
code_loader/contract/visualizer_classes.py,sha256=t0EKxTGFJoFBnKuMmjtFpj-L32xEFF3NV-E5XutVXa0,10118
|
9
|
+
code_loader/inner_leap_binder/__init__.py,sha256=koOlJyMNYzGbEsoIbXathSmQ-L38N_pEXH_HvL7beXU,99
|
10
|
+
code_loader/inner_leap_binder/leapbinder.py,sha256=7_ffUiGW54Y27f7eKnvpJ2XLOqfGfTCW5cMNaH21iIk,24464
|
11
|
+
code_loader/leaploader.py,sha256=gQaEpHyQx50FP-d0LS2PjQdm9aOUf3jok8ZeLbWkGZc,17917
|
12
|
+
code_loader/utils.py,sha256=61I4PgSl-ZBIe4DifLxMNlBELE-HQR2pB9efVYPceIU,2230
|
13
|
+
code_loader/visualizers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
+
code_loader/visualizers/default_visualizers.py,sha256=F2qRT6rNy7SOmr4QfqVxIkLlYEa00CwDkLJuA45lfSI,2254
|
15
|
+
code_loader-1.0.42a0.dist-info/LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
|
16
|
+
code_loader-1.0.42a0.dist-info/METADATA,sha256=HrRgFfW68Nr0KIBzK-C9Fwnxcw9SYotWTzWfwW2PF4I,770
|
17
|
+
code_loader-1.0.42a0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
18
|
+
code_loader-1.0.42a0.dist-info/RECORD,,
|
@@ -1,18 +0,0 @@
|
|
1
|
-
LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
|
2
|
-
code_loader/__init__.py,sha256=V3DEXSN6Ie6PlGeSAbzjp9ufRj0XPJLpD7pDLLYxk6M,122
|
3
|
-
code_loader/contract/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
code_loader/contract/datasetclasses.py,sha256=e4pEajPiktogtrctf29Q9IqG5VaZz0QE_ioc4Ri1ohs,4796
|
5
|
-
code_loader/contract/enums.py,sha256=6Lo7p5CUog68Fd31bCozIuOgIp_IhSiPqWWph2k3OGU,1602
|
6
|
-
code_loader/contract/exceptions.py,sha256=jWqu5i7t-0IG0jGRsKF4DjJdrsdpJjIYpUkN1F4RiyQ,51
|
7
|
-
code_loader/contract/responsedataclasses.py,sha256=JgISOk1fVAD7dBLmwp2IzCkpItwO7YP3SDqzTX5FMDA,2880
|
8
|
-
code_loader/contract/visualizer_classes.py,sha256=EKkQ7qWS48LeT3JoJT8-uMdRDxVOkSp0q-rhVMxrEFY,5990
|
9
|
-
code_loader/inner_leap_binder/__init__.py,sha256=koOlJyMNYzGbEsoIbXathSmQ-L38N_pEXH_HvL7beXU,99
|
10
|
-
code_loader/inner_leap_binder/leapbinder.py,sha256=cayCJxnksr5lrEIX1HngiuPpTupStti4DD6KX3k-PBI,13610
|
11
|
-
code_loader/leaploader.py,sha256=SCAJWVTmuAZ4G4SvPljaxDS1zaM_8BOSO45fKhz4L7g,17956
|
12
|
-
code_loader/utils.py,sha256=61I4PgSl-ZBIe4DifLxMNlBELE-HQR2pB9efVYPceIU,2230
|
13
|
-
code_loader/visualizers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
-
code_loader/visualizers/default_visualizers.py,sha256=F2qRT6rNy7SOmr4QfqVxIkLlYEa00CwDkLJuA45lfSI,2254
|
15
|
-
code_loader-1.0.41.dist-info/LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
|
16
|
-
code_loader-1.0.41.dist-info/METADATA,sha256=QmhzHlZeg1rUYSRKrDAsdJtCYMEZl-9bolsHDtXYuHk,768
|
17
|
-
code_loader-1.0.41.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
18
|
-
code_loader-1.0.41.dist-info/RECORD,,
|
File without changes
|
File without changes
|