def partial_derivative(self, X): r"""Compute partial derivative of cumulative distribution. The partial derivative of the copula(CDF) is the conditional CDF. .. math:: F(v|u) = \frac{\partial C(u,v)}{\partial u} = C(u,v)\frac{((-\ln u)^{\theta} + (-\ln v)^{\theta})^{\frac{1}{\theta} - 1}} {\theta(- \ln u)^{1 -\theta}} Args: X (np.ndarray) y (float) Returns: numpy.ndarray """ self.check_fit() U, V = split_matrix(X) if self.theta == 1: return V else: t1 = np.power(-np.log(U), self.theta) t2 = np.power(-np.log(V), self.theta) p1 = self.cumulative_distribution(X) p2 = np.power(t1 + t2, -1 + 1.0 / self.theta) p3 = np.power(-np.log(V), self.theta - 1) return np.divide(np.multiply(np.multiply(p1, p2), p3), V)
def probability_density(self, X): r"""Compute probability density function for given copula family. The probability density(PDF) for the Frank family of copulas correspond to the formula: .. math:: c(U,V) = \frac{\partial^2 C(u,v)}{\partial v \partial u} = \frac{-\theta g(1)(1 + g(u + v))}{(g(u) g(v) + g(1)) ^ 2} Where the g function is defined by: .. math:: g(x) = e^{-\theta x} - 1 Args: X: `np.ndarray` Returns: np.array: probability density """ self.check_fit() U, V = split_matrix(X) if self.theta == 0: return np.multiply(U, V) else: num = np.multiply(np.multiply(-self.theta, self._g(1)), 1 + self._g(np.add(U, V))) aux = np.multiply(self._g(U), self._g(V)) + self._g(1) den = np.power(aux, 2) return num / den
def cumulative_distribution(self, X): r"""Compute the cumulative distribution function for the Gumbel copula. The cumulative density(cdf), or distribution function for the Gumbel family of copulas correspond to the formula: .. math:: C(u,v) = e^{-((-\ln u)^{\theta} + (-\ln v)^{\theta})^{\frac{1}{\theta}}} Args: X (np.ndarray) Returns: np.ndarray: cumulative probability for the given datapoints, cdf(X). """ self.check_fit() U, V = split_matrix(X) if self.theta == 1: return np.multiply(U, V) else: h = np.power(-np.log(U), self.theta) + np.power(-np.log(V), self.theta) h = -np.power(h, 1.0 / self.theta) cdfs = np.exp(h) return cdfs
def cumulative_distribution(self, X): r"""Compute the cumulative distribution function for the Frank copula. The cumulative density(cdf), or distribution function for the Frank family of copulas correspond to the formula: .. math:: C(u,v) = −\frac{\ln({\frac{1 + g(u) g(v)}{g(1)}})}{\theta} Args: X: `np.ndarray` Returns: np.array: cumulative distribution """ self.check_fit() U, V = split_matrix(X) num = np.multiply( np.exp(np.multiply(-self.theta, U)) - 1, np.exp(np.multiply(-self.theta, V)) - 1) den = np.exp(-self.theta) - 1 return -1.0 / self.theta * np.log(1 + num / den)
def cumulative_distribution(self, X): """Compute the cumulative distribution function for the clayton copula. The cumulative density(cdf), or distribution function for the Clayton family of copulas correspond to the formula: .. math:: C(u,v) = max[(u^{-θ} + v^{-θ} - 1),0]^{-1/θ} Args: X (numpy.ndarray) Returns: numpy.ndarray: cumulative probability. """ self.check_fit() U, V = split_matrix(X) if (V == 0).all() or (U == 0).all(): return np.zeros(V.shape[0]) else: cdfs = [ np.power( np.power(U[i], -self.theta) + np.power(V[i], -self.theta) - 1, -1.0 / self.theta ) if (U[i] > 0 and V[i] > 0) else 0 for i in range(len(U)) ] return np.array([max(x, 0) for x in cdfs])
def partial_derivative(self, X): r"""Compute partial derivative of cumulative distribution. The partial derivative of the copula(CDF) is the conditional CDF. .. math:: F(v|u) = \frac{\partial}{\partial u}C(u,v) = \frac{g(u)g(v) + g(v)}{g(u)g(v) + g(1)} Args: X (np.ndarray) y (float) Returns: np.ndarray """ self.check_fit() U, V = split_matrix(X) if self.theta == 0: return V else: num = np.multiply(self._g(U), self._g(V)) + self._g(U) den = np.multiply(self._g(U), self._g(V)) + self._g(1) return num / den
def partial_derivative(self, X, y=0): r"""Compute partial derivative of cumulative distribution. The partial derivative of the copula(CDF) is the value of the conditional probability. .. math:: F(v|u) = \frac{\partial C(u,v)}{\partial u} = u^{- \theta - 1}(u^{-\theta} + v^{-\theta} - 1)^{-\frac{\theta+1}{\theta}} Args: X (np.ndarray) y (float) Returns: numpy.ndarray: Derivatives """ self.check_fit() U, V = split_matrix(X) A = np.power(V, -self.theta - 1) # If theta tends to inf, A tends to inf # And the next partial_derivative tends to 0 if (A == np.inf).any(): return np.zeros(len(V)) B = np.power(V, -self.theta) + np.power(U, -self.theta) - 1 h = np.power(B, (-1 - self.theta) / self.theta) return np.multiply(A, h) - y
def probability_density(self, X): r"""Compute probability density function for given copula family. The probability density(PDF) for the Gumbel family of copulas correspond to the formula: .. math:: c(U,V) = \frac{\partial^2 C(u,v)}{\partial v \partial u} = \frac{C(u,v)}{uv} \frac{((-\ln u)^{\theta} + (-\ln v)^{\theta})^{\frac{2} {\theta} - 2 }}{(\ln u \ln v)^{1 - \theta}} ( 1 + (\theta-1) \big((-\ln u)^\theta + (-\ln v)^\theta\big)^{-1/\theta}) Args: X (numpy.ndarray) Returns: numpy.ndarray """ self.check_fit() U, V = split_matrix(X) if self.theta == 1: return np.multiply(U, V) else: a = np.power(np.multiply(U, V), -1) tmp = np.power(-np.log(U), self.theta) + np.power( -np.log(V), self.theta) b = np.power(tmp, -2 + 2.0 / self.theta) c = np.power(np.multiply(np.log(U), np.log(V)), self.theta - 1) d = 1 + (self.theta - 1) * np.power(tmp, -1.0 / self.theta) return self.cumulative_distribution(X) * a * b * c * d
def _compute_empirical(X): """Compute empirical distribution. Args: X(numpy.array): Shape (n,2); Datapoints to compute the empirical(frequentist) copula. Return: tuple(list): """ z_left = [] z_right = [] L = [] R = [] U, V = split_matrix(X) N = len(U) base = np.linspace(EPSILON, 1.0 - EPSILON, COMPUTE_EMPIRICAL_STEPS) # See https://github.com/DAI-Lab/Copulas/issues/45 for k in range(COMPUTE_EMPIRICAL_STEPS): left = sum(np.logical_and(U <= base[k], V <= base[k])) / N right = sum(np.logical_and(U >= base[k], V >= base[k])) / N if left > 0: z_left.append(base[k]) L.append(left / base[k]**2) if right > 0: z_right.append(base[k]) R.append(right / (1 - z_right[k])**2) return z_left, L, z_right, R
def fit(self, X): """Fit a model to the data updating the parameters. Args: X(np.ndarray): Array of datapoints with shape (n,2). Return: None """ U, V = split_matrix(X) self.tau = stats.kendalltau(U, V)[0] self._compute_theta()
def partial_derivative(self, X): """Compute the conditional probability of one event conditiones to the other. In the case of the independence copula, due to C(u,v) = u*v, we have that F(u|v) = dC/du = v. Args: X() """ _, V = split_matrix(X) return V
def cumulative_distribution(self, X): """Compute the cumulative distribution of the independence bivariate copula is the product. Args: X(numpy.array): Matrix of shape (n,2), whose values are in [0, 1] Returns: numpy.array: Cumulative distribution values of given input. """ U, V = split_matrix(X) return np.multiply(U, V)
def fit(self, X): """Fit a model to the data updating the parameters. Args: X(np.ndarray): Array of datapoints with shape (n,2). Return: None """ U, V = split_matrix(X) self.check_marginal(U) self.check_marginal(V) self.tau = stats.kendalltau(U, V)[0] if np.isnan(self.tau): if len(np.unique(U)) == 1 or len(np.unique(V)) == 1: raise ValueError("Constant column.") raise ValueError("Unable to compute tau.") self._compute_theta()
def probability_density(self, X): r"""Compute probability density function for given copula family. The probability density(PDF) for the Clayton family of copulas correspond to the formula: .. math:: c(U,V) = \frac{\partial^2}{\partial v \partial u}C(u,v) = (\theta + 1)(uv)^{-\theta-1}(u^{-\theta} + v^{-\theta} - 1)^{-\frac{2\theta + 1}{\theta}} Args: X (numpy.ndarray) Returns: numpy.ndarray: Probability density for the input values. """ self.check_fit() U, V = split_matrix(X) a = (self.theta + 1) * np.power(np.multiply(U, V), -(self.theta + 1)) b = np.power(U, -self.theta) + np.power(V, -self.theta) - 1 c = -(2 * self.theta + 1) / self.theta return a * np.power(b, c)