コード例 #1
0
    def test_min_rmse_rate(self):
        warnings.filterwarnings("ignore")

        # Check that the minimum RMSE solution is returned

        n_freqs = 10
        n_wavs = 100
        n_iterations = 50
        n_sources = 5
        lam_p = [0.0] * 5

        # Generate ground truth A and S
        A_org = np.random.normal(size=(n_freqs, n_sources))
        helpers.A_norm(A_org)
        S_org = np.random.normal(size=(n_sources, n_wavs))
        X = np.dot(A_org, S_org)

        # Initialize A and S for GMCA
        A_p = np.ones(A_org.shape)
        helpers.A_norm(A_p)
        A = np.ones(A_org.shape)
        helpers.A_norm(A)
        S = np.ones(S_org.shape)

        # Run GMCA
        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A,
                             S,
                             A_p,
                             lam_p,
                             ret_min_rmse=False,
                             min_rmse_rate=n_iterations)

        # Check that GMCA returns the minimum RMSE solution
        np.testing.assert_almost_equal(S, np.dot(np.linalg.pinv(A), X))

        # Reset A and S
        A = np.ones(A_org.shape)
        helpers.A_norm(A)
        S = np.ones(S_org.shape)

        # Re-run GMCA without ret_min_rmse
        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A,
                             S,
                             A_p,
                             lam_p,
                             ret_min_rmse=False,
                             min_rmse_rate=n_iterations - 1)

        # Check that GMCA does not return the min_rmse solution
        self.assertGreater(np.mean(np.abs(S - np.dot(np.linalg.pinv(A), X))),
                           1e-4)
コード例 #2
0
    def test_wrapper(self):
        # Test that the wrapper returns the same results as the numba
        # implementation
        freq_dim = 10
        pix_dim = 100
        n_iterations = 10
        n_sources = 5
        lam_p = [0.0] * 5

        X = np.random.normal(loc=1000, size=(freq_dim, pix_dim))

        A_numba = np.random.normal(size=(freq_dim, n_sources))
        helpers.A_norm(A_numba)
        S_numba = np.ones((n_sources, pix_dim))

        A_p = np.random.normal(size=(freq_dim, n_sources))
        helpers.A_norm(A_p)

        lam_s_vals = [0, 10]
        lam_p_vals = [0, 1000]
        min_rmse_rates = [0, 2]
        ret_min_rmse_vals = [True, False]
        enforce_nn_A = True

        for lam_s in lam_s_vals:
            for lam_p_val in lam_p_vals:
                lam_p = [lam_p_val] * n_sources
                for min_rmse_rate in min_rmse_rates:
                    for ret_min_rmse in ret_min_rmse_vals:
                        A_init = np.copy(A_numba)
                        S_init = np.copy(S_numba)
                        A, S = gmca_core.gmca(X,
                                              n_sources,
                                              n_iterations,
                                              A_init,
                                              S_init,
                                              A_p,
                                              lam_p,
                                              enforce_nn_A,
                                              lam_s,
                                              ret_min_rmse,
                                              min_rmse_rate,
                                              seed=2)
                        gmca_core.gmca_numba(X,
                                             n_sources,
                                             n_iterations,
                                             A_numba,
                                             S_numba,
                                             A_p,
                                             lam_p,
                                             enforce_nn_A,
                                             lam_s,
                                             ret_min_rmse,
                                             min_rmse_rate,
                                             seed=2)
                        self.assertAlmostEqual(np.max(np.abs(A_numba - A)), 0)
                        self.assertAlmostEqual(np.max(np.abs(S_numba - S)), 0)
コード例 #3
0
    def test_ret_min_rmse(self):
        warnings.filterwarnings("ignore")

        # Check that the minimum RMSE solution is returned
        n_freqs = 10
        n_wavs = 100
        n_iterations = 50
        n_sources = 5
        lam_p = [0.0] * 5

        # Generate ground truth A and S
        A_org = np.random.normal(size=(n_freqs, n_sources))
        S_org = np.random.normal(size=(n_sources, n_wavs))
        X = np.dot(A_org, S_org)

        # Initialize A and S for GMCA
        A_p = np.ones(A_org.shape)
        A = np.ones(A_org.shape)
        S = np.ones(S_org.shape)

        # Run GMCA
        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A,
                             S,
                             A_p,
                             lam_p,
                             ret_min_rmse=True)

        # Check that GMCA returns the minimum RMSE solution
        self.assertAlmostEqual(np.sum(S), np.sum(np.dot(np.linalg.pinv(A), X)))

        # Reset A and S
        A = np.ones(A_org.shape)
        S = np.ones(S_org.shape)

        # Re-run GMCA without ret_min_rmse
        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A,
                             S,
                             A_p,
                             lam_p,
                             ret_min_rmse=False)

        # Check that GMCA does not return the min_rmse solution
        self.assertNotEqual(np.sum(S), np.sum(np.dot(np.linalg.pinv(A), X)))
