Example #1
0
 def setUp(self):
     self.X = np.array([[2641.16233666, 180.2425623],
                        [921.14476418, 192.35609972],
                        [-651.32239137, 150.24830291],
                        [1223.63536668, 156.62123653],
                        [3233.37342355, 173.80311908],
                        [1373.22400821, 191.0922843],
                        [1959.28188858, 163.22252158],
                        [1076.99295365, 190.73280428],
                        [2029.25100261, 158.52982435],
                        [1835.52188141, 163.0101334],
                        [1170.03850556, 205.24904026],
                        [739.42628394, 175.42916046],
                        [1866.65810627, 208.31821984],
                        [3703.49786503, 178.98351969],
                        [1719.45232017, 160.50981075],
                        [258.90206528, 163.19294974],
                        [219.42363944, 173.30395132],
                        [609.90212377, 215.18996298],
                        [1618.44207239, 164.71141696],
                        [2323.2775272, 178.84973821],
                        [3251.78732274, 182.99902513],
                        [1430.63989981, 217.5796917],
                        [-180.57028875, 201.56983421],
                        [-592.84497457, 174.92272693]])
     self.copula = Frank()
Example #2
0
 def setUp(self):
     self.X = np.array([
         [0.2, 0.1],
         [0.2, 0.3],
         [0.4, 0.5],
         [0.6, 0.4],
         [0.8, 0.6],
         [0.8, 0.9],
     ])
     self.copula = Frank()
Example #3
0
    def test_cdf_zero_if_single_arg_is_zero(self):
        """Test of the analytical properties of copulas on a range of values of theta."""
        # Setup
        instance = Frank()
        tau_values = np.linspace(-1.0, 1.0, 20)[1: -1]

        # Run/Check
        for tau in tau_values:
            instance.tau = tau
            instance.theta = instance.compute_theta()
            copula_zero_if_arg_zero(instance)
Example #4
0
    def test_cdf_value_if_all_other_arg_are_one(self):
        """Test of the analytical properties of copulas on a range of values of theta."""
        # Setup
        instance = Frank()
        tau_values = np.linspace(-1.0, 1.0, 20)[1: -1]

        # Run/Check
        for tau in tau_values:
            instance.tau = tau
            instance.theta = instance.compute_theta()
            copula_single_arg_not_one(instance, tolerance=1E-03)
Example #5
0
    def test_sample(self, uniform_mock):
        """Sample use the inverse-transform method to generate new samples."""
        # Setup
        instance = Frank()
        instance.tau = 0.5
        instance.theta = instance.compute_theta()

        uniform_mock.return_value = np.array([0.1, 0.2, 0.4, 0.6, 0.8])

        expected_result = np.array([
            [0.0312640840463779, 0.1],
            [0.1007998170183327, 0.2],
            [0.3501836319841291, 0.4],
            [0.6498163680158703, 0.6],
            [0.8992001829816683, 0.8]
        ])

        expected_uniform_call_args_list = [
            ((0, 1, 5), {}),
            ((0, 1, 5), {})
        ]

        # Run
        result = instance.sample(5)

        # Check
        assert isinstance(result, np.ndarray)
        assert result.shape == (5, 2)
        compare_nested_iterables(result, expected_result)
        assert uniform_mock.call_args_list == expected_uniform_call_args_list
