Esempio n. 1
0
    def jsd_diss(self, w1, mu1, cov1, w2, mu2, cov2):
        """
		Calculates Jensen-Shannon divergence of two gmm's
		:param gmm_p: mixture.GaussianMixture
		:param gmm_q: mixture.GaussianMixture
		:param sample_count: number of monte carlo samples to use
		:return: Jensen-Shannon divergence
		"""
        gmm_p = GaussianMixture(n_components=n_components,
                                covariance_type="full")
        gmm_p.weights_ = w1
        gmm_p.covariances_ = cov1
        gmm_p.means_ = mu1
        gmm_p.n_components = 1
        gmm_p.precisions_cholesky_ = _compute_precision_cholesky(cov1, "full")

        gmm_q = GaussianMixture(n_components=n_components,
                                covariance_type="full")
        gmm_q.weights_ = w2
        gmm_q.covariances_ = cov2
        gmm_q.means_ = mu2
        gmm_q.n_components = 1
        gmm_q.precisions_cholesky_ = _compute_precision_cholesky(cov2, "full")

        X = gmm_p.sample(sample_count)[0]
        log_p_X = gmm_p.score_samples(X)
        log_q_X = gmm_q.score_samples(X)
        log_mix_X = np.logaddexp(log_p_X, log_q_X)

        Y = gmm_q.sample(sample_count)[0]
        log_p_Y = gmm_p.score_samples(Y)
        log_q_Y = gmm_q.score_samples(Y)
        log_mix_Y = np.logaddexp(log_p_Y, log_q_Y)

        # black magic?
        return (log_p_X.mean() -
                (log_mix_X.mean() - np.log(2)) + log_q_Y.mean() -
                (log_mix_Y.mean() - np.log(2))) / 2
Esempio n. 2
0
def gmm_combine(gmms, weights=None, params=None, good_idx=None,
                gmms_means=None, gmms_variances=None, gmms_weights=None, gmms_zps=None):
    """
    Method to combine Gaussian Mixture Models. This function create a new GaussianMixture instance and adds all
    mixture components from the input models.

    Parameters
    ----------
    gmms
        List of GaussianMixture instances to combine.
    weights : iterable, optional
        Weights for each GaussianMixture instance in the input list.
    params : dict, optional
        GaussianMixture parameter dictionary for faster instantiation.
    good_idx : iterable, optional
        Boolean array or list for masking. True indicates a good entry in the input list, False a bad entry.
    gmms_means : np.ndarray, optional
        The means of all components for all input GMMs in an array. Can be used to speed up the combination process-
    gmms_variances : np.ndarray, optional
        Same as gmms_means, but for all variances of all components.
    gmms_weights : np.ndarray, optional
        Same as gmms_means, but for all weights of all components.
    gmms_zps : np.ndarray, optional
        Zero point for all models. If None is given, no shift is applied.

    Returns
    -------
    GaussianMixture
        Combined GaussianMixture instance.

    """

    # Dummy checks
    if not isinstance(gmms, Iterable):
        raise ValueError("Models must be provided as an iterable")

    # Set good_idx
    if good_idx is None:
        good_idx = [True for _ in range(len(gmms))]

    # Extract good GMMs
    gmms = gmms[good_idx]

    # Set weights to unity if not specified
    if weights is None:
        weights = [1 for _ in range(len(gmms))]
    else:
        weights = weights[good_idx]

    # Return None if weights are all bad
    if np.sum(np.isfinite(weights)) == 0:
        return None

    # Set zeropoints if not specified
    if gmms_zps is None:
        gmms_zps = [0. for _ in range(len(gmms))]
    else:
        gmms_zps = gmms_zps[good_idx]

    # Get parameters if not set from first entry
    if params is None:
        params = gmms[0].get_params()

    # Dummy check
    if np.sum([isinstance(g, GaussianMixture) for g in gmms]) != len(gmms):
        raise ValueError("Must only supply GaussianMixture instances")

    # Instantiate combined GMM
    gmm_combined = GaussianMixture(**params)

    # Build combined components from supplied models if not given as attributes
    if gmms_means is None or gmms_variances is None or gmms_weights is None:

        gmm_combined_means = gmms[0].means_ + gmms_zps[0]
        gmm_combined_variances = gmms[0].covariances_
        gmm_combined_weights = gmms[0].weights_ * weights[0]
        for gmm, w, zp in zip(gmms[1:], weights[1:], gmms_zps[1:]):
            gmm_combined_means = np.vstack([gmm_combined_means, gmm.means_ + zp])
            gmm_combined_variances = np.vstack([gmm_combined_variances, gmm.covariances_])
            gmm_combined_weights = np.hstack([gmm_combined_weights, gmm.weights_ * w])

    # If the attributes are provided, extract the parameters directly (much faster)
    else:
        gmm_combined_means = np.vstack(gmms_means[good_idx] + gmms_zps)
        gmm_combined_variances = np.vstack(gmms_variances[good_idx])
        gmm_combined_weights = np.hstack(gmms_weights[good_idx] * weights)

    # Add attributes to new mixture
    gmm_combined.n_components = len(gmm_combined_means)
    gmm_combined.means_ = gmm_combined_means
    gmm_combined.covariances_ = gmm_combined_variances
    gmm_combined.weights_ = gmm_combined_weights / np.sum(gmm_combined_weights)
    gmm_combined.precisions_ = np.linalg.inv(gmm_combined.covariances_)
    gmm_combined.precisions_cholesky_ = np.linalg.cholesky(gmm_combined.precisions_)

    # Add attribute to store number of input models used to create this model
    gmm_combined.n_models = len(gmms)

    # Return new GMM
    return gmm_combined