コード例 #4
0
    def test_init_consistent(self):
        # Test that passing or not passing in the initialization returns the
        # same thing.
        n_freqs = 10
        n_wavs = 100
        n_sources = 5
        n_iterations = 10
        lam_p = np.array([0.0] * 5)
        X = np.random.normal(size=(n_freqs, n_wavs))

        # Run GMCA
        A_p = np.ones((n_freqs, n_sources))
        A = np.ones((n_freqs, n_sources))
        S = np.ones((n_sources, n_wavs))
        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A,
                             S,
                             A_p,
                             lam_p,
                             ret_min_rmse=True,
                             seed=2)

        # Premade initializations
        R_i = np.zeros(X.shape)
        AS = np.zeros(X.shape)
        A_R = np.zeros((1, X.shape[1]))
        A_i = np.zeros((A.shape[0], 1))
        A2 = np.ones((n_freqs, n_sources))
        S2 = np.ones((n_sources, n_wavs))
        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A2,
                             S2,
                             A_p,
                             lam_p,
                             ret_min_rmse=True,
                             seed=2,
                             R_i_init=R_i,
                             AS_init=AS,
                             A_R_init=A_R,
                             A_i_init=A_i)

        np.testing.assert_almost_equal(S, S2)
        np.testing.assert_almost_equal(A, A2)
コード例 #5
0
    def test_random_seed(self):
        warnings.filterwarnings("ignore")

        # Test that setting the random seed leads to consistent results.
        freq_dim = 10
        pix_dim = 100
        n_iterations = 1
        n_sources = 5
        lam_p = [0.0] * 5

        # Generate ground truth A and S
        A_org = np.abs(np.random.normal(size=(freq_dim, n_sources)))
        S_org = np.random.normal(loc=1000, size=(n_sources, pix_dim))
        X = np.dot(A_org, S_org)

        # Initialize A and S for GMCA
        A_p = np.ones(A_org.shape)
        A1 = np.ones(A_org.shape)
        S1 = np.ones(S_org.shape)
        A2 = np.ones(A_org.shape)
        S2 = np.ones(S_org.shape)
        A3 = np.ones(A_org.shape)
        S3 = np.ones(S_org.shape)

        # Run GMCA with different seeds.
        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A1,
                             S1,
                             A_p,
                             lam_p,
                             ret_min_rmse=False,
                             min_rmse_rate=n_iterations,
                             enforce_nn_A=False,
                             seed=1)
        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A2,
                             S2,
                             A_p,
                             lam_p,
                             ret_min_rmse=False,
                             min_rmse_rate=n_iterations,
                             enforce_nn_A=False,
                             seed=1)
        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A3,
                             S3,
                             A_p,
                             lam_p,
                             ret_min_rmse=False,
                             min_rmse_rate=n_iterations,
                             enforce_nn_A=False,
                             seed=2)

        # Make sure the two runs with the same random seed give the same
        # answer. Given that we only ran for 1 iteration, make sure that
        # different random seeds do not give the same answer.
        self.assertAlmostEqual(np.max(np.abs(A1 - A2)), 0)
        self.assertAlmostEqual(np.max(np.abs(S1 - S2)), 0)

        self.assertGreater(np.mean(np.abs(A1 - A3)), 1e-7)
        self.assertGreater(np.mean(np.abs(S1 - S3)), 1e-7)
