def test_compute_kle_gradient_from_mesh_gradient(self): nvars, sigma = 2, 3 length_scale = 1 mesh = np.linspace(0., 1., 11)[None, :] kle_mean = mesh[0, :] + 2 for use_log in [False, True]: kle = MeshKLE(mesh, kle_mean, use_log) kle.compute_basis(length_scale, sigma, nvars) def scalar_function_of_field(field): return np.dot(field[:, 0], field[:, 0]) sample = np.random.normal(0., 1., (nvars, 1)) kle_vals = kle(sample) from pyapprox.optimization import approx_jacobian mesh_gradient = kle_vals.T * 2 assert np.allclose(mesh_gradient, approx_jacobian(scalar_function_of_field, kle_vals), atol=1e-7) gradient = compute_kle_gradient_from_mesh_gradient( mesh_gradient, kle.eig_vecs, kle.mean_field, kle.use_log, sample[:, 0]) def scalar_function_of_sample(sample): field = kle(sample) return scalar_function_of_field(field) fd_gradient = approx_jacobian(scalar_function_of_sample, sample) # print((fd_gradient, gradient)) assert np.allclose(fd_gradient, gradient)
def test_1_layer_gradient_wrt_inputs(self): nqoi, nvars = 2, 3 A = np.random.normal(0, 1, (nqoi, nvars)) b = np.random.normal(0, 1, (nqoi, 1)) def fun(x): return sigmoid_function(A.dot(x) + b) def jac(x): return sigmoid_gradient(A.dot(x) + b) * A # return np.diag(sigmoid_gradient(A.dot(x)+b)[:, 0]).dot(A) x0 = np.random.normal(0, 1, (nvars, 1)) assert np.allclose(approx_jacobian(fun, x0), jac(x0)) def g(x): return sigmoid_function(x)[:, None] assert np.allclose( _approx_fprimeprime(x0[:, 0], g, 1e-4)[:, 0, :], approx_jacobian(sigmoid_gradient, x0[:, 0])) assert np.allclose( np.diag(approx_jacobian(sigmoid_gradient, x0[:, 0])), sigmoid_second_derivative(x0)[:, 0]) def f(x): x = x[:, None] return fun(x) def hess(x): return sigmoid_second_derivative(A.dot(x) + b) * A**2 assert np.allclose(hess(x0), _approx_fprimeprime(x0[:, 0], f, 1e-4)[:, 0, :])
def test_pce_jacobian(self): degree = 2 alpha_stat, beta_stat = 2, 3 univariate_variables = [beta(alpha_stat, beta_stat, 0, 1), norm(-1, 2)] variable = IndependentMultivariateRandomVariable(univariate_variables) var_trans = AffineRandomVariableTransformation(variable) num_vars = len(univariate_variables) poly = PolynomialChaosExpansion() poly_opts = define_poly_options_from_variable_transformation(var_trans) poly.configure(poly_opts) indices = compute_hyperbolic_indices(num_vars, degree, 1.0) poly.set_indices(indices) sample = generate_independent_random_samples(variable, 1) coef = np.ones((indices.shape[1], 2)) coef[:, 1] *= 2 poly.set_coefficients(coef) jac = poly.jacobian(sample) from pyapprox.optimization import approx_jacobian fd_jac = approx_jacobian(lambda x: poly(x[:, np.newaxis])[0, :], sample[:, 0]) assert np.allclose(jac, fd_jac)
def test_emax_model(self): from pyapprox.optimization import approx_jacobian theta = np.ones(3)*0.5 samples = np.random.uniform(1,2,(1,2)) fd_jac = approx_jacobian(emax_model,theta,samples) jac = emax_model_grad_parameters(theta,samples) assert np.allclose(jac.T,fd_jac)
def test_michaelis_menten_model(self): from pyapprox.optimization import approx_jacobian theta = np.ones(2)*0.5 samples = np.random.uniform(1,2,(1,3)) fd_jac = approx_jacobian(michaelis_menten_model,theta,samples) jac = michaelis_menten_model_grad_parameters(theta,samples) assert np.allclose(jac.T,fd_jac)
def test_smooth_l1_norm_gradients(self): #x = np.linspace(-1,1,101) #t = np.ones_like(x) #r = 1e1 #plt.plot(x,kouri_smooth_absolute_value(t,r,x)) #plt.show() t = np.ones(5);r=1 init_guess = np.random.normal(0,1,(t.shape[0])) func = partial(kouri_smooth_l1_norm,t,r) jac = partial(kouri_smooth_l1_norm_gradient,t,r) errors = check_gradients(func,jac,init_guess,disp=False) assert errors.min()<3e-7 fd_hess = approx_jacobian(jac,init_guess) assert np.allclose(fd_hess,kouri_smooth_l1_norm_hessian(t,r,init_guess))
def test_nonlinear_basis_pursuit(self): np.random.seed(1) nsamples, degree, sparsity = 7, 7, 2 samples = np.random.uniform(0, 1, (1, nsamples)) basis_matrix = samples.T**np.arange(degree + 1)[np.newaxis, :] def model(x): val = basis_matrix.dot(x[:-1]) * np.exp(samples[0, :] * x[-1]) grad = np.hstack([ basis_matrix * np.exp(samples[0, :] * x[-1])[:, np.newaxis], (samples[0, :] * val)[:, np.newaxis] ]) return val, grad true_coef = np.zeros(basis_matrix.shape[1] + 1) true_coef[np.random.permutation(true_coef.shape[0] - 1)[:sparsity - 1]] = 1. true_coef[-1] = 1 vals = model(true_coef)[0] def func(x): model_vals, grad = model(x) return model_vals - vals, grad jac = True hess = None init_guess = true_coef + np.random.normal(0, 1, true_coef.shape[0]) fd_jac = approx_jacobian(lambda x: model(x)[0], init_guess, epsilon=1e-7) analytical_jac = model(init_guess)[1] #print(analytical_jac-fd_jac) assert np.allclose(analytical_jac, fd_jac, atol=1e-8) tol = 1e-12 options = { 'ftol': tol, 'verbose': 2, 'disp': True, 'xtol': tol, 'maxiter': 1000 } init_guess = true_coef + np.random.normal(0, 1, true_coef.shape[0]) l1_coef = nonlinear_basis_pursuit(func, jac, hess, init_guess, options) print(np.linalg.norm(true_coef - l1_coef)) assert np.allclose(l1_coef, true_coef, atol=2e-6)
def test_conditional_value_at_risk_gradient(self): N = 6 p = np.ones(N) / N X = np.random.normal(0, 1, N) #X = np.arange(1,N+1) X = np.sort(X) beta = 7 / 12 beta = 2 / 3 i_beta_exact = 3 VaR_exact = X[i_beta_exact] cvar_exact = 1 / 5 * VaR_exact + 2 / 5 * (np.sort(X)[i_beta_exact + 1:]).sum() cvar_grad = conditional_value_at_risk_gradient(X, beta) from pyapprox.optimization import approx_jacobian func = partial(conditional_value_at_risk, alpha=beta) cvar_grad_fd = approx_jacobian(func, X) assert np.allclose(cvar_grad, cvar_grad_fd, atol=1e-7)
def test_smooth_l1_norm_gradients(self): #x = np.linspace(-1,1,101) #t = np.ones_like(x) #r = 1e1 #plt.plot(x,kouri_smooth_absolute_value(t,r,x)) #plt.show() from pyapprox.optimization import \ ScipyMinimizeObjectiveAsPyapproxFunction,\ ScipyMinimizeObjectiveJacAsPyapproxJac t = np.ones(5) r = 1 init_guess = np.random.normal(0, 1, (t.shape[0], 1)) func = ScipyMinimizeObjectiveAsPyapproxFunction( partial(kouri_smooth_l1_norm, t, r)) jac = partial(kouri_smooth_l1_norm_gradient, t, r) pya_jac = ScipyMinimizeObjectiveJacAsPyapproxJac(jac) errors = check_gradients(func, pya_jac, init_guess, disp=False) assert errors.min() < 3e-7 fd_hess = approx_jacobian(jac, init_guess[:, 0]) assert np.allclose(fd_hess, kouri_smooth_l1_norm_hessian(t, r, init_guess))
def test_advection_diffusion_base_class_adjoint(self): nvars, corr_len = 2, 0.1 benchmark = setup_advection_diffusion_benchmark(nvars=nvars, corr_len=corr_len, max_eval_concurrency=1) model = benchmark.fun #random_samples = np.zeros((nvars,1)) random_samples = -np.sqrt(3) * np.ones((nvars, 1)) config_samples = 3 * np.ones((3, 1)) samples = np.vstack([random_samples, config_samples]) bmodel = model.base_model qoi = bmodel(samples) assert np.all(np.isfinite(qoi)) sol = bmodel.solve(samples) grad = qoi_functional_grad_misc(sol, bmodel) kappa = bmodel.kappa J = dl_qoi_functional_misc(sol) control = dla.Control(kappa) Jhat = dla.ReducedFunctional(J, control) h = dla.Function(kappa.function_space()) h.vector()[:] = np.random.normal(0, 1, kappa.function_space().dim()) conv_rate = dla.taylor_test(Jhat, kappa, h) assert np.allclose(conv_rate, 2.0, atol=1e-3) # Check that gradient with respect to kappa is calculated correctly # this requires passing in entire kappa vector and not just variables # used to compute the KLE. from pyapprox.optimization import check_gradients from pyapprox.models.wrappers import SingleFidelityWrapper from functools import partial init_condition, boundary_conditions, function_space, beta, \ forcing, kappa = bmodel.initialize_random_expressions( random_samples[:, 0]) def fun(np_kappa): dt = 0.1 fn_kappa = dla.Function(function_space) fn_kappa.vector()[:] = np_kappa[:, 0] bmodel.kappa = fn_kappa sol = run_model( function_space, fn_kappa, forcing, init_condition, dt, bmodel.final_time, boundary_conditions, velocity=beta, second_order_timestepping=bmodel.second_order_timestepping, intermediate_times=bmodel.options.get('intermediate_times', None)) vals = np.atleast_1d(bmodel.qoi_functional(sol)) if vals.ndim == 1: vals = vals[:, np.newaxis] grad = bmodel.qoi_functional_grad(sol, bmodel) return vals, grad kappa = bmodel.get_diffusivity(random_samples[:, 0]) x0 = dla.project(kappa, function_space).vector()[:].copy()[:, None] check_gradients(fun, True, x0) # Test that gradient with respect to kle coefficients is correct from pyapprox.karhunen_loeve_expansion import \ compute_kle_gradient_from_mesh_gradient vals, jac = bmodel(samples, jac=True) # Extract mean field and KLE basis from expression # TODO add ability to compute gradient of kle to # nobile_diffusivity_fenics_class kle = bmodel.get_diffusivity(np.zeros(random_samples.shape[0])) mean_field_fn = dla.Function(function_space) mean_field_fn = dla.interpolate(kle, function_space) mean_field = mean_field_fn.vector()[:].copy() - np.exp(1) mesh_coords = function_space.tabulate_dof_coordinates()[:, 0] I = np.argsort(mesh_coords) basis_matrix = np.empty((mean_field.shape[0], random_samples.shape[0])) exact_basis_matrix = np.array([ mesh_coords * 0 + 1, np.sin((2) / 2 * np.pi * mesh_coords / bmodel.options['corr_len']) ]).T for ii in range(random_samples.shape[0]): zz = np.zeros(random_samples.shape[0]) zz[ii] = 1.0 kle = bmodel.get_diffusivity(zz) field_fn = dla.Function(function_space) field_fn = dla.interpolate(kle, function_space) # 1e-15 used to avoid taking log of zero basis_matrix[:, ii] = np.log(field_fn.vector()[:].copy() - mean_field + 1e-15) - 1 assert np.allclose( mean_field + np.exp(1 + basis_matrix.dot(random_samples[:, 0])), x0[:, 0]) # nobile diffusivity uses different definitions of KLE # k = np.exp(1+basis_matrix.dot(coef))+mean_field # than that assumed in compute_kle_gradient_from_mesh_gradient # k = np.exp(basis_matrix.dot(coef)+mean_field) # So to # keep current interface set mean field to zero and then correct # returned gradient grad = compute_kle_gradient_from_mesh_gradient(jac, basis_matrix, mean_field * 0, True, random_samples[:, 0]) grad *= np.exp(1) from pyapprox.optimization import approx_jacobian fun = SingleFidelityWrapper(bmodel, config_samples[:, 0]) fd_grad = approx_jacobian(fun, random_samples) # print(grad, fd_grad) assert np.allclose(grad, fd_grad)
def help_test_stochastic_dominance_gradients(self, sd_opt_problem): np.random.seed(1) xx = sd_opt_problem.init_guess if hasattr(sd_opt_problem, "eps"): # smoothers often only have nonzero derivative is a region or # diameter epsilon xx[0] -= sd_opt_problem.eps / 3 from pyapprox.optimization import approx_jacobian fd_jacobian = approx_jacobian(sd_opt_problem.objective, xx, epsilon=1e-8) jacobian = sd_opt_problem.objective_jacobian(xx) #check_gradients( # sd_opt_problem.objective,sd_opt_problem.objective_jacobian,xx,False) #print('jac ex',fd_jacobian) #print('jac fd',jacobian) assert np.allclose(fd_jacobian, jacobian, atol=1e-7) fd_jacobian = approx_jacobian(sd_opt_problem.nonlinear_constraints, xx) jacobian = sd_opt_problem.nonlinear_constraints_jacobian(xx) if hasattr(jacobian, 'todense'): jacobian = jacobian.todense() #print('jac ex',fd_jacobian) #print('jac fd',jacobian) msg = 'change x, current value is not an effective test' #check_gradients( # sd_opt_problem.nonlinear_constraints, # sd_opt_problem.nonlinear_constraints_jacobian,xx,False) assert not np.all(np.absolute(jacobian) < 1e-15), msg assert np.allclose(fd_jacobian, jacobian, atol=1e-7) if hasattr(sd_opt_problem, 'objective_hessian'): hessian = sd_opt_problem.objective_hessian(xx) fd_hessian = approx_jacobian(sd_opt_problem.objective_jacobian, xx) if hasattr(hessian, 'todense'): hessian = hessian.todense() assert np.allclose(hessian, fd_hessian) if hasattr(sd_opt_problem, 'define_nonlinear_constraint_hessian'): at_least_one_hessian_nonzero = False for ii in range(sd_opt_problem.nnl_constraints): def grad(xx): row = sd_opt_problem.nonlinear_constraints_jacobian(xx)[ ii, :] if hasattr(row, 'todense'): row = np.asarray(row.todense())[0, :] return row fd_hessian = approx_jacobian(grad, xx) hessian = sd_opt_problem.define_nonlinear_constraint_hessian( xx, ii) #np.set_printoptions(linewidth=1000) #print('h',hessian) #print('h_fd',fd_hessian) if hessian is None: assert np.allclose(fd_hessian, np.zeros_like(fd_hessian), atol=1e-7) else: if hasattr(hessian, 'todense'): hessian = hessian.todense() assert np.allclose(hessian, fd_hessian, atol=1e-7, rtol=1e-1) if not at_least_one_hessian_nonzero: at_least_one_hessian_nonzero = np.any( np.absolute(hessian) < 1e-15) at_least_one_hessian_nonzero = True if not at_least_one_hessian_nonzero: msg = 'change x, current value is not an effective test' assert False, msg return sd_opt_problem