radnn 0.0.8__py3-none-any.whl → 0.1.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.
Files changed (76) hide show
  1. radnn/__init__.py +5 -5
  2. radnn/benchmark/__init__.py +1 -0
  3. radnn/benchmark/latency.py +55 -0
  4. radnn/core.py +146 -2
  5. radnn/data/__init__.py +5 -10
  6. radnn/data/dataset_base.py +100 -260
  7. radnn/data/dataset_base_legacy.py +280 -0
  8. radnn/data/errors.py +32 -0
  9. radnn/data/sample_preprocessor.py +58 -0
  10. radnn/data/sample_set.py +203 -90
  11. radnn/data/sample_set_kind.py +126 -0
  12. radnn/data/sequence_dataset.py +25 -30
  13. radnn/data/structs/__init__.py +1 -0
  14. radnn/data/structs/tree.py +322 -0
  15. radnn/data_beta/__init__.py +12 -0
  16. radnn/{data → data_beta}/data_feed.py +1 -1
  17. radnn/data_beta/dataset_base.py +337 -0
  18. radnn/data_beta/sample_set.py +166 -0
  19. radnn/data_beta/sequence_dataset.py +134 -0
  20. radnn/data_beta/structures/__init__.py +2 -0
  21. radnn/data_beta/structures/dictionary.py +41 -0
  22. radnn/{data → data_beta}/tf_classification_data_feed.py +5 -2
  23. radnn/errors.py +10 -2
  24. radnn/experiment/__init__.py +2 -0
  25. radnn/experiment/identification.py +7 -0
  26. radnn/experiment/ml_experiment.py +7 -2
  27. radnn/experiment/ml_experiment_log.py +47 -0
  28. radnn/images/image_processor.py +4 -1
  29. radnn/learn/__init__.py +0 -7
  30. radnn/learn/keras/__init__.py +4 -0
  31. radnn/learn/{state → keras}/keras_best_state_saver.py +5 -1
  32. radnn/learn/{learning_algorithm.py → keras/keras_learning_algorithm.py} +5 -9
  33. radnn/learn/{keras_learning_rate_scheduler.py → keras/keras_learning_rate_scheduler.py} +4 -1
  34. radnn/learn/{keras_optimization_algorithm.py → keras/keras_optimization_combo.py} +7 -3
  35. radnn/learn/torch/__init__.py +3 -0
  36. radnn/learn/torch/ml_model_freezer.py +330 -0
  37. radnn/learn/torch/ml_trainer.py +461 -0
  38. radnn/learn/torch/staircase_lr_scheduler.py +21 -0
  39. radnn/ml_system.py +68 -52
  40. radnn/models/__init__.py +5 -0
  41. radnn/models/cnn/__init__.py +0 -0
  42. radnn/models/cnn/cnn_stem_setup.py +35 -0
  43. radnn/models/model_factory.py +85 -0
  44. radnn/models/model_hyperparams.py +128 -0
  45. radnn/models/model_info.py +91 -0
  46. radnn/plots/plot_learning_curve.py +19 -8
  47. radnn/system/__init__.py +1 -0
  48. radnn/system/files/__init__.py +1 -1
  49. radnn/system/files/csvfile.py +37 -5
  50. radnn/system/files/filelist.py +30 -0
  51. radnn/system/files/fileobject.py +11 -1
  52. radnn/system/files/imgfile.py +1 -1
  53. radnn/system/files/jsonfile.py +37 -9
  54. radnn/system/files/picklefile.py +3 -3
  55. radnn/system/files/textfile.py +39 -10
  56. radnn/system/files/zipfile.py +96 -0
  57. radnn/system/filestore.py +147 -47
  58. radnn/system/filesystem.py +3 -3
  59. radnn/test/__init__.py +1 -0
  60. radnn/test/tensor_hash.py +130 -0
  61. radnn/utils.py +16 -2
  62. radnn-0.1.0.dist-info/METADATA +30 -0
  63. radnn-0.1.0.dist-info/RECORD +99 -0
  64. {radnn-0.0.8.dist-info → radnn-0.1.0.dist-info}/WHEEL +1 -1
  65. {radnn-0.0.8.dist-info → radnn-0.1.0.dist-info/licenses}/LICENSE.txt +1 -1
  66. radnn/learn/state/__init__.py +0 -4
  67. radnn-0.0.8.dist-info/METADATA +0 -58
  68. radnn-0.0.8.dist-info/RECORD +0 -70
  69. /radnn/{data → data_beta}/dataset_folder.py +0 -0
  70. /radnn/{data → data_beta}/image_dataset.py +0 -0
  71. /radnn/{data → data_beta}/image_dataset_files.py +0 -0
  72. /radnn/{data → data_beta}/preprocess/__init__.py +0 -0
  73. /radnn/{data → data_beta}/preprocess/normalizer.py +0 -0
  74. /radnn/{data → data_beta}/preprocess/standardizer.py +0 -0
  75. /radnn/{data → data_beta}/subset_type.py +0 -0
  76. {radnn-0.0.8.dist-info → radnn-0.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,280 @@
1
+ # ......................................................................................
2
+ # MIT License
3
+
4
+ # Copyright (c) 2023 Pantelis I. Kaplanoglou
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ # ......................................................................................
25
+
26
+
27
+ import numpy as np
28
+ from sklearn.model_selection import train_test_split # import a standalone procedure function from the pacakge
29
+
30
+
31
+ # =========================================================================================================================
32
+ class CDataSetBase(object):
33
+ # --------------------------------------------------------------------------------------
34
+ # Constructor
35
+ def __init__(self, name=None, random_seed=None, is_classification=True):
36
+ # ................................................................
37
+ # // Fields \\
38
+ self.Name = name
39
+ self.RandomSeed = random_seed
40
+ self.IsClassification = is_classification
41
+
42
+ self.FeatureCount = None
43
+ self.ClassCount = None
44
+ self.class_names = dict()
45
+ self.SampleCount = None
46
+
47
+ self.Samples = None
48
+ self.Targets = None
49
+
50
+ self.TSSampleIDs = None
51
+ self.TSSamples = None
52
+ self.TSTargets = None
53
+ self.TSSampleCount = 0
54
+
55
+ self.VSSampleIDs = None
56
+ self.VSSamples = None
57
+ self.VSTargets = None
58
+ self.VSSampleCount = 0
59
+
60
+ self.UTSampleIDs = None
61
+ self.UTSamples = None
62
+ self.UTTargets = None
63
+ self.UTSampleCount = None
64
+
65
+ # ................................................................
66
+ if self.RandomSeed is not None:
67
+ ml.RandomSeed(self.RandomSeed)
68
+
69
+ # --------------------------------------------------------------------------------------
70
+ def preview_images(self):
71
+ import matplotlib.pyplot as plt
72
+
73
+ # Look at some sample images from dataset
74
+ plt.figure(figsize=(10, 10))
75
+ for i in range(25):
76
+ plt.subplot(5, 5, i + 1)
77
+ if self.TSSamples.shape[2] == 2:
78
+ plt.imshow(self.TSSamples[i].squeeze().astype(np.uint8), cmap='gray')
79
+ else:
80
+ plt.imshow(self.TSSamples[i].squeeze().astype(np.uint8))
81
+
82
+ nClassIndex = self.TSLabels[i]
83
+ sClassDescr = str(nClassIndex)
84
+ if isinstance(self.class_names, dict):
85
+ if nClassIndex in self.class_names:
86
+ sClassName = self.class_names[nClassIndex]
87
+ sClassDescr += " `" + sClassName + "`"
88
+ elif isinstance(self.class_names, list):
89
+ sClassName = self.class_names[nClassIndex]
90
+ sClassDescr += " `" + sClassName + "` "
91
+
92
+ plt.title(f"Label: {sClassDescr}")
93
+ plt.axis('off')
94
+ plt.show()
95
+
96
+ # --------------------------------------------------------------------------------------
97
+ @property
98
+ def Labels(self):
99
+ return self.Targets
100
+
101
+ # --------------------------------------------------------------------------------------
102
+ @property
103
+ def TSLabels(self):
104
+ return self.TSTargets
105
+
106
+ # --------------------------------------------------------------------------------------
107
+ @property
108
+ def VSLabels(self):
109
+ return self.VSTargets
110
+
111
+ # --------------------------------------------------------------------------------------
112
+ @property
113
+ def UTLabels(self):
114
+ return self.UTTargets
115
+
116
+ # --------------------------------------------------------------------------------------
117
+ def TrainingSet(self, p_nSamples, p_nTargets):
118
+ self.TSSamples = p_nSamples
119
+ self.TSTargets = p_nTargets
120
+ self.countSamples()
121
+ self.TSSampleIDs = np.arange(0, self.TSSampleCount)
122
+
123
+ # Feature count is calculated on samples that are flattened as vectors
124
+ if self.FeatureCount is None:
125
+ self.FeatureCount = np.prod(self.TSSamples.shape[1:])
126
+
127
+ if self.ClassCount is None:
128
+ if self.IsClassification:
129
+ self.ClassCount = len(np.unique(self.TSTargets))
130
+ else:
131
+ self.ClassCount = 0
132
+
133
+ # --------------------------------------------------------------------------------------
134
+ def ValidationSet(self, p_nSamples, p_nTargets):
135
+ self.VSSamples = p_nSamples
136
+ self.VSTargets = p_nTargets
137
+ self.countSamples()
138
+ self.VSSampleIDs = np.arange(0, self.VSSampleCount)
139
+
140
+ # --------------------------------------------------------------------------------------
141
+ def UnknownTestSet(self, p_nSamples, p_nTargets):
142
+ self.UTSamples = p_nSamples
143
+ self.UTTargets = p_nTargets
144
+ self.countSamples()
145
+ self.UTSampleIDs = np.arange(0, self.UTSampleCount)
146
+ # --------------------------------------------------------------------------------------
147
+
148
+ def info(self):
149
+ self.PrintInfo()
150
+
151
+ # --------------------------------------------------------------------------------------
152
+ def PrintInfo(self):
153
+ print("Dataset [%s]" % self.Name)
154
+ print(" |__ FeatureCount:", self.FeatureCount)
155
+ if self.IsClassification:
156
+ print(" |__ ClassCount:", self.ClassCount)
157
+
158
+ if self.TSSamples is not None:
159
+ print(" |__ Training set samples : %d shape:%s" % (self.TSSampleCount, self.TSSamples.shape))
160
+ if self.TSTargets is not None:
161
+ print(" |__ Training set targets : %d shape:%s" % (self.TSSampleCount, self.TSTargets.shape))
162
+
163
+ if self.VSSamples is not None:
164
+ print(" |__ Validation set samples: %d shape:%s" % (self.VSSampleCount, self.VSSamples.shape))
165
+ if self.VSTargets is not None:
166
+ print(" |__ Validation set targets: %d shape:%s" % (self.VSSampleCount, self.VSTargets.shape))
167
+
168
+ if self.UTSamples is not None:
169
+ print(" |__ MemoryTest set samples : %d shape:%s" % (self.UTSampleCount, self.UTSamples.shape))
170
+ if self.UTTargets is not None:
171
+ print(" |__ MemoryTest set targets : %d shape:%s" % (self.UTSampleCount, self.UTTargets.shape))
172
+
173
+ # --------------------------------------------------------------------------------------
174
+ def countSamples(self):
175
+ if self.TSSamples is not None:
176
+ self.TSSampleCount = self.TSSamples.shape[0]
177
+ self.SampleCount = self.TSSampleCount + self.VSSampleCount
178
+
179
+ if self.VSSamples is not None:
180
+ self.VSSampleCount = self.VSSamples.shape[0]
181
+ self.SampleCount = self.TSSampleCount + self.VSSampleCount
182
+
183
+ # The test set samples are not included in the available sample count
184
+ if self.UTSamples is not None:
185
+ self.UTSampleCount = self.UTSamples.shape[0]
186
+
187
+ # --------------------------------------------------------------------------------------
188
+ def Split(self, p_nTrainingPercentage):
189
+ nTSSamples, nVSSamples, nTSTargets, nVSTargets = train_test_split(self.Samples, self.Targets
190
+ , test_size=1.0 - p_nTrainingPercentage
191
+ , random_state=self.RandomSeed
192
+ , shuffle=True
193
+ , stratify=self.Targets
194
+ )
195
+ self.TrainingSet(nTSSamples, nTSTargets)
196
+ self.ValidationSet(nVSSamples, nVSTargets)
197
+ self.countSamples()
198
+
199
+ # --------------------------------------------------------------------------------------
200
+ def LoadCache(self, p_oFileStore, p_sSamplesFilePrefix="Samples", p_sTargetsFilePrefix="Targets", p_bIsVerbose=False):
201
+ bResult = p_oFileStore.Exists("%s.pkl" % p_sSamplesFilePrefix) or p_oFileStore.Exists(
202
+ "%s.TS.pkl" % p_sSamplesFilePrefix)
203
+
204
+ if bResult:
205
+ if p_bIsVerbose:
206
+ print("Loading known data set ...")
207
+ self.Samples = p_oFileStore.Deserialize("%s.pkl" % p_sSamplesFilePrefix)
208
+ self.Targets = p_oFileStore.Deserialize("%s.pkl" % p_sTargetsFilePrefix)
209
+
210
+ if p_bIsVerbose:
211
+ print("Loading training set ...")
212
+ nTSSamples = p_oFileStore.Deserialize("%s.TS.pkl" % p_sSamplesFilePrefix)
213
+ nTSTargets = p_oFileStore.Deserialize("%s.TS.pkl" % p_sTargetsFilePrefix)
214
+ self.TrainingSet(nTSSamples, nTSTargets)
215
+
216
+ if p_bIsVerbose:
217
+ print("Loading validation set ...")
218
+ nVSSamples = p_oFileStore.Deserialize("%s.VS.pkl" % p_sSamplesFilePrefix)
219
+ nVSTargets = p_oFileStore.Deserialize("%s.VS.pkl" % p_sTargetsFilePrefix)
220
+ self.ValidationSet(nVSSamples, nVSTargets)
221
+
222
+ if p_bIsVerbose:
223
+ print("Loading unknown test data set ...")
224
+ nUTSamples = p_oFileStore.Deserialize("%s.UT.pkl" % p_sSamplesFilePrefix)
225
+ if nUTSamples is not None:
226
+ nUTTargets = p_oFileStore.Deserialize("%s.UT.pkl" % p_sTargetsFilePrefix)
227
+ self.UnknownTestSet(nUTSamples, nUTTargets)
228
+
229
+ return bResult
230
+
231
+ # --------------------------------------------------------------------------------------
232
+ def SaveCache(self, p_oFileStore, p_sSamplesFilePrefix="Samples", p_sTargetsFilePrefix="Targets"):
233
+ if self.Samples is not None:
234
+ p_oFileStore.Serialize("%s.pkl" % p_sSamplesFilePrefix, self.Samples, True)
235
+ p_oFileStore.Serialize("%s.pkl" % p_sTargetsFilePrefix, self.Labels, True)
236
+
237
+ p_oFileStore.Serialize("%s.TS.pkl" % p_sSamplesFilePrefix, self.TSSamples, True)
238
+ p_oFileStore.Serialize("%s.TS.pkl" % p_sTargetsFilePrefix, self.TSLabels, True)
239
+
240
+ p_oFileStore.Serialize("%s.VS.pkl" % p_sSamplesFilePrefix, self.VSSamples, True)
241
+ p_oFileStore.Serialize("%s.VS.pkl" % p_sTargetsFilePrefix, self.VSLabels, True)
242
+
243
+ if self.UTSamples is not None:
244
+ p_oFileStore.Serialize("%s.UT.pkl" % p_sSamplesFilePrefix, self.UTSamples, True)
245
+ p_oFileStore.Serialize("%s.UT.pkl" % p_sTargetsFilePrefix, self.UTLabels, True)
246
+ # --------------------------------------------------------------------------------------
247
+
248
+
249
+ # =========================================================================================================================
250
+
251
+
252
+ if __name__ == "__main__":
253
+ ml.RandomSeed(2023)
254
+
255
+ #nData = np.random.rand(100).astype(np.float32)
256
+ nData = np.arange(0, 100)
257
+ nData = nData / (nData + 1)
258
+ print(nData.shape)
259
+ nTargets = np.concatenate([np.zeros(50), np.ones(50)], axis=0).astype(np.int32)
260
+ print(nTargets.shape)
261
+
262
+ oDataset = CDataSetBase("dummy")
263
+ oDataset.Samples = nData
264
+ oDataset.Targets = nTargets
265
+ oDataset.Split(0.8)
266
+ oDataset.PrintInfo()
267
+
268
+ nTSChecksum = np.sum(oDataset.TSSamples)
269
+ nVSChecksum = np.sum(oDataset.VSSamples)
270
+ print(nTSChecksum, nVSChecksum)
271
+
272
+ # // Unit Testing \\
273
+ assert nTSChecksum == 75.59110064555725
274
+ assert nVSChecksum == 19.22152183680314
275
+
276
+ # Seed None: 75.45033306926038 19.362289413100005
277
+ # Seed None: Parameter 2023: 75.59110064555725 19.22152183680314
278
+ # Seed 2023: Parameter 2023: 75.59110064555725 19.22152183680314 # First call with the same seed
279
+ # Seed 2023: Parameter None: 75.59110064555725 19.22152183680314 # First call with the same seed
280
+ # Seed 2025: 75.55118094349115 19.261441538869224
radnn/data/errors.py ADDED
@@ -0,0 +1,32 @@
1
+ # ......................................................................................
2
+ # MIT License
3
+
4
+ # Copyright (c) 2019-2025 Pantelis I. Kaplanoglou
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ # ......................................................................................
25
+ ERR_NO_CALLBACKS = "You should assign callbacks to the dataset perform proper random seed initialization for your framework."
26
+ ERR_NO_RANDOM_SEED_INITIALIZER_CALLBACK = "Callback method for random seed initialization has not been defined."
27
+
28
+ ERR_SUBSET_MUST_HAVE_TS = "A dataset must have at least a training subset."
29
+ ERR_SUBSET_INVALID_SETUP = "Invalid sample subset setup. Please use one of the valid kinds: 'training/train/ts', 'validation/val/vs', 'testing/test/us'."
30
+ ERR_SUBSET_MUST_HAVE_SAMPLES = "The subset has no samples, check the implementation of your dataset class."
31
+ ERR_DATASET_FOLDER_NOT_FOUND = "The dataset was not found under the folder %s"
32
+ ERR_DATASET_MUST_PROVIDE_LOCAL_FILESTORE = "You must provide a local filestore/path for the dataset"
@@ -0,0 +1,58 @@
1
+ # ......................................................................................
2
+ # MIT License
3
+
4
+ # Copyright (c) 2019-2025 Pantelis I. Kaplanoglou
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ # ......................................................................................
25
+ from abc import ABC, abstractmethod
26
+
27
+
28
+ # ======================================================================================================================
29
+ class SamplePreprocessor(ABC):
30
+ # --------------------------------------------------------------------------------------------------------------------
31
+ def __init__(self, settings):
32
+ self.settings = settings
33
+ self.ts_transform_augment, self.vs_transform_augment, self.us_transform_augment = self.prepare_pipelines()
34
+ # --------------------------------------------------------------------------------------------------------------------
35
+ def __call__(self, samples, **kwargs):
36
+ if self.us_transform_augment is None:
37
+ return samples
38
+ else:
39
+ return self.input_for_inference(input)
40
+ # --------------------------------------------------------------------------------------------------------------------
41
+ @abstractmethod
42
+ def input_for_inference(self, samples):
43
+ pass
44
+ # --------------------------------------------------------------------------------------------------------------------
45
+ @abstractmethod
46
+ def prepare_pipelines(self):
47
+ pass
48
+ # --------------------------------------------------------------------------------------------------------------------
49
+
50
+ # ======================================================================================================================
51
+ class VoidPreprocessor(SamplePreprocessor):
52
+ # --------------------------------------------------------------------------------------------------------------------
53
+ def input_for_inference(self, samples):
54
+ return samples
55
+ # --------------------------------------------------------------------------------------------------------------------
56
+ def prepare_pipelines(self):
57
+ return None, None, None
58
+ # --------------------------------------------------------------------------------------------------------------------