Exemple #1
0
def fit_cor(copula, data: np.ndarray, typ: str) -> np.ndarray:
    """
    Constructs parameter matrix from matrix of Kendall's Taus or Spearman's Rho

    Parameters
    ----------
    copula: BaseCopula
        Copula instance

    data: ndarray
        Data to fit copula with
    typ: {'irho', 'itau'}
        The type of rank correlation measure to use. 'itau' uses Kendall's tau while 'irho' uses Spearman's rho

    Returns
    -------
    ndarray
        Parameter matrix is copula is elliptical. Otherwise, a vector
    """

    indices = tri_indices(copula.dim, 1, 'lower')
    if typ == 'itau':
        tau = kendall_tau(data)[indices]
        theta = copula.itau(tau)
    elif typ == 'irho':
        rho = spearman_rho(data)[indices]
        theta = copula.irho(rho)
    else:
        raise ValueError(
            "Correlation Inversion must be either 'itau' or 'irho'")

    if is_elliptical(copula):
        theta = near_psd(create_cov_matrix(theta))[indices]

    return theta
Exemple #2
0
    def initial_params(self) -> np.ndarray:
        if self.x0 is not None:
            return self.x0

        if is_elliptical(self.copula):
            corr = pearson_rho(self.data)
            rhos = corr[tri_indices(self.copula.dim, 1, 'lower')]
            if hasattr(self.copula, '_df'):
                # T-distribution
                return np.array([4.669,
                                 *rhos])  # set df as Feigenbaum's constant
            else:
                # Gaussian
                return rhos

        try:
            start = CorrInversionEstimator(self.copula, self.data,
                                           self.verbose).fit('itau')

            ll = self.copula.log_lik(self.data)

            if np.isfinite(ll):
                return start
            else:
                if self.copula.name.lower(
                ) == 'clayton' and self.copula.dim == 2:
                    # The support of bivariate claytonCopula with negative parameter is not
                    # the full unit square; the further from 0, the more restricted.
                    while start < 0:
                        start += .2
                        self.copula.params = start
                        if np.isfinite(self.copula.log_lik(self.data)):
                            break

                if not np.isnan(ll) and np.isinf(ll):
                    # for perfectly correlated data
                    return start
                return self.copula.params
        except NotImplementedError:
            return self.copula.params
Exemple #3
0
def initial_params(copula: Copula, data: np.ndarray, x0: np.ndarray):
    # ensure that initial is defined. If it is defined, checks that all x0 values are finite
    # neither infinite nor nan
    if x0 is not None and \
            ((np.isscalar(x0) and not np.isfinite(x0)) or (not np.isscalar(x0) and all(np.isfinite(x0)))):
        return x0

    if is_elliptical(copula):
        corr = pearson_rho(data)
        rhos = corr[tri_indices(copula.dim, 1, 'lower')]
        if copula.name.lower() == 'student':
            # T-distribution
            return np.array([4.669, *rhos])  # set df as Feigenbaum's constant
        else:
            # Gaussian
            return rhos

    try:
        start = estimate_corr_inverse_params(copula, data, 'itau')
        ll = copula.log_lik(data)

        if np.isfinite(ll):
            return start
        else:
            if copula.name.lower() == 'clayton' and copula.dim == 2:
                # The support of bivariate claytonCopula with negative parameter is not
                # the full unit square; the further from 0, the more restricted.
                while start < 0:
                    start += .2
                    copula.params = start
                    if np.isfinite(copula.log_lik(data)):
                        break

            if not np.isnan(ll) and np.isinf(ll):
                # for perfectly correlated data
                return start
            return copula.params
    except NotImplementedError:
        return copula.params
Exemple #4
0
def estimate_corr_inverse_params(copula, data: np.ndarray,
                                 type_: Literal['itau', 'irho']):
    """
    Fits the copula with the inversion of Spearman's rho or Kendall's tau Estimator

    Parameters
    ----------
    copula
        Copula whose parameters are to be estimated
    data
        Data to fit the copula with
    type_ : {'irho', 'itau'}
        The type of rank correlation measure to use. 'itau' uses Kendall's tau while 'irho' uses Spearman's rho
    """

    type_ = type_.lower()
    if type_ not in ('itau', 'irho'):
        raise ValueError(
            "Correlation Inversion must be either 'itau' or 'irho'")

    icor = fit_cor(copula, data, type_)

    if is_elliptical(copula):
        estimate = icor
        copula.params[:] = estimate
    elif is_archimedean(copula):
        estimate = np.mean(icor)
        copula.params = estimate
    else:
        raise NotImplementedError(
            f"Have not developed for '{copula.name} copula'")

    method = f"Inversion of {'Spearman Rho' if type_ == 'irho' else 'Kendall Tau'} Correlation"

    copula.fit_smry = FitSummary(estimate, method, copula.log_lik(data),
                                 len(data))

    return estimate
Exemple #5
0
    def fit(self, typ: str) -> np.ndarray:
        """
        Fits the copula with the inversion of Spearman's rho or Kendall's tau Estimator

        Parameters
        ----------
        typ: {'irho', 'itau'}
            The type of rank correlation measure to use. 'itau' uses Kendall's tau while 'irho' uses Spearman's rho

        Returns
        -------
        ndarray
            Estimates for the copula
        """
        typ = typ.lower()
        if typ not in ('itau', 'irho'):
            raise ValueError(
                "Correlation Inversion must be either 'itau' or 'irho'")

        icor = fit_cor(self.copula, self.data, typ)

        if is_elliptical(self.copula):
            estimate = icor
            self.copula.params[:] = estimate
        elif is_archimedean(self.copula):
            estimate = np.mean(icor)
            self.copula.params = estimate
        else:
            raise NotImplementedError(
                f"Have not developed for '{self.copula.name} copula'")

        method = f"Inversion of {'Spearman Rho' if typ == 'irho' else 'Kendall Tau'} Correlation"

        self.copula.fit_smry = FitSummary(estimate, method,
                                          self.copula.log_lik(self.data),
                                          len(self.data))

        return estimate