コード例 #6
0
    def test_gmca_end_to_end(self):
        warnings.filterwarnings("ignore")

        # Test that gmca works end to end, returning reasonable results.
        rseed = 5
        n_freqs = 10
        n_wavs = int(1e3)
        n_iterations = 50
        n_sources = 5
        lam_s = 1e-5
        lam_p = [0.0] * n_sources
        s_mag = 1e3

        # Generate ground truth A and S
        A_org = np.random.rand(n_freqs * n_sources).reshape(
            (n_freqs, n_sources))
        helpers.A_norm(A_org)
        S_org = np.random.rand(n_sources * n_wavs).reshape((n_sources, n_wavs))
        S_org *= s_mag
        X = np.dot(A_org, S_org)

        # Initialize A and S for GMCA
        A_p = np.ones(A_org.shape)
        helpers.A_norm(A_p)
        A = np.ones(A_org.shape)
        helpers.A_norm(A)
        S = np.ones(S_org.shape)

        # Run GMCA
        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A,
                             S,
                             A_p,
                             lam_p,
                             lam_s=lam_s,
                             ret_min_rmse=False,
                             min_rmse_rate=2 * n_iterations,
                             enforce_nn_A=True,
                             seed=rseed)

        # Save sparsity of S for later test
        sparsity_1 = np.sum(np.abs(S))
        err1 = np.sum(np.abs(np.dot(A, S) - X))

        # Continue GMCA
        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A,
                             S,
                             A_p,
                             lam_p,
                             lam_s=lam_s,
                             ret_min_rmse=False,
                             min_rmse_rate=2 * n_iterations,
                             enforce_nn_A=True,
                             seed=rseed)
        err2 = np.sum(np.abs(np.dot(A, S) - X))

        self.assertGreater(err1, err2)

        gmca_core.gmca_numba(X,
                             n_sources,
                             200,
                             A,
                             S,
                             A_p,
                             lam_p,
                             lam_s=lam_s,
                             ret_min_rmse=False,
                             min_rmse_rate=2 * n_iterations,
                             enforce_nn_A=True,
                             seed=rseed)

        np.testing.assert_almost_equal(np.dot(A, S), X, decimal=4)

        # Test that lam_s enforces sparsity end_to_end
        lam_s = 10

        A = np.ones(A_org.shape)
        helpers.A_norm(A)
        S = np.ones(S_org.shape)

        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A,
                             S,
                             A_p,
                             lam_p,
                             lam_s=lam_s,
                             ret_min_rmse=False,
                             min_rmse_rate=2 * n_iterations,
                             enforce_nn_A=True,
                             seed=rseed)

        # Save closeness to prior for later test
        A_p_val = np.sum(np.abs(A - A_p))

        self.assertLess(np.sum(np.abs(S)), sparsity_1)
        # Test that lam_p enforcces prior end_to_end

        A = np.ones(A_org.shape)
        helpers.A_norm(A)
        S = np.ones(S_org.shape)
        lam_p = [1e8] * n_sources

        gmca_core.gmca_numba(X,
                             n_sources,
                             n_iterations,
                             A,
                             S,
                             A_p,
                             lam_p,
                             lam_s=lam_s,
                             ret_min_rmse=False,
                             min_rmse_rate=2 * n_iterations,
                             enforce_nn_A=True,
                             seed=rseed)

        self.assertLess(np.sum(np.abs(A - A_p)), A_p_val)

        # Finally, test data with nans does not impose constraining power
        # where there are nans.
        X_copy = np.copy(X)
        for i in range(n_freqs):
            X_copy[i, np.random.randint(0, X.shape[1], 10)] = np.nan
        A = np.ones(A_org.shape)
        helpers.A_norm(A)
        S = np.ones(S_org.shape)
        lam_p = [0.0] * n_sources
        lam_s = 1e-5
        gmca_core.gmca_numba(X_copy,
                             n_sources,
                             200,
                             A,
                             S,
                             A_p,
                             lam_p,
                             lam_s=lam_s,
                             ret_min_rmse=False,
                             min_rmse_rate=2 * n_iterations,
                             enforce_nn_A=True,
                             seed=rseed)
        self.assertEqual(np.sum(np.isnan(np.dot(A, S))), 0)
        self.assertLess(np.mean(np.abs(X - np.dot(A, S))) / s_mag, 0.1)
