179 lines
5.4 KiB
Python
179 lines
5.4 KiB
Python
|
"""
|
||
|
Created on Wed Feb 17 23:44:18 2021
|
||
|
|
||
|
Author: Josef Perktold
|
||
|
License: BSD-3
|
||
|
|
||
|
"""
|
||
|
|
||
|
import numpy as np
|
||
|
from numpy.testing import assert_allclose, assert_array_less
|
||
|
from scipy import stats
|
||
|
|
||
|
from statsmodels.distributions.copula.api import (
|
||
|
CopulaDistribution, ArchimedeanCopula)
|
||
|
from statsmodels.distributions.copula.api import transforms as tra
|
||
|
import statsmodels.distributions.tools as dt
|
||
|
from statsmodels.distributions.bernstein import (
|
||
|
BernsteinDistribution, BernsteinDistributionBV, BernsteinDistributionUV)
|
||
|
|
||
|
|
||
|
def test_bernstein_distribution_1d():
|
||
|
grid = dt._Grid([501])
|
||
|
loc = grid.x_flat == 0
|
||
|
grid.x_flat[loc] = grid.x_flat[~loc].min() / 2
|
||
|
grid.x_flat[grid.x_flat == 1] = 1 - grid.x_flat.min()
|
||
|
|
||
|
distr = stats.beta(3, 5)
|
||
|
cdf_g = distr.cdf(np.squeeze(grid.x_flat))
|
||
|
bpd = BernsteinDistribution(cdf_g)
|
||
|
|
||
|
cdf_bp = bpd.cdf(grid.x_flat)
|
||
|
assert_allclose(cdf_bp, cdf_g, atol=0.005)
|
||
|
assert_array_less(np.median(np.abs(cdf_bp - cdf_g)), 0.001)
|
||
|
|
||
|
pdfv = distr.pdf(np.squeeze(grid.x_flat))
|
||
|
pdf_bp = bpd.pdf(grid.x_flat)
|
||
|
assert_allclose(pdf_bp, pdfv, atol=0.02)
|
||
|
assert_array_less(np.median(np.abs(pdf_bp - pdfv)), 0.01)
|
||
|
|
||
|
# compare with UV class
|
||
|
xf = np.squeeze(grid.x_flat) # UV returns column if x is column
|
||
|
bpd1 = BernsteinDistributionUV(cdf_g)
|
||
|
cdf_bp1 = bpd1.cdf(xf)
|
||
|
assert_allclose(cdf_bp1, cdf_bp, atol=1e-13)
|
||
|
pdf_bp1 = bpd1.pdf(xf)
|
||
|
assert_allclose(pdf_bp1, pdf_bp, atol=1e-13)
|
||
|
|
||
|
cdf_bp1 = bpd1.cdf(xf, method="beta")
|
||
|
assert_allclose(cdf_bp1, cdf_bp, atol=1e-13)
|
||
|
pdf_bp1 = bpd1.pdf(xf, method="beta")
|
||
|
assert_allclose(pdf_bp1, pdf_bp, atol=1e-13)
|
||
|
|
||
|
cdf_bp1 = bpd1.cdf(xf, method="bpoly")
|
||
|
assert_allclose(cdf_bp1, cdf_bp, atol=1e-13)
|
||
|
pdf_bp1 = bpd1.pdf(xf, method="bpoly")
|
||
|
assert_allclose(pdf_bp1, pdf_bp, atol=1e-13)
|
||
|
|
||
|
# check rvs
|
||
|
# currently smoke test
|
||
|
rvs = bpd.rvs(100)
|
||
|
assert len(rvs) == 100
|
||
|
|
||
|
|
||
|
def test_bernstein_distribution_2d():
|
||
|
grid = dt._Grid([51, 51])
|
||
|
|
||
|
cop_tr = tra.TransfFrank
|
||
|
args = (2,)
|
||
|
ca = ArchimedeanCopula(cop_tr())
|
||
|
distr1 = stats.uniform
|
||
|
distr2 = stats.uniform
|
||
|
cad = CopulaDistribution(ca, [distr1, distr2], cop_args=args)
|
||
|
cdfv = cad.cdf(grid.x_flat, args)
|
||
|
cdf_g = cdfv.reshape(grid.k_grid)
|
||
|
|
||
|
bpd = BernsteinDistribution(cdf_g)
|
||
|
|
||
|
cdf_bp = bpd.cdf(grid.x_flat)
|
||
|
assert_allclose(cdf_bp, cdfv, atol=0.005)
|
||
|
assert_array_less(np.median(np.abs(cdf_bp - cdfv)), 0.001)
|
||
|
|
||
|
grid_eps = dt._Grid([51, 51], eps=1e-8)
|
||
|
pdfv = cad.pdf(grid_eps.x_flat)
|
||
|
pdf_bp = bpd.pdf(grid_eps.x_flat)
|
||
|
assert_allclose(pdf_bp, pdfv, atol=0.01, rtol=0.04)
|
||
|
assert_array_less(np.median(np.abs(pdf_bp - pdfv)), 0.05)
|
||
|
|
||
|
# check marginal cdfs
|
||
|
# get marginal cdf
|
||
|
xx = np.column_stack((np.linspace(0, 1, 5), np.ones(5)))
|
||
|
cdf_m1 = bpd.cdf(xx)
|
||
|
assert_allclose(cdf_m1, xx[:, 0], atol=1e-13)
|
||
|
xx = np.column_stack((np.ones(5), np.linspace(0, 1, 5)))
|
||
|
cdf_m2 = bpd.cdf(xx)
|
||
|
assert_allclose(cdf_m2, xx[:, 1], atol=1e-13)
|
||
|
|
||
|
xx_ = np.linspace(0, 1, 5)
|
||
|
xx = xx_[:, None] # currently requires 2-dim
|
||
|
bpd_m1 = bpd.get_marginal(0)
|
||
|
cdf_m1 = bpd_m1.cdf(xx)
|
||
|
assert_allclose(cdf_m1, xx_, atol=1e-13)
|
||
|
pdf_m1 = bpd_m1.pdf(xx)
|
||
|
assert_allclose(pdf_m1, np.ones(len(xx)), atol=1e-13)
|
||
|
|
||
|
bpd_m = bpd.get_marginal(1)
|
||
|
cdf_m = bpd_m.cdf(xx)
|
||
|
assert_allclose(cdf_m, xx_, atol=1e-13)
|
||
|
pdf_m = bpd_m.pdf(xx)
|
||
|
assert_allclose(pdf_m, np.ones(len(xx)), atol=1e-13)
|
||
|
|
||
|
|
||
|
class TestBernsteinBeta2d:
|
||
|
|
||
|
@classmethod
|
||
|
def setup_class(cls):
|
||
|
grid = dt._Grid([91, 101])
|
||
|
|
||
|
cop_tr = tra.TransfFrank
|
||
|
args = (2,)
|
||
|
ca = ArchimedeanCopula(cop_tr())
|
||
|
distr1 = stats.beta(4, 3)
|
||
|
distr2 = stats.beta(4, 4) # (5, 2)
|
||
|
cad = CopulaDistribution(ca, [distr1, distr2], cop_args=args)
|
||
|
cdfv = cad.cdf(grid.x_flat, args)
|
||
|
cdf_g = cdfv.reshape(grid.k_grid)
|
||
|
|
||
|
cls.grid = grid
|
||
|
cls.cdfv = cdfv
|
||
|
cls.distr = cad
|
||
|
cls.bpd = BernsteinDistributionBV(cdf_g)
|
||
|
|
||
|
def test_basic(self):
|
||
|
bpd = self.bpd
|
||
|
grid = self.grid
|
||
|
cdfv = self.cdfv
|
||
|
distr = self.distr
|
||
|
|
||
|
if grid.x_flat.shape[0] < 51**2:
|
||
|
cdf_bp = bpd.cdf(grid.x_flat)
|
||
|
assert_allclose(cdf_bp, cdfv, atol=0.05)
|
||
|
assert_array_less(np.median(np.abs(cdf_bp - cdfv)), 0.01)
|
||
|
|
||
|
grid_eps = dt._Grid([51, 51], eps=1e-2)
|
||
|
cdfv = distr.cdf(grid_eps.x_flat)
|
||
|
cdf_bp = bpd.cdf(grid_eps.x_flat)
|
||
|
assert_allclose(cdf_bp, cdfv, atol=0.01, rtol=0.01)
|
||
|
assert_array_less(np.median(np.abs(cdf_bp - cdfv)), 0.05)
|
||
|
|
||
|
pdfv = distr.pdf(grid_eps.x_flat)
|
||
|
pdf_bp = bpd.pdf(grid_eps.x_flat)
|
||
|
assert_allclose(pdf_bp, pdfv, atol=0.06, rtol=0.1)
|
||
|
assert_array_less(np.median(np.abs(pdf_bp - pdfv)), 0.05)
|
||
|
|
||
|
def test_rvs(self):
|
||
|
# currently smoke test
|
||
|
rvs = self.bpd.rvs(100)
|
||
|
assert len(rvs) == 100
|
||
|
|
||
|
|
||
|
class TestBernsteinBeta2dd(TestBernsteinBeta2d):
|
||
|
|
||
|
@classmethod
|
||
|
def setup_class(cls):
|
||
|
grid = dt._Grid([91, 101])
|
||
|
|
||
|
cop_tr = tra.TransfFrank
|
||
|
args = (2,)
|
||
|
ca = ArchimedeanCopula(cop_tr())
|
||
|
distr1 = stats.beta(4, 3)
|
||
|
distr2 = stats.beta(4, 4) # (5, 2)
|
||
|
cad = CopulaDistribution(ca, [distr1, distr2], cop_args=args)
|
||
|
cdfv = cad.cdf(grid.x_flat, args)
|
||
|
cdf_g = cdfv.reshape(grid.k_grid)
|
||
|
|
||
|
cls.grid = grid
|
||
|
cls.cdfv = cdfv
|
||
|
cls.distr = cad
|
||
|
cls.bpd = BernsteinDistribution(cdf_g)
|