• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tonegas / nnodely / 13056267505

30 Jan 2025 04:04PM UTC coverage: 94.525% (+0.6%) from 93.934%
13056267505

push

github

web-flow
Merge pull request #48 from tonegas/develop

Develop merge on main release 1.0.0

1185 of 1215 new or added lines in 21 files covered. (97.53%)

3 existing lines in 2 files now uncovered.

9426 of 9972 relevant lines covered (94.52%)

0.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.21
/tests/test_export.py
1
import sys, os, unittest, torch, shutil
1✔
2
import numpy as np
1✔
3

4
from nnodely import *
1✔
5
from nnodely import relation
1✔
6
relation.CHECK_NAMES = False
1✔
7

8
import torch.onnx
1✔
9
import onnx
1✔
10
import onnxruntime as ort
1✔
11
import importlib
1✔
12

13
from nnodely.logger import logging, nnLogger
1✔
14
log = nnLogger(__name__, logging.CRITICAL)
1✔
15
log.setAllLevel(logging.CRITICAL)
1✔
16

17
# 11 Tests
18
# Test of export and import the network to a file in different format
19

20
class ModelyExportTest(unittest.TestCase):
1✔
21

22
    def TestAlmostEqual(self, data1, data2, precision=4):
1✔
NEW
23
        assert np.asarray(data1, dtype=np.float32).ndim == np.asarray(data2, dtype=np.float32).ndim, f'Inputs must have the same dimension! Received {type(data1)} and {type(data2)}'
×
NEW
24
        if type(data1) == type(data2) == list:
×
NEW
25
            self.assertEqual(len(data1),len(data2))
×
NEW
26
            for pred, label in zip(data1, data2):
×
NEW
27
                self.TestAlmostEqual(pred, label, precision=precision)
×
28
        else:
NEW
29
            self.assertAlmostEqual(data1, data2, places=precision)
×
30

31
    def __init__(self, *args, **kwargs):
1✔
32
        super(ModelyExportTest, self).__init__(*args, **kwargs)
1✔
33

34
        self.result_path = './results'
1✔
35
        self.test = Modely(visualizer=None, seed=42, workspace=self.result_path)
1✔
36

37
        x = Input('x')
1✔
38
        y = Input('y')
1✔
39
        z = Input('z')
1✔
40

41
        ## create the relations
42
        def myFun(K1, p1, p2):
1✔
43
            return K1 * p1 * p2
1✔
44

45
        K_x = Parameter('k_x', dimensions=1, tw=1, init=init_constant, init_params={'value': 1})
1✔
46
        K_y = Parameter('k_y', dimensions=1, tw=1)
1✔
47
        w = Parameter('w', dimensions=1, tw=1, init=init_constant, init_params={'value': 1})
1✔
48
        t = Parameter('t', dimensions=1, tw=1)
1✔
49
        c_v = Constant('c_v', tw=1, values=[[1], [2]])
1✔
50
        c = 5
1✔
51
        w_5 = Parameter('w_5', dimensions=1, tw=5)
1✔
52
        t_5 = Parameter('t_5', dimensions=1, tw=5)
1✔
53
        c_5 = [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]]
1✔
54
        parfun_x = ParamFun(myFun, parameters=[K_x], constants=[c_v])
1✔
55
        parfun_y = ParamFun(myFun, parameters=[K_y])
1✔
56
        parfun_z = ParamFun(myFun)
1✔
57
        fir_w = Fir(parameter=w_5)(x.tw(5))
1✔
58
        fir_t = Fir(parameter=t_5)(y.tw(5))
1✔
59
        time_part = TimePart(x.tw(5), i=1, j=3)
1✔
60
        sample_select = SampleSelect(x.sw(5), i=1)
1✔
61

62
        def fuzzyfun(x):
1✔
63
            return torch.tan(x)
×
64

65
        fuzzy = Fuzzify(output_dimension=4, range=[0, 4], functions=fuzzyfun)(x.tw(1))
1✔
66
        fuzzyTriang = Fuzzify(centers=[1, 2, 3, 7])(x.tw(1))
