Example #1
0
    def fit(self,
            Y_normalized,
            embedding,
            initialization,
            iterations=100,
            max_concentration_cw=100,
            max_concentration_vmf=500):
        """

        Args:
            Y_normalized: Mix with shape (..., T, D).
            embedding: Embedding from Deep Clustering with shape (..., T, E).
            initialization: Shape (..., K, T)
            iterations:
            max_concentration_cw:
            max_concentration_vmf:

        Returns:

        """
        Y_normalized_for_psd = np.copy(np.swapaxes(Y_normalized, -2, -1), 'C')
        Y_normalized_for_pdf = np.copy(Y_normalized, 'C')
        affiliations = np.copy(initialization)
        D = Y_normalized.shape[-2]
        cw = ComplexWatson(D, max_concentration=max_concentration_cw)

        for i in range(iterations):
            # E step
            if i > 0:
                affiliations = self.predict(Y_normalized_for_pdf, embedding)

            # M step
            self.pi = affiliations.mean(axis=-1)
            Phi = get_power_spectral_density_matrix(Y_normalized_for_psd,
                                                    np.copy(affiliations, 'C'),
                                                    sensor_dim=-2,
                                                    source_dim=-2,
                                                    time_dim=-1)
            self.W, eigenvalues = get_pca(Phi)
            self.kappa_cw = cw.hypergeometric_ratio_inverse(eigenvalues)
            self.mu, self.kappa_vmf = VonMisesFisher.fit(
                embedding,
                reshape(affiliations, 'fkt->k,t*f'),
                max_concentration=max_concentration_vmf)
Example #2
0
    def fit(self,
            Y_normalized,
            initialization,
            iterations=100,
            max_concentration=100):
        """ EM for CWMMs with any number of independent dimensions.

        Does not support sequence lengths.
        Can later be extended to accept more initializations, but for now
        only accepts affiliations (masks) as initialization.

        Args:
            Y_normalized: Mix with shape (..., T, D).
            initialization: Shape (..., K, T)
            iterations: Most of the time 10 iterations are acceptable.
            max_concentration: For numerical stability reasons.
        """
        Y_normalized_for_pdf = np.copy(Y_normalized, 'C')
        Y_normalized_for_psd = np.copy(np.swapaxes(Y_normalized, -2, -1), 'C')

        D = Y_normalized.shape[-2]
        cw = ComplexWatson(D, max_concentration=max_concentration)

        affiliations = np.copy(initialization)

        for i in range(iterations):
            # E step
            if i > 0:
                affiliations = self.predict(Y_normalized_for_pdf)

            # M step
            self.pi = np.mean(affiliations, axis=-1)
            Phi = get_power_spectral_density_matrix(Y_normalized_for_psd,
                                                    np.copy(affiliations, 'C'),
                                                    sensor_dim=-2,
                                                    source_dim=-2,
                                                    time_dim=-1)

            self.W, eigenvalues = get_pca(Phi)
            self.kappa = cw.hypergeometric_ratio_inverse(eigenvalues)
Example #3
0
    def fit(
        self,
        Y,
        initialization,
        source_activity_mask=None,
        iterations=100,
        max_concentration=100,
    ) -> ComplexWatsonMixtureModelParameters:
        """ EM for CWMMs with any number of independent dimensions.

        Does not support sequence lengths.
        Can later be extended to accept more initializations, but for now
        only accepts affiliations (masks) as initialization.

        Args:
            Y_normalized: Mix with shape (..., T, D).
            initialization: Shape (..., K, T)
            iterations: Most of the time 10 iterations are acceptable.
            max_concentration: For numerical stability reasons.
        """

        *independent, T, D = Y.shape
        independent = tuple(independent)

        assert D < 20, (D, 'Sure?')

        if isinstance(initialization, self.Parameters):
            K = initialization.mixture_weights.shape[-1]
            assert K < 20, (K, 'Sure?')
        else:
            K = initialization.shape[-2]
            assert K < 20, (K, 'Sure?')
            assert initialization.shape[-1] == T, (initialization.shape, T)
            assert initialization.shape[:-2] == independent, (
                initialization.shape, independent)

        Y = _unit_norm(Y, axis=-1, eps=1e-10, eps_style='where')

        Y_normalized_for_pdf = np.ascontiguousarray(Y)
        Y_normalized_for_psd = np.ascontiguousarray(np.swapaxes(Y, -2, -1))

        if isinstance(initialization, self.Parameters):
            params = initialization
        else:
            params = self.Parameters(eps=self.eps)
            params.affiliation = np.copy(initialization)  # Shape (..., K, T)

        cw = ComplexWatson(D, max_concentration=max_concentration)

        if isinstance(initialization, self.Parameters):
            range_iterations = range(1, 1 + iterations)
        else:
            range_iterations = range(iterations)

        if self.pbar:
            import tqdm
            range_iterations = tqdm.tqdm(range_iterations, 'cWMM Iteration')
        else:
            range_iterations = range_iterations

        for i in range_iterations:
            # E step
            if i > 0:
                params.affiliation = params._predict(
                    Y_normalized_for_pdf,
                    source_activity_mask=source_activity_mask,
                )

            # M step
            params.mixture_weights = np.mean(params.affiliation, axis=-1)

            Phi = get_power_spectral_density_matrix(Y_normalized_for_psd,
                                                    np.maximum(
                                                        params.affiliation,
                                                        params.eps),
                                                    sensor_dim=-2,
                                                    source_dim=-2,
                                                    time_dim=-1)

            params.complex_watson.mode, eigenvalues = get_pca(Phi)
            params.complex_watson.concentration = \
                cw.hypergeometric_ratio_inverse(eigenvalues)
        return params