dragon-ml-toolbox 2.4.0__py3-none-any.whl → 3.0.0__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.
- {dragon_ml_toolbox-2.4.0.dist-info → dragon_ml_toolbox-3.0.0.dist-info}/METADATA +7 -4
- dragon_ml_toolbox-3.0.0.dist-info/RECORD +25 -0
- ml_tools/ETL_engineering.py +8 -7
- ml_tools/GUI_tools.py +24 -25
- ml_tools/MICE_imputation.py +8 -4
- ml_tools/ML_callbacks.py +341 -0
- ml_tools/ML_evaluation.py +255 -0
- ml_tools/ML_trainer.py +344 -0
- ml_tools/ML_tutorial.py +300 -0
- ml_tools/PSO_optimization.py +27 -20
- ml_tools/RNN_forecast.py +49 -0
- ml_tools/VIF_factor.py +6 -5
- ml_tools/datasetmaster.py +601 -527
- ml_tools/ensemble_learning.py +12 -9
- ml_tools/handle_excel.py +9 -10
- ml_tools/logger.py +45 -8
- ml_tools/utilities.py +18 -1
- dragon_ml_toolbox-2.4.0.dist-info/RECORD +0 -22
- ml_tools/trainer.py +0 -346
- ml_tools/vision_helpers.py +0 -231
- {dragon_ml_toolbox-2.4.0.dist-info → dragon_ml_toolbox-3.0.0.dist-info}/WHEEL +0 -0
- {dragon_ml_toolbox-2.4.0.dist-info → dragon_ml_toolbox-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {dragon_ml_toolbox-2.4.0.dist-info → dragon_ml_toolbox-3.0.0.dist-info}/licenses/LICENSE-THIRD-PARTY.md +0 -0
- {dragon_ml_toolbox-2.4.0.dist-info → dragon_ml_toolbox-3.0.0.dist-info}/top_level.txt +0 -0
- /ml_tools/{pytorch_models.py → _pytorch_models.py} +0 -0
ml_tools/vision_helpers.py
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import imghdr
|
|
3
|
-
from PIL import Image, ImageOps
|
|
4
|
-
from typing import Literal
|
|
5
|
-
from torchvision import transforms
|
|
6
|
-
import torch
|
|
7
|
-
from .utilities import _script_info
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
__all__ = [
|
|
11
|
-
"inspect_images",
|
|
12
|
-
"image_augmentation",
|
|
13
|
-
"ResizeAspectFill",
|
|
14
|
-
"is_image",
|
|
15
|
-
"model_predict"
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def inspect_images(path: str):
|
|
20
|
-
"""
|
|
21
|
-
Prints out the types, sizes and channels of image files found in the directory and its subdirectories.
|
|
22
|
-
|
|
23
|
-
Possible band names (channels):
|
|
24
|
-
* “R”: Red channel
|
|
25
|
-
* “G”: Green channel
|
|
26
|
-
* “B”: Blue channel
|
|
27
|
-
* “A”: Alpha (transparency) channel
|
|
28
|
-
* “L”: Luminance (grayscale) channel
|
|
29
|
-
* “P”: Palette channel
|
|
30
|
-
* “I”: Integer channel
|
|
31
|
-
* “F”: Floating point channel
|
|
32
|
-
|
|
33
|
-
Args:
|
|
34
|
-
path (string): path to target directory.
|
|
35
|
-
"""
|
|
36
|
-
# Non-image files present?
|
|
37
|
-
red_flag = False
|
|
38
|
-
non_image = set()
|
|
39
|
-
# Image types found
|
|
40
|
-
img_types = set()
|
|
41
|
-
# Image sizes found
|
|
42
|
-
img_sizes = set()
|
|
43
|
-
# Color channels found
|
|
44
|
-
img_channels = set()
|
|
45
|
-
# Number of images
|
|
46
|
-
img_counter = 0
|
|
47
|
-
# Loop through files in the directory and subdirectories
|
|
48
|
-
for root, directories, files in os.walk(path):
|
|
49
|
-
for filename in files:
|
|
50
|
-
filepath = os.path.join(root, filename)
|
|
51
|
-
img_type = imghdr.what(filepath)
|
|
52
|
-
# Not an image file
|
|
53
|
-
if img_type is None:
|
|
54
|
-
red_flag = True
|
|
55
|
-
non_image.add(filename)
|
|
56
|
-
continue
|
|
57
|
-
# Image type
|
|
58
|
-
img_types.add(img_type)
|
|
59
|
-
# Image counter
|
|
60
|
-
img_counter += 1
|
|
61
|
-
# Image size
|
|
62
|
-
img = Image.open(filepath)
|
|
63
|
-
img_sizes.add(img.size)
|
|
64
|
-
# Image color channels
|
|
65
|
-
channels = img.getbands()
|
|
66
|
-
for code in channels:
|
|
67
|
-
img_channels.add(code)
|
|
68
|
-
|
|
69
|
-
if red_flag:
|
|
70
|
-
print(f"⚠️ Non-image files found: {non_image}")
|
|
71
|
-
# Print results
|
|
72
|
-
print(f"Image types found: {img_types}\nImage sizes found: {img_sizes}\nImage channels found: {img_channels}\nImages found: {img_counter}")
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def image_augmentation(path: str, samples: int=100, size: int=256, mode: Literal["RGB", "L"]="RGB", jitter_ratio: float=0.0,
|
|
76
|
-
rotation_deg=270, output: Literal["jpeg", "png", "tiff", "bmp"]="jpeg"):
|
|
77
|
-
"""
|
|
78
|
-
Perform image augmentation on a directory containing image files.
|
|
79
|
-
A new directory "temp_augmented_images" will be created; an error will be raised if it already exists.
|
|
80
|
-
|
|
81
|
-
Args:
|
|
82
|
-
path (str): Path to target directory.
|
|
83
|
-
samples (int, optional): Number of images to create per image in the directory. Defaults to 100.
|
|
84
|
-
size (int, optional): Image size to resize to. Defaults to 256.
|
|
85
|
-
mode (str, optional): 'RGB' for 3 channels, 'L' for 1 grayscale channel.
|
|
86
|
-
jitter_ratio (float, optional): Brightness and Contrast factor to use in the ColorJitter transform. Defaults to 0.
|
|
87
|
-
rotation_deg (int, optional): Range for the rotation transformation. Defaults to 270.
|
|
88
|
-
output (str, optional): output image format. Defaults to 'jpeg'.
|
|
89
|
-
"""
|
|
90
|
-
# Define the transformations
|
|
91
|
-
transform = transforms.Compose([
|
|
92
|
-
transforms.Resize(size=(int(size*1.2),int(size*1.2))),
|
|
93
|
-
transforms.CenterCrop(size=size),
|
|
94
|
-
transforms.ColorJitter(brightness=jitter_ratio, contrast=jitter_ratio),
|
|
95
|
-
transforms.RandomHorizontalFlip(p=0.5),
|
|
96
|
-
transforms.RandomRotation(degrees=rotation_deg),
|
|
97
|
-
])
|
|
98
|
-
|
|
99
|
-
# Create container folder
|
|
100
|
-
dir_name = "temp_augmented_images"
|
|
101
|
-
os.makedirs(dir_name, exist_ok=False)
|
|
102
|
-
|
|
103
|
-
# Keep track of non-image files
|
|
104
|
-
non_image = set()
|
|
105
|
-
|
|
106
|
-
# Apply transformation to each image in path
|
|
107
|
-
for filename in os.listdir(path):
|
|
108
|
-
filepath = os.path.join(path, filename)
|
|
109
|
-
|
|
110
|
-
# Is image file?
|
|
111
|
-
if not is_image(filename):
|
|
112
|
-
non_image.add(filename)
|
|
113
|
-
continue
|
|
114
|
-
# if imghdr.what(filepath) is None:
|
|
115
|
-
# non_image.add(filename)
|
|
116
|
-
# continue
|
|
117
|
-
|
|
118
|
-
# current image
|
|
119
|
-
img = Image.open(filepath)
|
|
120
|
-
|
|
121
|
-
# Convert to RGB or grayscale
|
|
122
|
-
if mode == "RGB":
|
|
123
|
-
img = img.convert("RGB")
|
|
124
|
-
else:
|
|
125
|
-
img = img.convert("L")
|
|
126
|
-
|
|
127
|
-
# Create and save images
|
|
128
|
-
for i in range(1, samples+1):
|
|
129
|
-
new_img = transform(img)
|
|
130
|
-
filename_no_ext = os.path.splitext(filename)[0]
|
|
131
|
-
new_img.save(f"{dir_name}/{filename_no_ext}_{i}.{output}")
|
|
132
|
-
|
|
133
|
-
# Print non-image files
|
|
134
|
-
if len(non_image) != 0:
|
|
135
|
-
print(f"Files not processed: {non_image}")
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
class ResizeAspectFill:
|
|
139
|
-
"""
|
|
140
|
-
Custom transformation to make a square image (width/height = 1).
|
|
141
|
-
|
|
142
|
-
Implemented by padding with a `pad_color` border an image of size (w, h) when w > h or w < h to match the longest side.
|
|
143
|
-
"""
|
|
144
|
-
def __init__(self, pad_color: Literal["black", "white"]="black") -> None:
|
|
145
|
-
self.pad_color = pad_color
|
|
146
|
-
|
|
147
|
-
def __call__(self, image: Image.Image):
|
|
148
|
-
# Check correct PIL.Image file
|
|
149
|
-
if not isinstance(image, Image.Image):
|
|
150
|
-
raise TypeError(f"Expected PIL.Image.Image, got {type(image).__name__}")
|
|
151
|
-
|
|
152
|
-
w = image.width
|
|
153
|
-
h = image.height
|
|
154
|
-
delta = abs(w - h)
|
|
155
|
-
|
|
156
|
-
if w > h:
|
|
157
|
-
# padding: left, top, right, bottom
|
|
158
|
-
padding = (0, 0, 0, delta)
|
|
159
|
-
elif h > w:
|
|
160
|
-
padding = (0, 0, delta, 0)
|
|
161
|
-
else:
|
|
162
|
-
padding = (0, 0)
|
|
163
|
-
|
|
164
|
-
return ImageOps.expand(image=image, border=padding, fill=self.pad_color)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
def is_image(file: str):
|
|
168
|
-
"""
|
|
169
|
-
Returns `True` if the file is an image, `False` otherwise.
|
|
170
|
-
|
|
171
|
-
Args:
|
|
172
|
-
`file`, filename with extension.
|
|
173
|
-
"""
|
|
174
|
-
try:
|
|
175
|
-
Image.open(file)
|
|
176
|
-
except IOError:
|
|
177
|
-
return False
|
|
178
|
-
else:
|
|
179
|
-
return True
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
def model_predict(model: torch.nn.Module, kind: Literal["regression", "classification"], samples_list: list[torch.Tensor],
|
|
183
|
-
device: Literal["cpu", "cuda", "mps"]='cpu', view_as: tuple[int,int]=(1,-1), add_batch_dimension: bool=True):
|
|
184
|
-
"""
|
|
185
|
-
Returns a list containing lists of predicted values, one for each input sample.
|
|
186
|
-
|
|
187
|
-
Each sample must be a tensor and have the same shape and normalization expected by the model.
|
|
188
|
-
|
|
189
|
-
Args:
|
|
190
|
-
`model`: A trained PyTorch model.
|
|
191
|
-
|
|
192
|
-
`kind`: Regression or Classification task.
|
|
193
|
-
|
|
194
|
-
`samples_list`: A list of input tensors.
|
|
195
|
-
|
|
196
|
-
`device`: Device to use, default is CPU.
|
|
197
|
-
|
|
198
|
-
`view_as`: Reshape each model output, default is (1,-1).
|
|
199
|
-
|
|
200
|
-
`add_batch_dimension`: Automatically adds the batch dimension to each sample shape.
|
|
201
|
-
"""
|
|
202
|
-
# Validate device
|
|
203
|
-
if device == "cuda":
|
|
204
|
-
if not torch.cuda.is_available():
|
|
205
|
-
print("CUDA not available, switching to CPU.")
|
|
206
|
-
device = "cpu"
|
|
207
|
-
elif device == "mps":
|
|
208
|
-
if not torch.backends.mps.is_available():
|
|
209
|
-
print("MPS not available, switching to CPU.")
|
|
210
|
-
device = "cpu"
|
|
211
|
-
|
|
212
|
-
model.eval()
|
|
213
|
-
results = list()
|
|
214
|
-
with torch.no_grad():
|
|
215
|
-
for data_point in samples_list:
|
|
216
|
-
if add_batch_dimension:
|
|
217
|
-
data_point = data_point.unsqueeze(0).to(device)
|
|
218
|
-
else:
|
|
219
|
-
data_point = data_point.to(device)
|
|
220
|
-
|
|
221
|
-
output = model(data_point)
|
|
222
|
-
if kind == "classification":
|
|
223
|
-
results.append(output.argmax(dim=1).view(view_as).cpu().tolist())
|
|
224
|
-
else: #regression
|
|
225
|
-
results.append(output.view(view_as).cpu().tolist())
|
|
226
|
-
|
|
227
|
-
return results
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
def info():
|
|
231
|
-
_script_info(__all__)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|