def test_patch_reconstruction_error(): rng = check_random_state(42) n_times_atoms, n_times = 21, 128 n_atoms = 3 n_trials, n_channels = 29, 7 n_times_valid = n_times - n_times_atoms + 1 density = 0.1 z = sparse.random(n_atoms * n_trials, n_times_valid, density, random_state=rng).toarray().reshape( (n_trials, n_atoms, n_times_valid)) uv = rng.randn(n_atoms, n_channels + n_times_atoms) X = construct_X_multi(z, D=uv, n_channels=n_channels) from alphacsc.utils.dictionary import _patch_reconstruction_error rec = _patch_reconstruction_error(X, z, uv) assert rec.shape == (n_trials, n_times_valid) assert_allclose(rec, 0) uv = rng.randn(n_atoms, n_channels + n_times_atoms) rec = _patch_reconstruction_error(X, z, uv) X_hat = construct_X_multi(z, D=uv, n_channels=n_channels) for i in range(10): for j in range(10): assert np.isclose( rec[i, j], np.sum((X_hat[i, :, j:j + n_times_atoms] - X[i, :, j:j + n_times_atoms])**2))
def get_signals(n_channels=50, n_times_atom=64, n_times_valid=640, sigma=.01, random_state=None): """Generate a signal following the sparse linear model with a rank1 triangle and square atoms and a Bernoulli-uniform distribution.""" n_atoms = 2 rng = np.random.RandomState(random_state) v0 = get_atoms('triangle', n_times_atom) # temporal atoms v1 = get_atoms('square', n_times_atom) u0 = get_atoms('sin', n_channels) # spatial maps u1 = get_atoms('cos', n_channels) u0[0] = u1[0] = 1 uv = np.array([np.r_[u0, v0], np.r_[u1, v1]]) uv = prox_uv(uv, 'separate', n_channels) # add atoms z = np.array([sparse.random(n_atoms, n_times_valid, density=.05, random_state=random_state).toarray() for _ in range(n_trials)]) z = np.swapaxes(z, 0, 1) X = construct_X_multi(z, uv, n_channels=n_channels) X = X + sigma * rng.randn(*X.shape) uv_init = rng.randn(n_atoms, n_channels + n_times_atom) uv_init = prox_uv(uv_init, uv_constraint='separate', n_channels=n_channels) return X, uv, uv_init
def test_get_cost(solver, X, D_hat, requires_dicodile): """Test for valid values.""" with get_z_encoder_for(solver=solver, X=X, D_hat=D_hat, n_atoms=N_ATOMS, n_times_atom=N_TIMES_ATOM, n_jobs=2) as z_encoder: initial_cost = z_encoder.get_cost() z_encoder.compute_z() z_hat = z_encoder.get_z_hat() final_cost = z_encoder.get_cost() assert final_cost < initial_cost X_hat = construct_X_multi(z_hat, D_hat, n_channels=N_CHANNELS) cost = compute_objective(X=X, X_hat=X_hat, z_hat=z_hat, reg=0.1, D=D_hat) assert np.isclose(cost, final_cost)
def test_construct_X(): rng = check_random_state(42) n_times_atoms, n_times = 21, 128 n_atoms = 3 n_trials, n_channels = 29, 7 n_times_valid = n_times - n_times_atoms + 1 density = 0.1 zi = sparse.random(n_atoms * n_trials, n_times_valid, density, random_state=rng).toarray().reshape( (n_trials, n_atoms, n_times_valid)) uv = rng.randn(n_atoms, n_channels + n_times_atoms) ds = get_D(uv, n_channels) X_uv = construct_X_multi(zi, D=uv, n_channels=n_channels) X_ds = construct_X_multi(zi, D=ds) assert_allclose(X_uv, X_ds, atol=1e-16)
def test_update_uv(solver_d, uv_constraint): # Generate synchronous D n_times_atom, n_times = 10, 100 n_channels = 5 n_atoms = 2 n_trials = 3 rng = np.random.RandomState() z = rng.normal(size=(n_trials, n_atoms, n_times - n_times_atom + 1)) uv0 = rng.normal(size=(n_atoms, n_channels + n_times_atom)) uv1 = rng.normal(size=(n_atoms, n_channels + n_times_atom)) uv0 = prox_uv(uv0) uv1 = prox_uv(uv1) X = construct_X_multi(z, D=uv0, n_channels=n_channels) def objective(uv): X_hat = construct_X_multi(z, D=uv, n_channels=n_channels) return compute_objective(X, X_hat, loss='l2') # Ensure that the known optimal point is stable uv = update_uv(X, z, uv0, max_iter=1000, verbose=0) cost = objective(uv) assert np.isclose(cost, 0), "optimal point not stable" assert np.allclose(uv, uv0), "optimal point not stable" # Ensure that the update is going down from a random initialization cost0 = objective(uv1) uv, pobj = update_uv(X, z, uv1, debug=True, max_iter=5000, verbose=10, solver_d=solver_d, momentum=False, eps=1e-10, uv_constraint=uv_constraint) cost1 = objective(uv) msg = "Learning is not going down" try: assert cost1 < cost0, msg # assert np.isclose(cost1, 0, atol=1e-7) except AssertionError: import matplotlib.pyplot as plt pobj = np.array(pobj) plt.semilogy(pobj) plt.title(msg) plt.show() raise
D_hat = res._D_hat fig = display_dictionaries(D_init, D_hat) ############################################################################### # # Signal reconstruction ############################################################################### # Now, let's reconstruct the original signal. from alphacsc.utils import construct_X_multi z_hat = res._z_hat X_hat = construct_X_multi(z_hat, D_hat) ############################################################################### # Plot a small part of the original and reconstructed signals fig_hat, ax_hat = plt.subplots() ax_hat.plot(X[0][0][5000:5800], label='right foot vertical acceleration (ORIGINAL)') ax_hat.plot(X_hat[0][0][5000:5800], label='right foot vertical acceleration (RECONSTRUCTED)') ax_hat.set_xlabel('time (x10ms)') ax_hat.set_ylabel('acceleration ($m.s^{-2}$)') ax_hat.legend() ############################################################################### # Check that our representation is indeed sparse:
def func(d0): D0 = d0.reshape(n_atoms, n_channels, n_times_atom) X_hat = construct_X_multi(z, D=D0) return compute_objective(X, X_hat, loss=loss, loss_params=loss_params)
def objective(uv): X_hat = construct_X_multi(z, D=uv, n_channels=n_channels) res = X - X_hat return .5 * np.sum(res * res)
def objective(uv): X_hat = construct_X_multi(z, D=uv, n_channels=n_channels) return compute_objective(X, X_hat, loss='l2')
def func(uv0): uv0 = uv0.reshape(n_atoms, n_channels + n_times_atom) X_hat = construct_X_multi(z, D=uv0, n_channels=n_channels) return compute_objective(X, X_hat, loss=loss, loss_params=loss_params)
def test_cd(): n_trials, n_channels, n_times = 5, 3, 100 n_times_atom, n_atoms = 10, 4 n_times_valid = n_times - n_times_atom + 1 reg = 1 rng = np.random.RandomState(0) uv = rng.randn(n_atoms, n_channels + n_times_atom) z = abs(rng.randn(n_trials, n_atoms, n_times_valid)) z_gen = abs(rng.randn(n_trials, n_atoms, n_times_valid)) z[z < 1] = 0 z_gen[z_gen < 1] = 0 z0 = z[0] X = construct_X_multi(z_gen, D=uv, n_channels=n_channels) loss_0 = compute_X_and_objective_multi(X=X, z_hat=z_gen, D_hat=uv, reg=reg, loss='l2', feasible_evaluation=False) constants = {} constants['DtD'] = compute_DtD(uv, n_channels) # Ensure that the initialization is good, by using a nearly optimal point # and verifying that the cost does not goes up. z_hat, ztz, ztX = update_z_multi(X, D=uv, reg=reg, z0=z_gen, solver="lgcd", solver_kwargs={ 'max_iter': 5, 'tol': 1e-5 }, return_ztz=True) assert np.allclose(ztz, compute_ztz(z_hat, n_times_atom)) assert np.allclose(ztX, compute_ztX(z_hat, X)) loss_1 = compute_X_and_objective_multi(X=X, z_hat=z_hat, D_hat=uv, reg=reg, loss='l2', feasible_evaluation=False) assert loss_1 <= loss_0, "Bad initialization in greedy CD." z_hat, pobj, times = _coordinate_descent_idx(X[0], uv, constants, reg, debug=True, timing=True, z0=z0, max_iter=10000) try: assert all([p1 >= p2 for p1, p2 in zip(pobj[:-1], pobj[1:])]), "oups" except AssertionError: import matplotlib.pyplot as plt plt.plot(pobj) plt.show() raise
def _construct_X(X, z, D, loss, loss_params): return construct_X_multi(z, D, n_channels=X.shape[1])
def test_cd(use_sparse_lil): n_trials, n_channels, n_times = 5, 3, 100 n_times_atom, n_atoms = 10, 4 n_times_valid = n_times - n_times_atom + 1 reg = 1 uv = np.random.randn(n_atoms, n_channels + n_times_atom) if use_sparse_lil: density = .1 z = [ sparse.random(n_atoms, n_times_valid, format='lil', density=density) for _ in range(n_trials) ] z_gen = [ sparse.random(n_atoms, n_times_valid, format='lil', density=density) for _ in range(n_trials) ] z0 = z[0] else: z = abs(np.random.randn(n_trials, n_atoms, n_times_valid)) z_gen = abs(np.random.randn(n_trials, n_atoms, n_times_valid)) z[z < 1] = 0 z_gen[z_gen < 1] = 0 z0 = z[0] X = construct_X_multi(z_gen, D=uv, n_channels=n_channels) loss_0 = compute_X_and_objective_multi(X=X, z_hat=z_gen, D_hat=uv, reg=reg, loss='l2', feasible_evaluation=False) constants = {} constants['DtD'] = compute_DtD(uv, n_channels) # Ensure that the initialization is good, by using a nearly optimal point # and verifying that the cost does not goes up. z_hat, ztz, ztX = update_z_multi(X, D=uv, reg=reg, z0=z_gen, solver="lgcd", solver_kwargs={ 'max_iter': 5, 'tol': 1e-5 }) if use_sparse_lil and cython_code._CYTHON_AVAILABLE: from alphacsc.cython_code import _fast_compute_ztz, _fast_compute_ztX assert np.allclose(ztz, _fast_compute_ztz(z_hat, n_times_atom)) assert np.allclose(ztX, _fast_compute_ztX(z_hat, X)) else: assert np.allclose(ztz, compute_ztz(z_hat, n_times_atom)) assert np.allclose(ztX, compute_ztX(z_hat, X)) loss_1 = compute_X_and_objective_multi(X=X, z_hat=z_hat, D_hat=uv, reg=reg, loss='l2', feasible_evaluation=False) assert loss_1 <= loss_0, "Bad initialization in greedy CD." z_hat, pobj, times = _coordinate_descent_idx(X[0], uv, constants, reg, debug=True, timing=True, z0=z0, max_iter=10000) try: assert all([p1 >= p2 for p1, p2 in zip(pobj[:-1], pobj[1:])]), "oups" except AssertionError: import matplotlib.pyplot as plt plt.plot(pobj) plt.show() raise