Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for Power Transformer #430

Merged
Merged
Changes from 29 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
7455508
add test file for power transformer
veni-vidi-vici-dormivi Apr 29, 2024
7dae2b8
test lambda function
veni-vidi-vici-dormivi Apr 29, 2024
1a49b59
add test for fit
veni-vidi-vici-dormivi Apr 30, 2024
31868ea
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 30, 2024
b5d4a17
increase tolerance
veni-vidi-vici-dormivi Apr 30, 2024
ec939a3
flaking
veni-vidi-vici-dormivi Apr 30, 2024
ae2ac44
decrease tolerance again
veni-vidi-vici-dormivi Apr 30, 2024
2fa5b64
test transform
veni-vidi-vici-dormivi Apr 30, 2024
f960e44
test inverse transform
veni-vidi-vici-dormivi Apr 30, 2024
e4bc840
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 30, 2024
c4927af
remove hard coded test for lambda function
veni-vidi-vici-dormivi Apr 30, 2024
9d24aed
Merge branch 'main' into pt_testing
veni-vidi-vici-dormivi May 3, 2024
f717f66
change from uniform to normal test data
veni-vidi-vici-dormivi May 6, 2024
62b2fa9
update comment in fit
veni-vidi-vici-dormivi May 6, 2024
044f62e
relax tolerance
veni-vidi-vici-dormivi May 6, 2024
feca601
remove superfluous line
veni-vidi-vici-dormivi May 6, 2024
2980592
readability of pt_coeffs result
veni-vidi-vici-dormivi May 6, 2024
186b667
explicit n_years and n_gridcells in test_transform
veni-vidi-vici-dormivi May 6, 2024
4d06fa4
change from ints to float for transform
veni-vidi-vici-dormivi May 6, 2024
0ec13cb
extend inverse transform tes
veni-vidi-vici-dormivi May 6, 2024
e4af1b4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 6, 2024
1273b39
change n_years to n_ts
veni-vidi-vici-dormivi May 6, 2024
242c493
rename other timesteps
veni-vidi-vici-dormivi May 6, 2024
d47be70
add test for optimize lambda
veni-vidi-vici-dormivi May 7, 2024
f79201c
remove years*12
veni-vidi-vici-dormivi May 7, 2024
3455103
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 7, 2024
405f5a0
rewording in test_labda_function
veni-vidi-vici-dormivi May 7, 2024
294b158
100_000
veni-vidi-vici-dormivi May 7, 2024
8dfebb6
add comment in test lambda function
veni-vidi-vici-dormivi May 7, 2024
c26aaac
Update tests/unit/test_power_transformer.pyAdd Note f
veni-vidi-vici-dormivi May 15, 2024
d6445e4
typo
veni-vidi-vici-dormivi May 15, 2024
ec79d12
Renaming inverse transform
veni-vidi-vici-dormivi May 15, 2024
c3964b6
deterministic lambda func tests
veni-vidi-vici-dormivi May 15, 2024
1b8c82f
scipy as sp
veni-vidi-vici-dormivi May 15, 2024
7ddab6a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 16, 2024
2330f58
Merge branch 'main' into pt_testing
veni-vidi-vici-dormivi May 17, 2024
cdd7501
switch from uniform to normal data
veni-vidi-vici-dormivi May 17, 2024
65afa40
add right skewed test
veni-vidi-vici-dormivi May 17, 2024
267f61d
add comments
veni-vidi-vici-dormivi May 17, 2024
7dbb583
parameterize optimize
veni-vidi-vici-dormivi May 17, 2024
8f198ad
add more optimize tests
veni-vidi-vici-dormivi May 17, 2024
8bdad5c
test numerical stability
veni-vidi-vici-dormivi May 17, 2024
8ee4f9d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 17, 2024
f22a20a
fit power transformer with standardize = False
veni-vidi-vici-dormivi May 23, 2024
abc63bd
test random data
veni-vidi-vici-dormivi May 23, 2024
3b30362
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 23, 2024
fcaab1a
remove random data testing again
veni-vidi-vici-dormivi May 23, 2024
2bd00c2
test eps equality
veni-vidi-vici-dormivi May 23, 2024
a69a8bd
remove eps testing again
veni-vidi-vici-dormivi May 23, 2024
3b418c1
try with Nelder Mead
veni-vidi-vici-dormivi May 23, 2024
bf1acf4
change back to SLSQP
veni-vidi-vici-dormivi May 23, 2024
25b2e36
set all standardize to false
veni-vidi-vici-dormivi May 23, 2024
7b8ba9c
add test for scaler
veni-vidi-vici-dormivi May 23, 2024
318c020
Merge branch 'main' into pt_testing
veni-vidi-vici-dormivi May 23, 2024
7691916
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 23, 2024
c21905f
add inverse trasform to scaler test
veni-vidi-vici-dormivi May 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions tests/unit/test_power_transformer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import numpy as np
import scipy