1✔
67

68
        out = Output('out', Fir(parfun_x(x.tw(1)) + parfun_y(y.tw(1), c_v)))
1✔
69
        # out = Output('out', Fir(parfun_x(x.tw(1))+parfun_y(y.tw(1),c_v)+parfun_z(x.tw(5),t_5,c_5)))
70
        out2 = Output('out2', Add(w, x.tw(1)) + Add(t, y.tw(1)) + Add(w, c))
1✔
71
        out3 = Output('out3', Add(fir_w, fir_t))
1✔
72
        out4 = Output('out4', Linear(output_dimension=1)(fuzzy+fuzzyTriang))
1✔
73
        out5 = Output('out5', Fir(time_part) + Fir(sample_select))
1✔
74
        out6 = Output('out6', LocalModel(output_function=Fir())(x.tw(1), fuzzy))
1✔
75

76
        self.test.addModel('modelA', out)
1✔
77
        self.test.addModel('modelB', [out2, out3, out4])
1✔
78
        self.test.addModel('modelC', [out4, out5, out6])
1✔
79
        self.test.addMinimize('error1', x.last(), out)
1✔
80
        self.test.addMinimize('error2', y.last(), out3, loss_function='rmse')
1✔
81
        self.test.addMinimize('error3', z.last(), out6, loss_function='rmse')
1✔
82

83
    def test_export_pt(self):
1✔
84
        if os.path.exists(self.test.getWorkspace()):
1✔
85
            shutil.rmtree(self.test.getWorkspace())
×
86
        os.makedirs(self.result_path, exist_ok=True)
1✔
87
        # Export torch file .pt
88
        # Save torch model and load it
89
        self.test.neuralizeModel(0.5)
1✔
90
        old_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
91
        self.test.saveTorchModel()
1✔
92
        self.test.neuralizeModel(clear_model=True)
1✔
93
        # The new_out is different from the old_out because the model is cleared
94
        new_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
95
        # The new_out_after_load is the same as the old_out because the model is loaded with the same parameters
96
        self.test.loadTorchModel()
1✔
97
        new_out_after_load = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
98

99
        with self.assertRaises(AssertionError):
1✔
100
            self.assertEqual(old_out, new_out)
1✔
101
        self.assertEqual(old_out, new_out_after_load)
1✔
102

103
        with self.assertRaises(RuntimeError):
1✔
104
            test2 = Modely(visualizer=None, workspace = self.result_path)
1✔
105
            # You need not neuralized model to load a torch model
106
            test2.loadTorchModel()
1✔
107

108
        if os.path.exists(self.test.getWorkspace()):
1✔
109
            shutil.rmtree(self.test.getWorkspace())
1✔
110

111
    def test_export_json_not_neuralized(self):
1✔
112
        if os.path.exists(self.test.getWorkspace()):
1✔
113
            shutil.rmtree(self.test.getWorkspace())
1✔
114
        os.makedirs(self.result_path, exist_ok=True)
1✔
115
        # Export json of nnodely model before neuralize
116
        # Save a not neuralized nnodely json model and load it
117
        self.test.saveModel()  # Save a model without parameter values and samples values
1✔
118
        with self.assertRaises(RuntimeError):
1✔
119
            self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
120
        self.test.loadModel()  # Load the nnodely model without parameter values
1✔
121
        with self.assertRaises(RuntimeError):
1✔
122
            self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
123
        test2 = Modely(visualizer=None, workspace=self.test.getWorkspace())
1✔
124
        test2.loadModel()  # Load the nnodely model with parameter values
1✔
125
        self.assertEqual(test2.model_def.json, self.test.model_def.json)
1✔
126

127
        if os.path.exists(self.test.getWorkspace()):
1✔
128
            shutil.rmtree(self.test.getWorkspace())
1✔
129

130
    def test_export_json_untrained(self):
1✔
131
        if os.path.exists(self.test.getWorkspace()):
1✔
132
            shutil.rmtree(self.test.getWorkspace())
