Module gmr.tests.test_mvn

Functions

def test_conditional_distribution()
Expand source code
def test_conditional_distribution():
    """Test moments from conditional MVN."""
    random_state = check_random_state(0)

    mean = np.array([0.0, 1.0])
    covariance = np.array([[0.5, 0.0], [0.0, 5.0]])
    mvn = MVN(mean=mean, covariance=covariance, random_state=random_state)

    conditional = mvn.condition(np.array([1]), np.array([5.0]))
    assert conditional.mean == np.array([0.0])
    assert conditional.covariance == np.array([0.5])
    conditional = mvn.condition(np.array([0]), np.array([0.5]))
    assert conditional.mean == np.array([1.0])
    assert conditional.covariance == np.array([5.0])

Test moments from conditional MVN.

def test_ellipse()
Expand source code
def test_ellipse():
    """Test equiprobable ellipse."""
    random_state = check_random_state(0)

    mean = np.array([0.0, 1.0])
    covariance = np.array([[0.5, 0.0], [0.0, 5.0]])
    mvn = MVN(mean=mean, covariance=covariance, random_state=random_state)

    angle, width, height = mvn.to_ellipse()
    assert angle == 0.5 * np.pi
    assert width == np.sqrt(5.0)
    assert height == np.sqrt(0.5)

Test equiprobable ellipse.

def test_estimate_moments()
Expand source code
def test_estimate_moments():
    """Test moments estimated from samples and sampling from MVN."""
    random_state = check_random_state(0)
    actual_mean = np.array([0.0, 1.0])
    actual_covariance = np.array([[0.5, -1.0], [-1.0, 5.0]])
    X = random_state.multivariate_normal(actual_mean, actual_covariance,
                                         size=(100000,))
    mvn = MVN(random_state=random_state)
    mvn.from_samples(X)
    assert np.linalg.norm(mvn.mean - actual_mean) < 0.02
    assert np.linalg.norm(mvn.covariance - actual_covariance) < 0.02

    X2 = mvn.sample(n_samples=100000)

    mvn2 = MVN(random_state=random_state)
    mvn2.from_samples(X2)
    assert np.linalg.norm(mvn2.mean - actual_mean) < 0.03
    assert np.linalg.norm(mvn2.covariance - actual_covariance) < 0.03

Test moments estimated from samples and sampling from MVN.

def test_in_confidence_region()
Expand source code
def test_in_confidence_region():
    """Test check for confidence region."""
    mvn = MVN(mean=np.array([1.0, 2.0]),
              covariance=np.array([[1.0, 0.0], [0.0, 4.0]]))

    alpha_1sigma = 0.6827
    alpha_2sigma = 0.9545

    assert mvn.is_in_confidence_region(mvn.mean, alpha_1sigma)
    assert mvn.is_in_confidence_region(mvn.mean + np.array([1.0, 0.0]), alpha_1sigma)
    assert not mvn.is_in_confidence_region(mvn.mean + np.array([1.001, 0.0]), alpha_1sigma)

    assert mvn.is_in_confidence_region(mvn.mean + np.array([2.0, 0.0]), alpha_2sigma)
    assert not mvn.is_in_confidence_region(mvn.mean + np.array([3.0, 0.0]), alpha_2sigma)

    assert mvn.is_in_confidence_region(mvn.mean + np.array([0.0, 1.0]), alpha_1sigma)
    assert mvn.is_in_confidence_region(mvn.mean + np.array([0.0, 2.0]), alpha_1sigma)
    assert not mvn.is_in_confidence_region(mvn.mean + np.array([0.0, 3.0]), alpha_1sigma)

    assert mvn.is_in_confidence_region(mvn.mean + np.array([0.0, 4.0]), alpha_2sigma)
    assert not mvn.is_in_confidence_region(mvn.mean + np.array([0.0, 4.001]), alpha_2sigma)

Test check for confidence region.

def test_is_in_confidence_region_1d()
Expand source code
def test_is_in_confidence_region_1d():
    mvn = MVN(mean=[0.0], covariance=[[1.0]])
    assert mvn.is_in_confidence_region([0.0], 1.0)