Example #6
0
class TestFrank(TestCase):

    def setUp(self):
        self.X = np.array([
            [0.2, 0.1],
            [0.2, 0.3],
            [0.4, 0.5],
            [0.6, 0.4],
            [0.8, 0.6],
            [0.8, 0.9],
        ])
        self.copula = Frank()

    def test_fit(self):
        """On fit, theta and tau attributes are set."""
        self.copula.fit(self.X)
        self.assertAlmostEqual(self.copula.tau, 0.7877, places=3)
        self.assertAlmostEqual(self.copula.theta, 17.0227, places=3)

    def test_probability_density(self):
        """Probability_density returns the probability density for the given values."""
        # Setup
        self.copula.fit(self.X)
        expected_result = np.array([4.4006, 4.2302])

        # Run
        result = self.copula.probability_density(np.array([
            [0.2, 0.2],
            [0.6, 0.61]
        ]))

        # Check
        assert isinstance(result, np.ndarray)
        assert np.isclose(result, expected_result, rtol=0.05).all()

    def test_cumulative_distribution(self):
        """Cumulative_density returns the probability distribution value for a point."""
        # Setup
        self.copula.fit(self.X)
        expected_result = np.array([0.1602, 0.5641])

        # Run
        result = self.copula.cumulative_distribution(np.array([
            [0.2, 0.2],
            [0.6, 0.61]
        ]))

        # Check
        assert isinstance(result, np.ndarray)
        assert np.isclose(result, expected_result, rtol=0.05).all()

    @patch('copulas.bivariate.base.np.random.uniform')
    def test_sample(self, uniform_mock):
        """Sample use the inverse-transform method to generate new samples."""
        # Setup
        instance = Frank()
        instance.tau = 0.5
        instance.theta = instance.compute_theta()

        uniform_mock.return_value = np.array([0.1, 0.2, 0.4, 0.6, 0.8])

        expected_result = np.array([
            [0.0312640840463779, 0.1],
            [0.1007998170183327, 0.2],
            [0.3501836319841291, 0.4],
            [0.6498163680158703, 0.6],
            [0.8992001829816683, 0.8]
        ])

        expected_uniform_call_args_list = [
            ((0, 1, 5), {}),
            ((0, 1, 5), {})
        ]

        # Run
        result = instance.sample(5)

        # Check
        assert isinstance(result, np.ndarray)
        assert result.shape == (5, 2)
        compare_nested_iterables(result, expected_result)
        assert uniform_mock.call_args_list == expected_uniform_call_args_list

    def test_cdf_zero_if_single_arg_is_zero(self):
        """Test of the analytical properties of copulas on a range of values of theta."""
        # Setup
        instance = Frank()
        tau_values = np.linspace(-1.0, 1.0, 20)[1: -1]

        # Run/Check
        for tau in tau_values:
            instance.tau = tau
            instance.theta = instance.compute_theta()
            copula_zero_if_arg_zero(instance)

    def test_cdf_value_if_all_other_arg_are_one(self):
        """Test of the analytical properties of copulas on a range of values of theta."""
        # Setup
        instance = Frank()
        tau_values = np.linspace(-1.0, 1.0, 20)[1: -1]

        # Run/Check
        for tau in tau_values:
            instance.tau = tau
            instance.theta = instance.compute_theta()
            copula_single_arg_not_one(instance, tolerance=1E-03)
Example #7
0
class TestFrank(TestCase):
    def setUp(self):
        self.X = np.array([[2641.16233666, 180.2425623],
                           [921.14476418, 192.35609972],
                           [-651.32239137, 150.24830291],
                           [1223.63536668, 156.62123653],
                           [3233.37342355, 173.80311908],
                           [1373.22400821, 191.0922843],
                           [1959.28188858, 163.22252158],
                           [1076.99295365, 190.73280428],
                           [2029.25100261, 158.52982435],
                           [1835.52188141, 163.0101334],
                           [1170.03850556, 205.24904026],
                           [739.42628394, 175.42916046],
                           [1866.65810627, 208.31821984],
                           [3703.49786503, 178.98351969],
                           [1719.45232017, 160.50981075],
                           [258.90206528, 163.19294974],
                           [219.42363944, 173.30395132],
                           [609.90212377, 215.18996298],
                           [1618.44207239, 164.71141696],
                           [2323.2775272, 178.84973821],
                           [3251.78732274, 182.99902513],
                           [1430.63989981, 217.5796917],
                           [-180.57028875, 201.56983421],
                           [-592.84497457, 174.92272693]])
        self.copula = Frank()

    def test_fit(self):
        """On fit, theta and tau attributes are set."""
        # Setup
        expected_theta = 0.1307082
        expected_tau = 0.01449275

        # Run
        self.copula.fit(self.X)
        actual_theta = self.copula.theta
        actual_tau = self.copula.tau

        # Check
        self.assertAlmostEqual(actual_theta, expected_theta, places=3)
        self.assertAlmostEqual(actual_tau, expected_tau)

    def test_probability_density(self):
        """Probability_density returns the probability density for the given values."""
        # Setup
        self.copula.fit(self.X)
        expected_result = 0.999672586804842

        # Run
        result = self.copula.probability_density(np.array([[0.1, 0.5]]))

        # Check
        assert np.isclose(result, expected_result).all()
        assert isinstance(result, np.ndarray)

    def test_cumulative_distribution(self):
        """Cumulative_density returns the probability distribution value for a point."""
        # Setup
        self.copula.fit(self.X)
        expected_result = 0.05147003

        # Run
        result = self.copula.cumulative_distribution(np.array([[0.1, 0.5]]))

        # Check
        assert np.isclose(result, expected_result).all()
        assert isinstance(result, np.ndarray)

    @patch('copulas.bivariate.base.np.random.uniform')
    def test_sample(self, uniform_mock):
        """Sample use the inverse-transform method to generate new samples."""
        # Setup
        instance = Frank()
        instance.tau = 0.5
        instance.theta = instance.compute_theta()

        uniform_mock.return_value = np.array([0.1, 0.2, 0.4, 0.6, 0.8])

        expected_result = np.array([[0.0312640840463779, 0.1],
                                    [0.1007998170183327, 0.2],
                                    [0.3501836319841291, 0.4],
                                    [0.6498163680158703, 0.6],
                                    [0.8992001829816683, 0.8]])

        expected_uniform_call_args_list = [((0, 1, 5), {}), ((0, 1, 5), {})]

        # Run
        result = instance.sample(5)

        # Check
        assert isinstance(result, np.ndarray)
        assert result.shape == (5, 2)
        compare_nested_iterables(result, expected_result)
        assert uniform_mock.call_args_list == expected_uniform_call_args_list

    def test_cdf_zero_if_single_arg_is_zero(self):
        """Test of the analytical properties of copulas on a range of values of theta."""
        # Setup
        instance = Frank()
        tau_values = np.linspace(-1.0, 1.0, 20)[1:-1]

        # Run/Check
        for tau in tau_values:
            instance.tau = tau
            instance.theta = instance.compute_theta()
            copula_zero_if_arg_zero(instance)

    def test_cdf_value_if_all_other_arg_are_one(self):
        """Test of the analytical properties of copulas on a range of values of theta."""
        # Setup
        instance = Frank()
        tau_values = np.linspace(-1.0, 1.0, 20)[1:-1]

        # Run/Check
        for tau in tau_values:
            instance.tau = tau
            instance.theta = instance.compute_theta()
            copula_single_arg_not_one(instance, tolerance=1E-03)