×
133
        os.makedirs(self.result_path, exist_ok=True)
1✔
134
        # Export json of nnodely model
135
        # Save a untrained nnodely json model and load it
136
        # the new_out and new_out_after_load are different because the model saved model is not trained
137
        self.test.neuralizeModel(0.5)
1✔
138
        old_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
139
        self.test.saveModel()  # Save a model without parameter values
1✔
140
        self.test.neuralizeModel(clear_model=True)  # Create a new torch model
1✔
141
        new_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
142
        self.test.loadModel()  # Load the nnodely model without parameter values
1✔
143
        # Use the preloaded torch model for inference
144
        with self.assertRaises(RuntimeError):
1✔
145
            self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
146
        self.test.neuralizeModel(0.5)
1✔
147
        new_out_after_load = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
148
        with self.assertRaises(AssertionError):
1✔
149
            self.assertEqual(old_out, new_out)
1✔
150
        with self.assertRaises(AssertionError):
1✔
151
            self.assertEqual(new_out, new_out_after_load)
1✔
152

153
        if os.path.exists(self.test.getWorkspace()):
1✔
154
            shutil.rmtree(self.test.getWorkspace())
1✔
155

156
    def test_export_json_trained(self):
1✔
157
        if os.path.exists(self.test.getWorkspace()):
1✔
158
            shutil.rmtree(self.test.getWorkspace())
×
159
        os.makedirs(self.result_path, exist_ok=True)
1✔
160
        # Export json of nnodely model with parameter valuess
161
        # The old_out is the same as the new_out_after_load because the model is loaded with the same parameters
162
        self.test.neuralizeModel(0.5)
1✔
163
        old_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
164
        self.test.neuralizeModel()  # Load the parameter from torch model to nnodely model json
1✔
165
        self.test.saveModel()  # Save the model with and without parameter values
1✔
166
        self.test.neuralizeModel(clear_model=True)  # Create a new torch model
1✔
167
        new_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
168
        self.test.loadModel()  # Load the nnodely model with parameter values
1✔
169
        with self.assertRaises(RuntimeError):
1✔
170
            self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
171
        self.test.neuralizeModel()
1✔
172
        new_out_after_load = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
173
        with self.assertRaises(AssertionError):
1✔
174
            self.assertEqual(old_out, new_out)
1✔
175
        with self.assertRaises(AssertionError):
1✔
176
            self.assertEqual(new_out, new_out_after_load)
1✔
177
        self.assertEqual(old_out, new_out_after_load)
1✔
178

179
        if os.path.exists(self.test.getWorkspace()):
1✔
180
            shutil.rmtree(self.test.getWorkspace())
1✔
181

182
    def test_import_json_new_object(self):
1✔
183
        if os.path.exists(self.test.getWorkspace()):
1✔
184
            shutil.rmtree(self.test.getWorkspace())
×
185
        os.makedirs(self.result_path, exist_ok=True)
1✔
186
        # Import nnodely json model in a new object
187
        self.test.neuralizeModel(0.5)
1✔
188
        old_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
189
        self.test.neuralizeModel()
1✔
190
        self.test.saveModel()  # Save the model with and without parameter values
1✔
191
        test2 = Modely(visualizer=None, workspace=self.test.getWorkspace())
1✔
192
        test2.loadModel()  # Load the nnodely model with parameter values
1✔
193
        with self.assertRaises(RuntimeError):