def test_marginal_distribution()
Expand source code
def test_marginal_distribution():
    """Test moments from marginal MVN."""
    random_state = check_random_state(0)
    mvn = MVN(mean=mean, covariance=covariance, random_state=random_state)

    marginalized = mvn.marginalize(np.array([0]))
    assert marginalized.mean == np.array([0.0])
    assert marginalized.covariance == np.array([0.5])
    marginalized = mvn.marginalize(np.array([1]))
    assert marginalized.mean == np.array([1.0])
    assert marginalized.covariance == np.array([5.0])

Test moments from marginal MVN.

def test_plot()
Expand source code
def test_plot():
    """Test plot of MVN."""
    random_state = check_random_state(0)
    mvn = MVN(mean=mean, covariance=covariance, random_state=random_state)

    ax = AxisStub()
    try:
        plot_error_ellipse(ax, mvn)
    except ImportError:
        pytest.skip("matplotlib is required for this test")
    assert ax.count == 8
    plot_error_ellipse(ax, mvn, color="r")
    assert ax.count == 16

Test plot of MVN.

def test_probability_density()
Expand source code
def test_probability_density():
    """Test PDF of MVN."""
    mean = np.array([0.0, 1.0, 2.0])
    covariance = np.array([[ 0.5, -1.0,  0.0],
                           [-1.0,  5.0, -0.5],
                           [ 0.0, -0.5,  1.0]])

    random_state = check_random_state(0)
    mvn = MVN(mean, covariance, random_state=random_state)

    x = np.linspace(-100, 100, 201)
    X = np.vstack(list(map(np.ravel, np.meshgrid(x, x, x)))).T
    p = mvn.to_probability_density(X)

    bin_side_length = x[1] - x[0]
    bin_volume = bin_side_length ** 3
    approx_int = np.sum(p) * bin_volume

    assert pytest.approx(approx_int, abs=1e-3) == 1.0

Test PDF of MVN.

def test_probability_density_without_noise()
Expand source code
def test_probability_density_without_noise():
    """Test probability density of MVN with not invertible covariance."""
    random_state = check_random_state(0)

    n_samples = 10
    x = np.linspace(0, 1, n_samples)[:, np.newaxis]
    y = np.ones((n_samples, 1))
    samples = np.hstack((x, y))

    mvn = MVN(random_state=random_state)
    mvn.from_samples(samples)
    assert_array_almost_equal(mvn.mean, np.array([0.5, 1.0]), decimal=2)
    assert mvn.covariance[1, 1] == 0.0
    p_training = mvn.to_probability_density(samples)
    p_test = mvn.to_probability_density(samples + 1)
    assert np.all(p_training > p_test)

Test probability density of MVN with not invertible covariance.

def test_regression()
Expand source code
def test_regression():
    """Test regression with MVN."""
    random_state = check_random_state(0)

    n_samples = 100
    x = np.linspace(0, 1, n_samples)[:, np.newaxis]
    y = 3 * x + 1
    noise = random_state.randn(n_samples, 1) * 0.01
    y += noise
    samples = np.hstack((x, y))

    mvn = MVN(random_state=random_state)
    mvn.from_samples(samples)
    assert_array_almost_equal(mvn.mean, np.array([0.5, 2.5]), decimal=2)

    pred, cov = mvn.predict(np.array([0]), x)
    mse = np.sum((y - pred) ** 2) / n_samples
    assert mse < 1e-3
    assert cov[0, 0] < 0.01

Test regression with MVN.

def test_regression_with_2d_input()
Expand source code
def test_regression_with_2d_input():
    """Test regression with MVN and two-dimensional input."""
    random_state = check_random_state(0)

    n_samples = 100
    x = np.linspace(0, 1, n_samples)[:, np.newaxis]
    y = 3 * x + 1
    noise = random_state.randn(n_samples, 1) * 0.01
    y += noise
    samples = np.hstack((x, x[::-1], y))

    mvn = MVN(random_state=random_state)
    mvn.from_samples(samples)
    assert_array_almost_equal(mvn.mean, np.array([0.5, 0.5, 2.5]), decimal=2)

    x_test = np.hstack((x, x[::-1]))
    pred, cov = mvn.predict(np.array([0, 1]), x_test)
    mse = np.sum((y - pred) ** 2) / n_samples
    assert mse < 1e-3
    assert cov[0, 0] < 0.01

Test regression with MVN and two-dimensional input.

def test_regression_without_noise()
Expand source code
def test_regression_without_noise():
    """Test regression without noise with MVN."""
    random_state = check_random_state(0)

    n_samples = 10
    x = np.linspace(0, 1, n_samples)[:, np.newaxis]
    y = 3 * x + 1
    samples = np.hstack((x, y))

    mvn = MVN(random_state=random_state)
    mvn.from_samples(samples)
    assert_array_almost_equal(mvn.mean, np.array([0.5, 2.5]), decimal=2)

    pred, cov = mvn.predict(np.array([0]), x)
    mse = np.sum((y - pred) ** 2) / n_samples
    assert mse < 1e-10
    assert cov[0, 0] < 1e-10

Test regression without noise with MVN.

def test_sample_confidence_region()
Expand source code
def test_sample_confidence_region():
    """Test sampling of confidence region."""
    random_state = check_random_state(42)
    mvn = MVN(mean=np.array([1.0, 2.0]),
              covariance=np.array([[1.0, 0.0], [0.0, 4.0]]),
              random_state=random_state)
    samples = mvn.sample_confidence_region(100, 0.9)
    for sample in samples:
        assert mvn.is_in_confidence_region(sample, 0.9)

Test sampling of confidence region.

def test_squared_mahalanobis_distance()
Expand source code
def test_squared_mahalanobis_distance():
    """Test Mahalanobis distance."""
    mvn = MVN(mean=np.zeros(2), covariance=np.eye(2))
    assert np.sqrt(mvn.squared_mahalanobis_distance(np.zeros(2))) == pytest.approx(0.0)
    assert np.sqrt(mvn.squared_mahalanobis_distance(np.array([0, 1]))) == pytest.approx(1.0)

    mvn = MVN(mean=np.zeros(2), covariance=4.0 * np.eye(2))
    assert np.sqrt(mvn.squared_mahalanobis_distance(np.array([2, 0]))) == pytest.approx(1.0)
    assert np.sqrt(mvn.squared_mahalanobis_distance(np.array([2, 2]))) == pytest.approx(np.sqrt(2))

Test Mahalanobis distance.

def test_uninitialized()
Expand source code
def test_uninitialized():
    """Test behavior of uninitialized MVN."""
    random_state = check_random_state(0)
    mvn = MVN(random_state=random_state)
    with pytest.raises(ValueError):
        mvn.sample(10)
    with pytest.raises(ValueError):
        mvn.to_probability_density(np.ones((1, 1)))
    with pytest.raises(ValueError):
        mvn.marginalize(np.zeros(0))
    with pytest.raises(ValueError):
        mvn.condition(np.zeros(0), np.zeros(0))
    with pytest.raises(ValueError):
        mvn.predict(np.zeros(0), np.zeros(0))
    with pytest.raises(ValueError):
        mvn.to_ellipse()
    mvn = MVN(mean=np.ones(2), random_state=random_state)
    with pytest.raises(ValueError):
        mvn.sample(10)
    with pytest.raises(ValueError):
        mvn.to_probability_density(np.ones((1, 1)))
    with pytest.raises(ValueError):
        mvn.marginalize(np.zeros(0))
    with pytest.raises(ValueError):
        mvn.condition(np.zeros(0), np.zeros(0))
    with pytest.raises(ValueError):
        mvn.predict(np.zeros(0), np.zeros(0))
    with pytest.raises(ValueError):
        mvn.to_ellipse()

Test behavior of uninitialized MVN.