from mesmer.mesmer_m.power_transformer import (
PowerTransformerVariableLambda,
lambda_function,
)


def test_lambda_function():
# Note that we test with normally distributed data without skewness
# which would yield coefficients close to 1 and 0
# and a constant lambda of about 1
# but for the sake of testing, we use coefficients which respresent skewness
coeffs = [1, 0.1]
local_yearly_T_test_data = np.random.normal(0, 1, 10)

# even for random numbers, the lambdas should always be between 0 and 2
# because the function is logistic between 0 and 2
lambdas = lambda_function(coeffs, local_yearly_T_test_data)

assert np.all(lambdas > 0) and np.all(lambdas < 2)


def test_fit_power_transformer():
# with enough random data points the fit should be close to 1 and 0
# here we test with uniform random data because it is quicker to fit
# Uniform data is also symmetrically distributed so coefficients
# should be close to 1 and 0 as well

gridcells = 1
n_months = 100_000
monthly_residuals = np.random.rand(n_months, gridcells) * 10
yearly_T = np.ones((n_months, gridcells))

pt = PowerTransformerVariableLambda()
pt.fit(monthly_residuals, yearly_T, gridcells)

result = pt.coeffs_
expected = np.array([[1, 0]])

np.testing.assert_allclose(result, expected, atol=1e-7)


def test_yeo_johnson_optimize_lambda():
np.random.seed(0)
n_years = 10_000
yearly_T = np.random.randn(n_years)

skew = -2
local_monthly_residuals = scipy.stats.skewnorm.rvs(skew, size=n_years)

pt = PowerTransformerVariableLambda()
pt.coeffs_ = pt._yeo_johnson_optimize_lambda(local_monthly_residuals, yearly_T)
lmbda = lambda_function(pt.coeffs_, yearly_T)
transformed = pt._yeo_johnson_transform(local_monthly_residuals, lmbda)

assert (lmbda > 1).all() & (lmbda <= 2).all()
np.testing.assert_allclose(scipy.stats.skew(transformed), 0, atol=0.01)

# this fails, need to investigate more
# skew = 2
# local_monthly_residuals = scipy.stats.skewnorm.rvs(skew, size=n_years)

# pt = PowerTransformerVariableLambda()
# pt.coeffs_ = pt._yeo_johnson_optimize_lambda(local_monthly_residuals, yearly_T)
# lmbda = lambda_function(pt.coeffs_, yearly_T)
# transformed = pt._yeo_johnson_transform(local_monthly_residuals, lmbda)

# assert (lmbda >= 0).all() & (lmbda <= 1).all()
# np.testing.assert_allclose(scipy.stats.skew(transformed), 0, atol=0.01)


def test_transform():
n_ts = 20
n_gridcells = 10

pt = PowerTransformerVariableLambda()
pt.standardize = False
pt.coeffs_ = np.tile([1, 0], (n_gridcells, 1))

monthly_residuals = np.ones((n_ts, n_gridcells))
yearly_T = np.zeros((n_ts, n_gridcells))

result = pt.transform(monthly_residuals, yearly_T)
expected = np.ones((n_ts, n_gridcells))

np.testing.assert_equal(result, expected)


def test_yeo_johnson_transform():
pt = PowerTransformerVariableLambda()

# test all possible combinations of local_monthly_residuals and lambdas
local_monthly_residuals = np.array([0.0, 1.0, 0.0, 1.0, -1.0, -1.0])
lambdas = np.array([1.0, 1.0, 0.0, 0.0, 1.0, 2.0])

result = pt._yeo_johnson_transform(local_monthly_residuals, lambdas)
expected = np.array([0.0, 1.0, 0.0, np.log1p(1.0), -1.0, -np.log1p(1.0)])

np.testing.assert_equal(result, expected)


def test_inverse_transform():
n_ts = 20
n_gridcells = 5
# dummy seasonal cylce, having negative and positive values
monthly_residuals = np.sin(np.linspace(0, 2 * np.pi, n_ts * n_gridcells)).reshape(
n_ts, n_gridcells
)
yearly_T = np.zeros((n_ts, n_gridcells))

pt = PowerTransformerVariableLambda()
pt.standardize = False
# dummy lambdas (since yearly_T is zero lambda comes out to be second coefficient)
# we have all cases for lambdas 0 and 2 (special cases), 1 (identity case)
# lambda between 1 and 1 and lambda between 1 and 2 for concave and convex cases
pt.coeffs_ = np.array([[0, 0], [0, 1], [0, 2], [0, 0.5], [0, 1.5]])
pt.mins_ = np.amin(monthly_residuals, axis=0)
pt.maxs_ = np.amax(monthly_residuals, axis=0)

transformed = pt.transform(monthly_residuals, yearly_T)
result = pt.inverse_transform(transformed, yearly_T)

np.testing.assert_allclose(result, monthly_residuals, atol=1e-7)