1✔
194
            test2({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
195
        test2.neuralizeModel()
1✔
196
        new_model_out_after_load = test2({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
197
        self.assertEqual(old_out, new_model_out_after_load)
1✔
198

199
        if os.path.exists(self.test.getWorkspace()):
1✔
200
            shutil.rmtree(self.test.getWorkspace())
1✔
201

202
    def test_export_torch_script(self):
1✔
203
        if os.path.exists(self.test.getWorkspace()):
1✔
204
            shutil.rmtree(self.test.getWorkspace())
×
205
        os.makedirs(self.result_path, exist_ok=True)
1✔
206
        # Export and import of a torch script .py
207
        # The old_out is the same as the new_out_after_load because the model is loaded with the same parameters
208
        with self.assertRaises(RuntimeError):
1✔
209
            self.test.exportPythonModel() # The model is not neuralized yet
1✔
210
        self.test.neuralizeModel(0.5)
1✔
211
        old_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
212
        self.test.exportPythonModel()  # Export the trace model
1✔
213
        self.test.neuralizeModel(clear_model=True)  # Create a new torch model
1✔
214
        new_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
215
        self.test.importPythonModel()  # Import the tracer model
1✔
216
        with self.assertRaises(RuntimeError):
1✔
217
            self.test.exportPythonModel() # The model is traced
1✔
218
        # Perform inference with the imported tracer model
219
        new_out_after_load = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
220
        with self.assertRaises(AssertionError):
1✔
221
             self.assertEqual(old_out, new_out)
1✔
222
        self.assertEqual(old_out, new_out_after_load)
1✔
223

224
        if os.path.exists(self.test.getWorkspace()):
1✔
225
            shutil.rmtree(self.test.getWorkspace())
1✔
226

227
    def test_export_torch_script_new_object(self):
1✔
228
        if os.path.exists(self.test.getWorkspace()):
1✔
229
            shutil.rmtree(self.test.getWorkspace())
×
230
        os.makedirs(self.result_path, exist_ok=True)
1✔
231
        # Import of a torch script .py
232
        self.test.neuralizeModel(0.5,clear_model=True)
1✔
233
        old_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
234
        self.test.exportPythonModel()  # Export the trace model
1✔
235
        self.test.neuralizeModel(clear_model=True)
1✔
236
        test2 = Modely(visualizer=None, workspace=self.test.getWorkspace())
1✔
237
        test2.importPythonModel()  # Load the nnodely model with parameter values
1✔
238
        with self.assertRaises(RuntimeError):
1✔
239
            test2.exportPythonModel() # The model is traced
1✔
240
        new_out_after_load = test2({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
241
        self.assertEqual(old_out, new_out_after_load)
1✔
242

243
        if os.path.exists(self.test.getWorkspace()):
1✔
244
            shutil.rmtree(self.test.getWorkspace())
1✔
245

246
    def test_export_trained_torch_script(self):
1✔
247
        if os.path.exists(self.test.getWorkspace()):
1✔
248
            shutil.rmtree(self.test.getWorkspace())
×
249
        os.makedirs(self.result_path, exist_ok=True)
1✔
250
        # Perform training on an imported tracer model
251
        data_x = np.arange(0.0, 1, 0.1)
1✔
252
        data_y = np.arange(0.0, 1, 0.1)
1✔
253
        a, b = -1.0, 2.0
1✔
254
        dataset = {'x': data_x, 'y': data_y, 'z': a * data_x + b * data_y}
1✔
255
        params = {'num_of_epochs': 1, 'lr': 0.01}
1✔
256
        self.test.neuralizeModel(0.5,clear_model=True)
1✔
257
        old_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
258
        self.test.exportPythonModel()  # Export the trace model
1✔
259
        self.test.loadData(name='dataset', source=dataset)  # Create the dataset
1✔
260
        self.test.trainModel(optimizer='SGD', training_params=params)  # Train the traced model
1✔
261
        new_out_after_train = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
262
        with self.assertRaises(AssertionError):
1✔
263
             self.assertEqual(old_out, new_out_after_train)
1✔
264

265
        if os.path.exists(self.test.getWorkspace()):
1✔
266
            shutil.rmtree(self.test.getWorkspace())
1✔
267

268
    def test_export_torch_script_new_object_train(self):
1✔
269
        if os.path.exists(self.test.getWorkspace()):
1✔
270
            shutil.rmtree(self.test.getWorkspace())
×
271
        os.makedirs(self.result_path, exist_ok=True)
1✔
272
        # Perform training on an imported new tracer model
273
        self.test.neuralizeModel(0.5, clear_model=True)
1✔
274
        old_out = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
275
        self.test.exportPythonModel()  # Export the trace model
1✔
276
        data_x = np.arange(0.0, 1, 0.1)
1✔
277
        data_y = np.arange(0.0, 1, 0.1)
1✔
278
        a, b = -1.0, 2.0
1✔
279
        dataset = {'x': data_x, 'y': data_y, 'z': a * data_x + b * data_y}
1✔
280
        params = {'num_of_epochs': 1, 'lr': 0.01}
1✔
281
        self.test.loadData(name='dataset', source=dataset)  # Create the dataset
1✔
282
        self.test.trainModel(optimizer='SGD', training_params=params)  # Train the traced model
1✔
283
        old_out_after_train = self.test({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
284
        with self.assertRaises(AssertionError):
1✔
285
             self.assertEqual(old_out, old_out_after_train)
1✔
286
        test2 = Modely(visualizer=None, workspace=self.test.getWorkspace())
1✔
287
        test2.importPythonModel()  # Load the nnodely model with parameter values
1✔
288
        test2.loadData(name='dataset', source=dataset)  # Create the dataset
1✔
289
        test2.trainModel(optimizer='SGD', training_params=params)  # Train the traced model
1✔
290
        new_out_after_train = test2({'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'y': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
1✔
291
        with self.assertRaises(AssertionError):
1✔
292
             self.assertEqual(old_out, new_out_after_train)
1✔
293
        self.assertEqual(old_out_after_train, new_out_after_train)
1✔
294

295
        if os.path.exists(self.test.getWorkspace()):
1✔
296
            shutil.rmtree(self.test.getWorkspace())
1✔
297

298
    def test_export_onnx(self):
1✔
299
        if os.path.exists(self.test.getWorkspace()):
1✔
300
            shutil.rmtree(self.test.getWorkspace())
×
301
        os.makedirs(self.result_path, exist_ok=True)
1✔
302

303
        self.test.neuralizeModel(0.5, clear_model=True)
1✔
304
        # Export the all models in onnx format
305
        self.test.exportONNX(['x', 'y'], ['out', 'out2', 'out3', 'out4', 'out5', 'out6'])  # Export the onnx model
1✔
306
        # Export only the modelB in onnx format
307
        self.test.exportONNX(['x', 'y'], ['out3', 'out4', 'out2'], ['modelB'])  # Export the onnx model
1✔
308
        self.assertTrue(os.path.exists(os.path.join(self.test.getWorkspace(), 'onnx', 'net.onnx')))
1✔
309
        self.assertTrue(os.path.exists(os.path.join(self.test.getWorkspace(), 'onnx', 'net_modelB.onnx')))
1✔
310

311
        if os.path.exists(self.test.getWorkspace()):
1✔
312
            shutil.rmtree(self.test.getWorkspace())
1✔
313

314
    def test_export_report(self):
1✔
315
        if os.path.exists(self.test.getWorkspace()):
1✔
316
            shutil.rmtree(self.test.getWorkspace())
×
317
        os.makedirs(self.result_path, exist_ok=True)
1✔
318

319
        self.test.resetSeed(42)
1✔
320
        self.test.neuralizeModel(0.5, clear_model=True)
1✔
321
        data_x = np.arange(0.0, 10, 0.1)
1✔
322
        data_y = np.arange(0.0, 10, 0.1)
1✔
323
        a, b = -1.0, 2.0
1✔
324
        dataset = {'x': data_x, 'y': data_y, 'z': a * data_x + b * data_y}
1✔
325
        params = {'num_of_epochs': 20, 'lr': 0.01}
1✔
326
        self.test.loadData(name='dataset', source=dataset)  # Create the dataset
1✔
327
        self.test.trainModel(optimizer='SGD', training_params=params)  # Train the traced model
1✔
328
        self.test.exportReport()
1✔
329

330
        if os.path.exists(self.test.getWorkspace()):
1✔
331
            shutil.rmtree(self.test.getWorkspace())
1✔
332

333
if __name__ == '__main__':
1✔
334
    unittest.main()
×
335

336

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc