surrogates_interface 4.0.1__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.
@@ -0,0 +1,617 @@
1
+ # -*- coding: utf-8 -*-
2
+ import re
3
+ import uuid
4
+
5
+ import h5py
6
+ import numpy as np
7
+ import numpy.testing as npt
8
+ import pytest
9
+ from sklearn.decomposition import PCA
10
+ from sklearn.preprocessing import MinMaxScaler, PowerTransformer, StandardScaler
11
+ from sklearn.preprocessing._data import QuantileTransformer
12
+
13
+ from surrogates_interface.transformers import PCA as PCASI
14
+ from surrogates_interface.transformers import MinMaxScaler as MinMaxScalerSI
15
+ from surrogates_interface.transformers import PowerTransformer as PowerTransformerSI
16
+ from surrogates_interface.transformers import PowerTransformerYeoJohnson
17
+ from surrogates_interface.transformers import StandardScaler as StandardScalerSI
18
+ from surrogates_interface.transformers import Transformer
19
+
20
+
21
+ class TestMinMaxScaler:
22
+ @staticmethod
23
+ @pytest.fixture(scope="class")
24
+ def make_data():
25
+ rng = np.random.default_rng(seed=1234)
26
+ n_samples = 10
27
+ x = np.column_stack(
28
+ (
29
+ rng.uniform(low=-5.0, high=20.0, size=(n_samples,)),
30
+ rng.uniform(low=1.0, high=12.0, size=(n_samples,)),
31
+ rng.uniform(low=-23.0, high=+101.0, size=(n_samples,)),
32
+ )
33
+ )
34
+ # n_features = x.shape[1]
35
+
36
+ sklearn_scaler = MinMaxScaler(feature_range=(-1.0, +1.0), copy=True, clip=False)
37
+ x_transformed = sklearn_scaler.fit_transform(x)
38
+ return sklearn_scaler, x, x_transformed
39
+
40
+ @pytest.fixture(scope="class")
41
+ def si_scaler(self, make_data):
42
+ # test_from_sklearn
43
+ sklearn_scaler, _, _ = make_data
44
+ si_scaler = Transformer.from_sklearn(sklearn_scaler)
45
+ npt.assert_array_equal(si_scaler.scale_, sklearn_scaler.scale_)
46
+ npt.assert_array_equal(si_scaler.min_, sklearn_scaler.min_)
47
+ return si_scaler
48
+
49
+ @staticmethod
50
+ def test_clip():
51
+ scaler_with_clip = MinMaxScaler(clip=True)
52
+ with pytest.raises(
53
+ ValueError,
54
+ match=re.escape(
55
+ "clip is not supported, because it cannot be differentiated."
56
+ ),
57
+ ):
58
+ MinMaxScalerSI.from_sklearn(scaler_with_clip)
59
+
60
+ @staticmethod
61
+ def test_transform_outofplace(make_data, si_scaler):
62
+ _, x, x_transformed = make_data
63
+ y_si = si_scaler.transform(x, inplace=False)
64
+ npt.assert_array_almost_equal_nulp(y_si, x_transformed)
65
+
66
+ @staticmethod
67
+ def test_transform_inplace(make_data, si_scaler):
68
+ _, x, x_transformed = make_data
69
+ y_si = x.copy()
70
+ si_scaler.transform(y_si, inplace=True)
71
+ npt.assert_array_almost_equal_nulp(y_si, x_transformed)
72
+
73
+ @staticmethod
74
+ def test_inverse_transform_outofplace(make_data, si_scaler):
75
+ _, x, x_transformed = make_data
76
+ y_si = si_scaler.inverse_transform(x_transformed, inplace=False)
77
+ npt.assert_array_almost_equal_nulp(y_si, x, nulp=2)
78
+
79
+ @staticmethod
80
+ def test_inverse_transform_inplace(make_data, si_scaler):
81
+ _, x, x_transformed = make_data
82
+ y_si = x_transformed.copy()
83
+ si_scaler.inverse_transform(y_si, inplace=True)
84
+ npt.assert_array_almost_equal_nulp(y_si, x, nulp=2)
85
+
86
+ @staticmethod
87
+ def test_transform_gradient(make_data, si_scaler):
88
+ _, x, _ = make_data
89
+ y_exact = si_scaler.transform_gradient(x)
90
+ h = 1e-6
91
+ y_fd = (
92
+ si_scaler.transform(x + h, inplace=False)
93
+ - si_scaler.transform(x, inplace=False)
94
+ ) / h
95
+ npt.assert_allclose(y_exact, y_fd)
96
+
97
+ @staticmethod
98
+ def test_inverse_transform_gradient(make_data, si_scaler):
99
+ _, x, x_transformed = make_data
100
+ y_exact = si_scaler.inverse_transform_gradient(x_transformed)
101
+ h = 1e-6
102
+ y_fd = (
103
+ si_scaler.inverse_transform(x_transformed + h, inplace=False)
104
+ - si_scaler.inverse_transform(x_transformed, inplace=False)
105
+ ) / h
106
+ npt.assert_allclose(y_exact, y_fd)
107
+
108
+ @staticmethod
109
+ def test_eq():
110
+ obj_1 = MinMaxScalerSI(
111
+ np.array([1.1, 10.4, 3.7]), np.array([-3.0, -50.0, +21.0])
112
+ )
113
+ obj_2 = MinMaxScalerSI(
114
+ np.array([1.1, 10.4, 3.7]), np.array([-3.0, -50.0, +21.0])
115
+ )
116
+ assert obj_1 == obj_2
117
+
118
+ @staticmethod
119
+ def test_eq_wrong_type():
120
+ obj_1 = MinMaxScalerSI(
121
+ np.array([1.1, 10.4, 3.7]), np.array([-3.0, -50.0, +21.0])
122
+ )
123
+ obj_2 = StandardScalerSI(np.array([1.1, 10.4]), np.array([-3.0, -50.0]))
124
+ assert not (obj_1 == obj_2)
125
+
126
+
127
+ class TestStandardScaler:
128
+ @staticmethod
129
+ @pytest.fixture(scope="class")
130
+ def make_data():
131
+ rng = np.random.default_rng(seed=1234)
132
+ n_samples = 10
133
+ x = np.column_stack(
134
+ (
135
+ rng.uniform(low=-5.0, high=20.0, size=(n_samples,)),
136
+ rng.uniform(low=1.0, high=12.0, size=(n_samples,)),
137
+ rng.uniform(low=-23.0, high=+101.0, size=(n_samples,)),
138
+ )
139
+ )
140
+ # n_features = x.shape[1]
141
+
142
+ sklearn_scaler = StandardScaler(copy=True, with_mean=True, with_std=True)
143
+ x_transformed = sklearn_scaler.fit_transform(x)
144
+ return sklearn_scaler, x, x_transformed
145
+
146
+ @staticmethod
147
+ @pytest.fixture(scope="class")
148
+ def si_scaler(make_data):
149
+ # test_from_sklearn
150
+ sklearn_scaler, _, _ = make_data
151
+ si_scaler = Transformer.from_sklearn(sklearn_scaler)
152
+ npt.assert_array_almost_equal_nulp(si_scaler.scale_, sklearn_scaler.scale_)
153
+ npt.assert_array_equal(si_scaler.mean_, sklearn_scaler.mean_)
154
+ return si_scaler
155
+
156
+ @staticmethod
157
+ def test_transform_outofplace(make_data, si_scaler):
158
+ _, x, x_transformed = make_data
159
+ y_si = si_scaler.transform(x, inplace=False)
160
+ npt.assert_array_almost_equal_nulp(y_si, x_transformed, nulp=180)
161
+
162
+ @staticmethod
163
+ def test_transform_inplace(make_data, si_scaler):
164
+ _, x, x_transformed = make_data
165
+ y_si = x.copy()
166
+ si_scaler.transform(y_si, inplace=True)
167
+ npt.assert_array_almost_equal_nulp(y_si, x_transformed, nulp=180)
168
+
169
+ @staticmethod
170
+ def test_inverse_transform_outofplace(make_data, si_scaler):
171
+ _, x, x_transformed = make_data
172
+ y_si = si_scaler.inverse_transform(x_transformed, inplace=False)
173
+ npt.assert_array_almost_equal_nulp(y_si, x, nulp=2)
174
+
175
+ @staticmethod
176
+ def test_inverse_transform_inplace(make_data, si_scaler):
177
+ _, x, x_transformed = make_data
178
+ y_si = x_transformed.copy()
179
+ si_scaler.inverse_transform(y_si, inplace=True)
180
+ npt.assert_array_almost_equal_nulp(y_si, x, nulp=2)
181
+
182
+ @staticmethod
183
+ def test_transform_gradient(make_data, si_scaler):
184
+ _, x, _ = make_data
185
+ y_exact = si_scaler.transform_gradient(x)
186
+ h = 1e-6
187
+ y_fd = (
188
+ si_scaler.transform(x + h, inplace=False)
189
+ - si_scaler.transform(x, inplace=False)
190
+ ) / h
191
+ npt.assert_allclose(y_exact, y_fd)
192
+
193
+ @staticmethod
194
+ def test_inverse_transform_gradient(make_data, si_scaler):
195
+ _, x, x_transformed = make_data
196
+ y_exact = si_scaler.inverse_transform_gradient(x_transformed)
197
+ h = 1e-6
198
+ y_fd = (
199
+ si_scaler.inverse_transform(x_transformed + h, inplace=False)
200
+ - si_scaler.inverse_transform(x_transformed, inplace=False)
201
+ ) / h
202
+ npt.assert_allclose(y_exact, y_fd)
203
+
204
+ @staticmethod
205
+ def test_eq():
206
+ obj_1 = StandardScalerSI(np.array([1.1, 10.4]), np.array([-3.0, -50.0]))
207
+ obj_2 = StandardScalerSI(np.array([1.1, 10.4]), np.array([-3.0, -50.0]))
208
+ assert obj_1 == obj_2
209
+
210
+ @staticmethod
211
+ def test_eq_wrong_type():
212
+ obj_1 = StandardScalerSI(np.array([1.1, 10.4]), np.array([-3.0, -50.0]))
213
+ obj_2 = MinMaxScalerSI(
214
+ np.array([1.1, 10.4, 3.7]), np.array([-3.0, -50.0, +21.0])
215
+ )
216
+ assert not (obj_1 == obj_2)
217
+
218
+
219
+ class TestPCA:
220
+ @staticmethod
221
+ @pytest.fixture(scope="class")
222
+ def make_data_with_whitening():
223
+ rng = np.random.default_rng(seed=1234)
224
+ n_samples = 100
225
+ n_features_original = 5
226
+ x = rng.normal(
227
+ loc=np.arange(n_features_original),
228
+ scale=np.array([1.0, 5.0, 2.0, 20.0, 6.0]),
229
+ size=(n_samples, n_features_original),
230
+ )
231
+ # Introduce linear correlation between some components.
232
+ x[:, 1] = 2.0 * x[:, 0]
233
+ x[:, 2] = 3.0 * x[:, 0] - 5.0
234
+ sklearn_pca = PCA(n_components=3, whiten=True)
235
+ x_transformed = sklearn_pca.fit_transform(x)
236
+ # Test: with n_components=n_features_original,
237
+ # the last 2 elements of sklearn_pca.singular_values_ are small.
238
+ return sklearn_pca, x, x_transformed
239
+
240
+ @staticmethod
241
+ @pytest.fixture(scope="class")
242
+ def make_data_without_whitening():
243
+ rng = np.random.default_rng(seed=1234)
244
+ n_samples = 100
245
+ n_features_original = 5
246
+ x = rng.normal(
247
+ loc=np.arange(n_features_original),
248
+ scale=np.array([1.0, 5.0, 2.0, 20.0, 6.0]),
249
+ size=(n_samples, n_features_original),
250
+ )
251
+ # Introduce linear correlation between some components.
252
+ x[:, 1] = 2.0 * x[:, 0]
253
+ x[:, 2] = 3.0 * x[:, 0] - 5.0
254
+ sklearn_pca = PCA(n_components=3, whiten=False)
255
+ x_transformed = sklearn_pca.fit_transform(x)
256
+ # Test: with n_components=n_features_original,
257
+ # the last 2 elements of sklearn_pca.singular_values_ are small.
258
+ return sklearn_pca, x, x_transformed
259
+
260
+ @staticmethod
261
+ @pytest.fixture(scope="class")
262
+ def si_pca_with_whitening(make_data_with_whitening):
263
+ # test_from_sklearn
264
+ sklearn_pca, _, _ = make_data_with_whitening
265
+ si_pca = Transformer.from_sklearn(sklearn_pca)
266
+ npt.assert_array_almost_equal_nulp(
267
+ np.sqrt(sklearn_pca.explained_variance_), si_pca.explained_std_
268
+ )
269
+ return si_pca
270
+
271
+ @staticmethod
272
+ @pytest.fixture(scope="class")
273
+ def si_pca_without_whitening(make_data_without_whitening):
274
+ # test_from_sklearn
275
+ sklearn_pca, _, _ = make_data_without_whitening
276
+ si_pca = Transformer.from_sklearn(sklearn_pca)
277
+ npt.assert_array_almost_equal_nulp(
278
+ np.sqrt(sklearn_pca.explained_variance_), si_pca.explained_std_
279
+ )
280
+ return si_pca
281
+
282
+ @staticmethod
283
+ def test_transform_outofplace_with_whitening(
284
+ make_data_with_whitening, si_pca_with_whitening
285
+ ):
286
+ _, x, x_transformed = make_data_with_whitening
287
+ y_si = si_pca_with_whitening.transform(x, inplace=False)
288
+ npt.assert_array_almost_equal_nulp(y_si, x_transformed, nulp=2500)
289
+
290
+ @staticmethod
291
+ def test_transform_inplace_with_whitening(
292
+ make_data_with_whitening, si_pca_with_whitening
293
+ ):
294
+ _, x, _ = make_data_with_whitening
295
+ with pytest.raises(
296
+ ValueError,
297
+ match=re.escape("The PCA transformation cannot be done inplace."),
298
+ ):
299
+ si_pca_with_whitening.transform(x, inplace=True)
300
+
301
+ @staticmethod
302
+ def test_inverse_transform_outofplace_with_whitening(
303
+ make_data_with_whitening, si_pca_with_whitening
304
+ ):
305
+ _, x, x_transformed = make_data_with_whitening
306
+ y_si = si_pca_with_whitening.inverse_transform(x_transformed, inplace=False)
307
+ npt.assert_array_almost_equal_nulp(y_si, x, nulp=5900)
308
+
309
+ @staticmethod
310
+ def test_inverse_transform_inplace(make_data_with_whitening, si_pca_with_whitening):
311
+ _, _, x_transformed = make_data_with_whitening
312
+ with pytest.raises(
313
+ ValueError,
314
+ match=re.escape("The PCA inverse transformation cannot be done inplace."),
315
+ ):
316
+ si_pca_with_whitening.inverse_transform(x_transformed, inplace=True)
317
+
318
+ @staticmethod
319
+ def test_transform_outofplace_without_whitening(
320
+ make_data_without_whitening, si_pca_without_whitening
321
+ ):
322
+ _, x, x_transformed = make_data_without_whitening
323
+ y_si = si_pca_without_whitening.transform(x, inplace=False)
324
+ npt.assert_array_almost_equal_nulp(y_si, x_transformed, nulp=2500)
325
+
326
+ @staticmethod
327
+ def test_transform_inplace_without_whitening(
328
+ make_data_without_whitening, si_pca_without_whitening
329
+ ):
330
+ _, x, _ = make_data_without_whitening
331
+ with pytest.raises(
332
+ ValueError,
333
+ match=re.escape("The PCA transformation cannot be done inplace."),
334
+ ):
335
+ si_pca_without_whitening.transform(x, inplace=True)
336
+
337
+ @staticmethod
338
+ def test_inverse_transform_outofplace_without_whitening(
339
+ make_data_without_whitening, si_pca_without_whitening
340
+ ):
341
+ _, x, x_transformed = make_data_without_whitening
342
+ y_si = si_pca_without_whitening.inverse_transform(x_transformed, inplace=False)
343
+ npt.assert_array_almost_equal_nulp(y_si, x, nulp=5900)
344
+
345
+ @staticmethod
346
+ def test_transform_gradient_with_whitening(
347
+ make_data_with_whitening, si_pca_with_whitening
348
+ ):
349
+ _, x, _ = make_data_with_whitening
350
+ # Compute exact gradient.
351
+ y_exact = si_pca_with_whitening.transform_gradient(x)
352
+ # Compute gradient with central finite differences.
353
+ y_fd = np.zeros(
354
+ (
355
+ x.shape[0],
356
+ si_pca_with_whitening.n_components,
357
+ si_pca_with_whitening.n_features,
358
+ )
359
+ )
360
+ h = 1e-5
361
+ for i in range(x.shape[1]):
362
+ xm = x.copy()
363
+ xp = x.copy()
364
+ xm[:, i] -= h
365
+ xp[:, i] += h
366
+ y_fd[:, :, i] = si_pca_with_whitening.transform(
367
+ xp, inplace=False
368
+ ) - si_pca_with_whitening.transform(xm, inplace=False)
369
+ y_fd /= 2.0 * h
370
+ npt.assert_allclose(y_exact, y_fd)
371
+
372
+ @staticmethod
373
+ def test_transform_gradient_without_whitening(
374
+ make_data_without_whitening, si_pca_without_whitening
375
+ ):
376
+ _, x, _ = make_data_without_whitening
377
+ # Compute exact gradient.
378
+ y_exact = si_pca_without_whitening.transform_gradient(x)
379
+ # Compute gradient with central finite differences.
380
+ y_fd = np.zeros(
381
+ (
382
+ x.shape[0],
383
+ si_pca_without_whitening.n_components,
384
+ si_pca_without_whitening.n_features,
385
+ )
386
+ )
387
+ h = 1e-5
388
+ for i in range(x.shape[1]):
389
+ xm = x.copy()
390
+ xp = x.copy()
391
+ xm[:, i] -= h
392
+ xp[:, i] += h
393
+ y_fd[:, :, i] = si_pca_without_whitening.transform(
394
+ xp, inplace=False
395
+ ) - si_pca_without_whitening.transform(xm, inplace=False)
396
+ y_fd /= 2.0 * h
397
+ npt.assert_allclose(y_exact, y_fd)
398
+
399
+ @staticmethod
400
+ def test_inverse_transform_gradient_with_whitening(
401
+ make_data_with_whitening, si_pca_with_whitening
402
+ ):
403
+ _, _, x_transformed = make_data_with_whitening
404
+ # Compute exact gradient.
405
+ y_exact = si_pca_with_whitening.inverse_transform_gradient(x_transformed)
406
+ # Compute gradient with central finite differences.
407
+ y_fd = np.zeros(
408
+ (
409
+ x_transformed.shape[0],
410
+ si_pca_with_whitening.n_features,
411
+ si_pca_with_whitening.n_components,
412
+ )
413
+ )
414
+ h = 1e-6
415
+ for i in range(x_transformed.shape[1]):
416
+ xm = x_transformed.copy()
417
+ xp = x_transformed.copy()
418
+ xm[:, i] -= h
419
+ xp[:, i] += h
420
+ y_fd[:, :, i] = si_pca_with_whitening.inverse_transform(
421
+ xp, inplace=False
422
+ ) - si_pca_with_whitening.inverse_transform(xm, inplace=False)
423
+ y_fd /= 2.0 * h
424
+ npt.assert_allclose(y_exact, y_fd)
425
+
426
+ @staticmethod
427
+ def test_inverse_transform_gradient_without_whitening(
428
+ make_data_without_whitening, si_pca_without_whitening
429
+ ):
430
+ _, _, x_transformed = make_data_without_whitening
431
+ # Compute exact gradient.
432
+ y_exact = si_pca_without_whitening.inverse_transform_gradient(x_transformed)
433
+ # Compute gradient with central finite differences.
434
+ y_fd = np.zeros(
435
+ (
436
+ x_transformed.shape[0],
437
+ si_pca_without_whitening.n_features,
438
+ si_pca_without_whitening.n_components,
439
+ )
440
+ )
441
+ h = 1e-5
442
+ for i in range(x_transformed.shape[1]):
443
+ xm = x_transformed.copy()
444
+ xp = x_transformed.copy()
445
+ xm[:, i] -= h
446
+ xp[:, i] += h
447
+ y_fd[:, :, i] = si_pca_without_whitening.inverse_transform(
448
+ xp, inplace=False
449
+ ) - si_pca_without_whitening.inverse_transform(xm, inplace=False)
450
+ y_fd /= 2.0 * h
451
+ npt.assert_allclose(y_exact, y_fd)
452
+
453
+ @staticmethod
454
+ def test_eq_different_type(si_pca_with_whitening):
455
+ obj_2 = StandardScalerSI(np.array([1.0]), np.array([0.5]))
456
+ assert not si_pca_with_whitening == obj_2
457
+
458
+ @staticmethod
459
+ def test_save_load(si_pca_with_whitening):
460
+ path = f"./{str(uuid.uuid4())}.h5"
461
+ with h5py.File(path, "w") as fid:
462
+ si_pca_with_whitening._save_h5(fid)
463
+ with h5py.File(path, "r") as fid:
464
+ si_pca_saved = PCASI._load_h5(fid)
465
+ assert si_pca_with_whitening == si_pca_saved
466
+
467
+
468
+ class TestPowerTransformerYeoJohnson:
469
+ @staticmethod
470
+ @pytest.fixture(scope="class")
471
+ def make_data():
472
+ rng = np.random.default_rng(seed=1234)
473
+ n_samples = 100
474
+ # We need to cover 4 cases, 2 with positive values and 2 with negative ones.
475
+ x = rng.uniform(low=-5.0, high=5.0, size=(n_samples, 4))
476
+ sklearn_scaler = PowerTransformer(
477
+ method="yeo-johnson", standardize=False, copy=True
478
+ )
479
+ sklearn_scaler.fit(x)
480
+ # Overwrite lambdas_, so that we can test everything.
481
+ sklearn_scaler.lambdas_ = np.array([0.5, 0.0, 3.5, 2.0])
482
+ x_transformed = sklearn_scaler.transform(x)
483
+ return sklearn_scaler, x, x_transformed
484
+
485
+ @pytest.fixture(scope="class")
486
+ def si_scaler(self, make_data):
487
+ # test_from_sklearn
488
+ sklearn_scaler, _, _ = make_data
489
+ si_scaler = Transformer.from_sklearn(sklearn_scaler)
490
+ npt.assert_array_almost_equal_nulp(si_scaler.lambdas_, sklearn_scaler.lambdas_)
491
+ return si_scaler
492
+
493
+ @staticmethod
494
+ def test_standardize():
495
+ with pytest.raises(
496
+ NotImplementedError,
497
+ match=re.escape(
498
+ "The standardize option is not supported. Please add a StandardScaler."
499
+ ),
500
+ ):
501
+ PowerTransformerSI(np.array([]), standardize=True)
502
+
503
+ @staticmethod
504
+ def test_transform_outofplace(make_data, si_scaler):
505
+ _, x, x_transformed = make_data
506
+ y_si = si_scaler.transform(x, inplace=False)
507
+ npt.assert_array_almost_equal_nulp(y_si, x_transformed)
508
+
509
+ @staticmethod
510
+ def test_transform_inplace(make_data, si_scaler):
511
+ _, x, x_transformed = make_data
512
+ y_si = x.copy()
513
+ si_scaler.transform(y_si, inplace=True)
514
+ npt.assert_array_almost_equal_nulp(y_si, x_transformed)
515
+
516
+ @staticmethod
517
+ def test_inverse_transform_outofplace(make_data, si_scaler):
518
+ _, x, x_transformed = make_data
519
+ y_si = si_scaler.inverse_transform(x_transformed, inplace=False)
520
+ npt.assert_array_almost_equal_nulp(y_si, x, nulp=35)
521
+
522
+ @staticmethod
523
+ def test_inverse_transform_inplace(make_data, si_scaler):
524
+ _, x, x_transformed = make_data
525
+ y_si = x_transformed.copy()
526
+ si_scaler.inverse_transform(y_si, inplace=True)
527
+ npt.assert_array_almost_equal_nulp(y_si, x, nulp=35)
528
+
529
+ @staticmethod
530
+ def test_transform_gradient(make_data, si_scaler):
531
+ _, x, x_transformed = make_data
532
+ # Compute exact gradient.
533
+ y_exact = si_scaler.transform_gradient(x)
534
+ # Compute gradient with central finite differences.
535
+ h = 1e-6
536
+ y_fd = (
537
+ si_scaler.transform(x + h, inplace=False)
538
+ - si_scaler.transform(x - h, inplace=False)
539
+ ) / (2 * h)
540
+ npt.assert_allclose(y_exact, y_fd)
541
+
542
+ @staticmethod
543
+ def test_inverse_transform_gradient(make_data, si_scaler):
544
+ _, x, x_transformed = make_data
545
+ y_exact = si_scaler.inverse_transform_gradient(x_transformed)
546
+ h = 1e-6
547
+ y_fd = (
548
+ si_scaler.inverse_transform(x_transformed + h, inplace=False)
549
+ - si_scaler.inverse_transform(x_transformed - h, inplace=False)
550
+ ) / (2 * h)
551
+ npt.assert_allclose(y_exact, y_fd, rtol=5e-5)
552
+
553
+ @staticmethod
554
+ def test_eq_same_type():
555
+ obj_1 = PowerTransformerSI(np.array([0.0, 3.5]), method="yeo-johnson")
556
+ obj_2 = PowerTransformerSI(np.array([0.0, 3.5]), method="yeo-johnson")
557
+ assert obj_1 == obj_2
558
+
559
+ @staticmethod
560
+ def test_eq_different_type():
561
+ obj_1 = PowerTransformerSI(np.array([0.0, 3.5]), method="yeo-johnson")
562
+ # obj_2 = PowerTransformerSI(np.array([0.0, 3.5]), method="box-cox")
563
+ obj_2 = StandardScalerSI(np.array([1.0]), np.array([0.5]))
564
+ assert not obj_1 == obj_2
565
+
566
+ @staticmethod
567
+ def test_save_load(si_scaler):
568
+ path = f"./{str(uuid.uuid4())}.h5"
569
+ with h5py.File(path, "w") as fid:
570
+ si_scaler._save_h5(fid)
571
+ with h5py.File(path, "r") as fid:
572
+ scaler_saved = PowerTransformerYeoJohnson._load_h5(fid)
573
+ assert si_scaler == scaler_saved
574
+
575
+ @staticmethod
576
+ def test_box_cox():
577
+ with pytest.raises(NotImplementedError):
578
+ PowerTransformerSI(np.array([0.0, 3.5]), method="box-cox")
579
+
580
+
581
+ def test_not_implemented_transformer():
582
+ scaler = QuantileTransformer()
583
+ with pytest.raises(NotImplementedError, match="QuantileTransformer not supported"):
584
+ Transformer.from_sklearn(scaler)
585
+
586
+
587
+ @pytest.mark.parametrize(
588
+ "scaler_cls,data",
589
+ [
590
+ (MinMaxScaler, np.reshape([4, 5, 6], (-1, 1))),
591
+ (MinMaxScaler, [[4, 5, 6], [6, 8, 10]]),
592
+ (StandardScaler, np.reshape([4, 5, 6], (-1, 1))),
593
+ (StandardScaler, [[4, 5, 6], [6, 8, 10]]),
594
+ ],
595
+ )
596
+ def test_save_load(scaler_cls, data):
597
+ # test save and load with 1 and more features
598
+ scaler_sk = scaler_cls()
599
+ scaler_sk.fit_transform(data)
600
+ scaler_si = Transformer.from_sklearn(scaler_sk)
601
+
602
+ with h5py.File("tmp.hdf5", "w") as f:
603
+ scaler_si._save_h5(f)
604
+ saved_scaler_cls = {
605
+ MinMaxScaler: MinMaxScalerSI,
606
+ StandardScaler: StandardScalerSI,
607
+ }[scaler_cls]
608
+ scaler_saved = saved_scaler_cls._load_h5(f)
609
+
610
+ npt.assert_array_equal(
611
+ scaler_si.transform(data, inplace=False),
612
+ scaler_si.transform(data, inplace=False),
613
+ )
614
+ npt.assert_array_equal(
615
+ scaler_si.transform(data, inplace=False),
616
+ scaler_saved.transform(data, inplace=False),
617
+ )