Example #8
0
def select_copula(X):
    r"""Select best copula function based on likelihood.

    Given out candidate copulas the procedure proposed for selecting the one
    that best fit to a dataset of pairs :math:`\{(u_j, v_j )\}, j=1,2,...n` , is as follows:

    1. Estimate the most likely parameter :math:`\theta` of each copula candidate for the given
       dataset.

    2. Construct :math:`R(z|\theta)`. Calculate the area under the tail for each of the copula
       candidates.

    3. Compare the areas: :math:`a_u` achieved using empirical copula against the ones
       achieved for the copula candidates. Score the outcome of the comparison from 3 (best)
       down to 1 (worst).

    4. Proceed as in steps 2- 3 with the lower tail and function :math:`L`.

    5. Finally the sum of empirical upper and lower tail functions is compared against
       :math:`R + L`. Scores of the three comparisons are summed and the candidate with the
       highest value is selected.

    Args:
        X(np.ndarray): Matrix of shape (n,2).

    Returns:
        copula: Best copula that fits for it.

    """
    frank = Frank()
    frank.fit(X)

    if frank.tau <= 0:
        return frank

    copula_candidates = [frank]

    # append copulas into the candidate list
    for copula_class in [Clayton, Gumbel]:
        try:
            copula = copula_class()
            copula.tau = frank.tau
            copula._compute_theta()
            copula_candidates.append(copula)
        except ValueError:
            pass

    left_tail, empirical_left_aut, right_tail, empirical_right_aut = _compute_empirical(
        X)
    candidate_left_auts, candidate_right_auts = _compute_candidates(
        copula_candidates, left_tail, right_tail)

    empirical_aut = np.concatenate((empirical_left_aut, empirical_right_aut))
    candidate_auts = [
        np.concatenate((l, r))
        for l, r in zip(candidate_left_auts, candidate_right_auts)
    ]

    # compute L2 distance from empirical distribution
    diff_left = [
        np.sum((empirical_left_aut - l)**2) for l in candidate_left_auts
    ]
    diff_right = [
        np.sum((empirical_right_aut - r)**2) for r in candidate_right_auts
    ]
    diff_both = [
        np.sum((empirical_aut - candidate)**2) for candidate in candidate_auts
    ]

    # calcule ranks
    score_left = pd.Series(diff_left).rank(ascending=False)
    score_right = pd.Series(diff_right).rank(ascending=False)
    score_both = pd.Series(diff_both).rank(ascending=False)

    score = score_left + score_right + score_both

    selected_copula = np.argmax(score.values)
    return copula_candidates[selected_copula]