def test_lipschitz_est(seed): """ Test the estimation of the Lipschitz. """ rng = check_random_state(seed) # test the identity case def AtA(x): return x shape = (10, ) L = lipschitz_est(AtA, shape) assert 1.0 == pytest.approx(L) # test by the definition of the Lipschitz constant A = rng.randn(10, 10) AtA_ = A.T.dot(A) def AtA(x): return AtA_.dot(x) L = lipschitz_est(AtA, shape) for _ in range(100): x, y = rng.randn(10), rng.randn(10) a = np.linalg.norm(AtA(x) - AtA(y)) b = np.linalg.norm(x - y) assert a <= L * b
def test_estim_v_scaled_hrf(seed): """ Test the estimation of the HRF with the scaled HRF model without noise in the observed data. """ rng = check_random_state(seed) eps = 1.0e-3 t_r = 1.0 n_atoms = 2 n_times_valid = 500 n_times_atom = 60 n_voxels_in_rois = 200 n_hrf_rois = 5 n_voxels = n_voxels_in_rois * n_hrf_rois indices = np.arange(n_voxels) rois_s = np.split(indices, n_hrf_rois) hrf_rois = dict(zip(range(1, n_hrf_rois + 1), rois_s)) u = rng.randn(n_atoms, n_voxels) z = rng.randn(n_atoms, n_times_valid) rois_idx, _, _ = split_atlas(hrf_rois) a_true = rng.uniform(MIN_DELTA + eps, MAX_DELTA - eps, n_hrf_rois) v_true = np.c_[[scaled_hrf(a_, t_r, n_times_atom) for a_ in a_true]] X = construct_X_hat_from_v(v_true, z, u, rois_idx) a_init = rng.uniform(MIN_DELTA + eps, MAX_DELTA - eps, n_hrf_rois) a_hat, v_hat = _estim_v_scaled_hrf(a_init, X, z, u, rois_idx, t_r, n_times_atom) # no garantie of recovery in any case... np.testing.assert_allclose(a_true, a_hat, atol=1e-1) np.testing.assert_allclose(v_true, v_hat, atol=1e-1)
def test_estim_v_3_basis(seed): """ Test the estimation of the HRF with the scaled HRF model without noise in the observed data. """ rng = check_random_state(seed) t_r = 1.0 n_atoms = 2 n_voxels = 1000 n_times_valid = 100 n_times_atom = 30 indices = np.arange(n_voxels) n_hrf_rois = 2 rois_1 = indices[int(n_voxels / 2):] rois_2 = indices[:int(n_voxels / 2)] hrf_rois = {1: rois_1, 2: rois_2} u = rng.randn(n_atoms, n_voxels) z = rng.randn(n_atoms, n_times_valid) rois_idx, _, _ = split_atlas(hrf_rois) h = hrf_3_basis(t_r, n_times_atom) a_true = np.c_[[[1.0, 0.8, 0.5], [1.0, 0.5, 0.0]]] v_true = np.c_[[a_.dot(h) for a_ in a_true]] X = construct_X_hat_from_v(v_true, z, u, rois_idx) a_init = np.c_[[np.array([1.0, 0.0, 0.0]) for _ in range(n_hrf_rois)]] a_hat, v_hat = _estim_v_d_basis(a_init, X, h, z, u, rois_idx) # no garantie of recovery in any case... np.testing.assert_allclose(a_true, a_hat, atol=1e-1) np.testing.assert_allclose(v_true, v_hat, atol=1e-1)
def test_proximal_descent(seed, momentum, restarting): """ Test the proximal descent algo. """ rng = check_random_state(seed) m = 100 x0 = rng.randn(m) y = rng.randn(int(m/2)) A = rng.randn(int(m/2), m) AtA = A.T.dot(A) def obj(x): res = (A.dot(x) - y).ravel() return 0.5 * res.dot(res) def grad(x): return A.T.dot(A.dot(x) - y) def prox(x, step_size): return x def AtA(x): return A.T.dot(A).dot(x) step_size = 0.9 / lipschitz_est(AtA, x0.shape) params = dict(x0=x0, grad=grad, prox=prox, step_size=step_size, momentum='fista', restarting='descent', max_iter=1000, obj=obj, benchmark=True) x_hat, pobj, _ = proximal_descent(**params) assert pobj[0] > pobj[-1] if momentum is None: assert np.all(np.diff(pobj) < np.finfo(np.float64).eps)
def test_v_loss(seed): """ Test the loss function. """ rng = check_random_state(seed) kwargs = _set_up_test(seed) X, u, z = kwargs['X'], kwargs['u'], kwargs['z'] t_r, n_times_atom = kwargs['t_r'], kwargs['n_times_atom'] uz = u.T.dot(z) eps = 1.0e-6 a = rng.uniform(MIN_DELTA + eps, MAX_DELTA - eps, 1) def loss_ref(a): n_atoms, _ = z.shape v = scaled_hrf(a, t_r, n_times_atom) X_hat = np.zeros_like(X) for k in range(n_atoms): X_hat += np.outer(u[k, :], np.convolve(v, z[k, :])) residual = (X_hat - X).ravel() return 0.5 * residual.dot(residual) loss_ref_ = loss_ref(a) sum_ztz, sum_ztz_y = _precompute_sum_ztz_sum_ztz_y(uz, X, n_times_atom, factor=2.0) loss_test_ = _loss_v(a, u, z, X, t_r, n_times_atom, sum_ztz, sum_ztz_y) np.testing.assert_allclose(loss_ref_, loss_test_)
def test_grad_v_scaled_hrf(seed): """ Test the gradient of v (model: scaled hrf). """ rng = check_random_state(seed) kwargs = _set_up_test(seed) t_r, n_times_atom = kwargs['t_r'], kwargs['n_times_atom'] X, u, z = kwargs['X'], kwargs['u'], kwargs['z'] uz = u.T.dot(z) epsilon = 1.0e-6 a = rng.uniform(MIN_DELTA + epsilon, MAX_DELTA - epsilon, 1) # Finite grad v def finite_grad_v(a): def f(a): return _loss_v(a, u, z, X, t_r, n_times_atom) return (f(a + epsilon) - f(a)) / epsilon grad_ref = finite_grad_v(a) # Closed form grad v sum_ztz, sum_ztz_y = _precompute_sum_ztz_sum_ztz_y(uz, X, n_times_atom, factor=1.0) grad_ = _grad_v_scaled_hrf(a, t_r, n_times_atom, sum_ztz, sum_ztz_y) np.testing.assert_allclose(grad_ref, grad_, rtol=1e-2)
def test_toeplitz(seed): """ Test the the making of the Toeplitz function. """ rng = check_random_state(seed) n_times_atom, n_times_valid = 30, 100 z = rng.randn(n_times_valid) v = rng.randn(n_times_atom) H = make_toeplitz(v, n_times_valid) np.testing.assert_allclose(np.convolve(v, z), H.dot(z))
def test_delta_derivative_double_gamma_hrf(seed): t_r = 1.0 rng = check_random_state(seed) eps = 1.0e-6 delta = rng.uniform(MIN_DELTA, MAX_DELTA) grad = delta_derivative_double_gamma_hrf(delta, t_r) finite_grad = scaled_hrf(delta + eps, t_r) - scaled_hrf(delta, t_r) finite_grad /= eps np.testing.assert_allclose(finite_grad, grad, atol=1.0e-3)
def test_add_gaussian_noise(seed, snr): """ Check the production of a synthtique noisy signa at a given SNR. """ rng = check_random_state(seed) signal = rng.randn(500) noisy_signal, noise = add_gaussian_noise(signal, snr, random_state=rng) l2_signal = np.sum(np.square(signal)) l2_noise = np.sum(np.square(noise)) true_snr = 10.0 * np.log10((l2_signal / l2_noise)) assert np.abs(snr - true_snr) < 1.0e-5
def test_check_random_state(): """ Test the check random state. """ rng = check_random_state(None) assert isinstance(rng, np.random.RandomState) rng = check_random_state(np.random) assert isinstance(rng, np.random.RandomState) rng = check_random_state(3) assert isinstance(rng, np.random.RandomState) rng = check_random_state(check_random_state(None)) assert isinstance(rng, np.random.RandomState) with pytest.raises(ValueError): check_random_state('foo')
def test_prox_l1_simplex(seed): """ Test the positive L1 simplex proximal operator. """ rng = check_random_state(seed) kwargs = _set_up_test(seed) u = kwargs['u'] u_0 = u[0, :] prox_u_0 = _prox_l1_simplex(u_0, 10.0) assert np.all(prox_u_0 >= 0.0) np.testing.assert_allclose(np.sum(np.abs(prox_u_0)), 10.0) n_try = 100 for _ in range(n_try): x = rng.randn(*u_0.shape) x[x < 0.0] = 0.0 norm_x = np.sum(np.abs(x)) if not (norm_x != 10.0): x /= norm_x assert np.linalg.norm(u_0 - prox_u_0) < np.linalg.norm(u_0 - x)
def test_prox_positive_L2_ball(seed): """ Test the positive L2 ball proximal operator. """ rng = check_random_state(seed) kwargs = _set_up_test(seed) u = kwargs['u'] u_0 = u[0, :] prox_u_0 = _prox_positive_l2_ball(u_0, 1.0) assert np.all(prox_u_0 >= 0.0) assert np.linalg.norm(prox_u_0) <= 1.0 n_try = 100 for _ in range(n_try): x = rng.randn(*u_0.shape) x[x < 0.0] = 0.0 norm_x = x.ravel().dot(x.ravel()) if not (norm_x <= 1.0): x /= norm_x assert np.linalg.norm(u_0 - prox_u_0) < np.linalg.norm(u_0 - x)