def test_unscented_transform_linear_combination()
Expand source code
def test_unscented_transform_linear_combination():
    """Test unscented transform with a linear combination."""
    mvn = MVN(mean=np.zeros(2), covariance=np.eye(2), random_state=42)

    points = mvn.sigma_points()
    new_points = np.empty_like(points)
    new_points[:, 0] = points[:, 1]
    new_points[:, 1] = points[:, 0] - 0.5 * points[:, 1]
    new_points += np.array([-0.5, 3.0])

    transformed_mvn = mvn.estimate_from_sigma_points(new_points)
    assert_array_almost_equal(transformed_mvn.mean, np.array([-0.5, 3.0]))
    assert_array_almost_equal(
        transformed_mvn.covariance,
        np.array([[1.0, -0.5], [-0.5, 1.25]])
    )

Test unscented transform with a linear combination.

def test_unscented_transform_linear_transformation()
Expand source code
def test_unscented_transform_linear_transformation():
    """Test unscented transform with a linear transformation."""
    mvn = MVN(mean=np.zeros(2), covariance=np.eye(2), random_state=42)

    points = mvn.sigma_points()
    new_points = np.copy(points)
    new_points[:, 1] *= 10
    new_points += np.array([0.5, -3.0])

    transformed_mvn = mvn.estimate_from_sigma_points(new_points)
    assert_array_almost_equal(transformed_mvn.mean, np.array([0.5, -3.0]))
    assert_array_almost_equal(
        transformed_mvn.covariance,
        np.array([[1.0, 0.0], [0.0, 100.0]])
    )

    sample1 = transformed_mvn.sample(1)
    sample2 = mvn.estimate_from_sigma_points(new_points, random_state=42).sample(1)
    assert_array_almost_equal(sample1, sample2)

Test unscented transform with a linear transformation.

def test_unscented_transform_projection_to_more_dimensions()
Expand source code
def test_unscented_transform_projection_to_more_dimensions():
    """Test unscented transform with a projection to 3D."""
    mvn = MVN(mean=np.zeros(2), covariance=np.eye(2), random_state=42)

    points = mvn.sigma_points()

    def f(points):
        new_points = np.empty((len(points), 3))
        new_points[:, 0] = points[:, 0]
        new_points[:, 1] = points[:, 1]
        new_points[:, 2] = -0.5 * points[:, 0] + 0.5 * points[:, 1]
        new_points += np.array([-0.5, 3.0, 10.0])
        return new_points

    transformed_mvn = mvn.estimate_from_sigma_points(f(points))
    assert_array_almost_equal(transformed_mvn.mean, np.array([-0.5, 3.0, 10.0]))
    assert_array_almost_equal(
        transformed_mvn.covariance,
        np.array([[1.0, 0.0, -0.5],
                  [0.0, 1.0, 0.5],
                  [-0.5, 0.5, 0.5]])
    )

Test unscented transform with a projection to 3D.

def test_unscented_transform_quadratic()
Expand source code
def test_unscented_transform_quadratic():
    """Test unscented transform with a quadratic transformation."""
    mvn = MVN(mean=np.zeros(2), covariance=np.eye(2), random_state=42)

    points = mvn.sigma_points(alpha=0.67, kappa=5.0)

    def f(points):
        new_points = np.empty_like(points)
        new_points[:, 0] = points[:, 0] ** 2 * np.sign(points[:, 0])
        new_points[:, 1] = points[:, 1] ** 2 * np.sign(points[:, 1])
        new_points += np.array([5.0, -3.0])
        return new_points

    transformed_mvn = mvn.estimate_from_sigma_points(f(points), alpha=0.67, kappa=5.0)
    assert_array_almost_equal(transformed_mvn.mean, np.array([5.0, -3.0]))
    assert_array_almost_equal(
        transformed_mvn.covariance,
        np.array([[3.1, 0.0], [0.0, 3.1]]),
        decimal=1
    )

Test unscented transform with a quadratic transformation.

Classes

class AxisStub
Expand source code
class AxisStub:
    def __init__(self):
        self.count = 0
        self.artists = []

    def add_artist(self, artist):
        self.artists.append(artist)
        self.count += 1

Methods

def add_artist(self, artist)
Expand source code
def add_artist(self, artist):
    self.artists.append(artist)
    self.count += 1