コード例 #7
0
def hgmca_epoch_numba(X_level,
                      A_hier_list,
                      lam_hier,
                      A_global,
                      lam_global,
                      S_level,
                      n_epochs,
                      m_level,
                      n_iterations,
                      lam_s,
                      seed,
                      enforce_nn_A,
                      min_rmse_rate,
                      epoch_start=0):
    """ Runs the epoch loop for a given level of hgmca using numba optimization.

	For an in depth description of the algorithm see arxiv 1910.08077

	Parameters:
		X_level (np.array): A numba.typed.List of numpy arrays corresponding to
		the data for each level of analysis.
		A_hier_list ([np.array]): A numba.typed.List of numpy arrays containing
			the mixing matrix hierarchy for each level of analysis.
		lam_hier (np.array): A n_sources long array of the prior for each of
			the columns of the mixing matrices in A_hier. This allows for a
			source dependent prior.
		A_global (np.array): A global mixing matrix prior that will be
			applied to all matrices in the hierarchy
		lam_global (np.array): A n_sources long array of the prior for each
			of the columns of the global prior.
		S_level ([np.array,...]):A numba.typed.List of numpy arrays containing
			the source matrices for each level of analysis.
		n_epochs (int): The number of times the algorithm should pass
			through all the levels.
		m_level (int): The maximum level of analysis.
		n_iterations (int): The number of iterations of coordinate descent
			to conduct per epoch.
		lam_s (float): The lambda parameter for the sparsity l1 norm.
		seed (int): An integer to seed the random number generator.
		enforce_nn_A (bool): A boolean that determines if the mixing matrix
			will be forced to only have non-negative values.
		min_rmse_rate (int): How often the source matrix will be set to the
			minimum rmse solution. 0 will never return min_rmse within the
			gmca optimization.
		epoch_start (int): What epoch the code is starting at. Important
			for min_rmse_rate.

	Notes:
		A_hier and S_level will be updated in place.
	"""
    # We allocate the arrays that gmca will use here to avoid them being
    # reallocated
    R_i_level = numba.typed.List()
    AS_level = numba.typed.List()
    A_R_level = numba.typed.List()
    A_i_level = numba.typed.List()
    for level in range(m_level + 1):
        R_i_level.append(np.zeros(X_level[level][0].shape))
        AS_level.append(np.zeros(X_level[level][0].shape))
        A_R_level.append(np.zeros((1, X_level[level].shape[2])))
        A_i_level.append(np.zeros((X_level[level].shape[1], 1)))
    # Set the random seed.
    np.random.seed(seed)
    # Now we iterate through our graphical model using our approximate closed
    # form solution for the desired number of epochs.
    for epoch in range(epoch_start, epoch_start + n_epochs):
        # We want to iterate through the levels in random order. This should
        # theoretically speed up convergence.
        level_perm = np.random.permutation(m_level + 1)
        for level in level_perm:
            npatches = wavelets_hgmca.level_to_npatches(level)
            for patch in range(npatches):
                # Calculate the mixing matrix prior and the number of matrices
                # used to construct that prior.
                A_prior = get_A_prior(A_hier_list, level, patch, lam_hier)
                A_prior += lam_global * A_global
                # First we deal with the relatively simple case where there are
                # no sources at this level
                if X_level[level].size == 0:
                    A_hier_list[level][patch] = A_prior
                    helpers.A_norm(A_hier_list[level][patch])
                # If there are sources at this level we must run GMCA
                else:
                    # Extract the data for the patch.
                    X_p = X_level[level][patch]
                    S_p = S_level[level][patch]
                    # For HGMCA we want to store the source signal that
                    # includes the lasso shooting subtraction of lam_s for
                    # stability of the loss function. Only in the last step do
                    # we want gmca to return the min_rmse solution.
                    if min_rmse_rate == 0:
                        ret_min_rmse = False
                    else:
                        ret_min_rmse = (((epoch + 1) % min_rmse_rate) == 0)

                    # Call gmca for the patch. Note the lam_p has already been
                    # accounted for.
                    n_sources = len(S_p)
                    gmca_core.gmca_numba(X_p,
                                         n_sources,
                                         n_iterations,
                                         A_hier_list[level][patch],
                                         S_p,
                                         A_p=A_prior,
                                         lam_p=np.ones(n_sources),
                                         enforce_nn_A=enforce_nn_A,
                                         lam_s=lam_s,
                                         ret_min_rmse=ret_min_rmse,
                                         R_i_init=R_i_level[level],
                                         AS_init=AS_level[level],
                                         A_R_init=A_R_level[level],
                                         A_i_init=A_i_level[level])