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
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
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
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
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