Ejemplo n.º 1
0
def modelVerify(model, a0, innerTol, is_quadratic=False):
    """
    Verify the reduced Gradient and the Hessian of a model.
    It will produce two loglog plots of the finite difference checks
    for the gradient and for the Hessian.
    It will also check for symmetry of the Hessian.
    """

    h = model.generate_vector(PARAMETER)
    h.set_local(np.random.normal(0, 1, len(h.array())))

    x = model.generate_vector()
    x[PARAMETER] = a0
    model.solveFwd(x[STATE], x, innerTol)
    model.solveAdj(x[ADJOINT], x, innerTol)
    cx = model.cost(x)

    grad_x = model.generate_vector(PARAMETER)
    model.evalGradientParameter(x, grad_x)
    grad_xh = grad_x.inner(h)

    model.setPointForHessianEvaluations(x)
    H = ReducedHessian(model, innerTol)
    Hh = model.generate_vector(PARAMETER)
    H.mult(h, Hh)

    n_eps = 32
    eps = np.power(.5, np.arange(n_eps))
    err_grad = np.zeros(n_eps)
    err_H = np.zeros(n_eps)

    for i in range(n_eps):
        my_eps = eps[i]

        x_plus = model.generate_vector()
        x_plus[PARAMETER].set_local(a0.array())
        x_plus[PARAMETER].axpy(my_eps, h)
        model.solveFwd(x_plus[STATE], x_plus, innerTol)
        model.solveAdj(x_plus[ADJOINT], x_plus, innerTol)

        dc = model.cost(x_plus)[0] - cx[0]
        err_grad[i] = abs(dc / my_eps - grad_xh)

        #Check the Hessian
        grad_xplus = model.generate_vector(PARAMETER)
        model.evalGradientParameter(x_plus, grad_xplus)

        err = grad_xplus - grad_x
        err *= 1. / my_eps
        err -= Hh

        err_H[i] = err.norm('linf')

    if is_quadratic:
        plt.figure()
        plt.subplot(121)
        plt.loglog(eps, err_grad, "-ob", eps, eps * (err_grad[0] / eps[0]),
                   "-.k")
        plt.title("FD Gradient Check")
        plt.subplot(122)
        plt.loglog(eps[0], err_H[0], "-ob",
                   [10 * eps[0], eps[0], 0.1 * eps[0]],
                   [err_H[0], err_H[0], err_H[0]], "-.k")
        plt.title("FD Hessian Check")
    else:
        plt.figure()
        plt.subplot(121)
        plt.loglog(eps, err_grad, "-ob", eps, eps * (err_grad[0] / eps[0]),
                   "-.k")
        plt.title("FD Gradient Check")
        plt.subplot(122)
        plt.loglog(eps, err_H, "-ob", eps, eps * (err_H[0] / eps[0]), "-.k")
        plt.title("FD Hessian Check")

    xx = model.generate_vector(PARAMETER)
    xx.set_local(np.random.normal(0, 1, len(xx.array())))
    yy = model.generate_vector(PARAMETER)
    yy.set_local(np.random.normal(0, 1, len(yy.array())))

    ytHx = H.inner(yy, xx)
    xtHy = H.inner(xx, yy)
    rel_symm_error = 2 * abs(ytHx - xtHy) / (ytHx + xtHy)
    print "(yy, H xx) - (xx, H yy) = ", rel_symm_error
    if (rel_symm_error > 1e-10):
        print "HESSIAN IS NOT SYMMETRIC!!"
Ejemplo n.º 2
0
    def solve(self, a0):
        """
        Solve the constrained optimization problem with initial guess a0.
        Return the solution [u,a,p] 
        """
        rel_tol = self.parameters["rel_tolerance"]
        abs_tol = self.parameters["abs_tolerance"]
        max_iter = self.parameters["max_iter"]
        innerTol = self.parameters["inner_rel_tolerance"]
        c_armijo = self.parameters["c_armijo"]
        max_backtracking_iter = self.parameters["max_backtracking_iter"]
        print_level = self.parameters["print_level"]
        GN_iter = self.parameters["GN_iter"]
        cg_coarse_tolerance = self.parameters["cg_coarse_tolerance"]

        [u, a, p] = self.model.generate_vector()
        self.model.solveFwd(u, [u, a0, p], innerTol)

        self.it = 0
        self.converged = False
        self.ncalls += 1

        ahat = self.model.generate_vector(PARAMETER)
        mg = self.model.generate_vector(PARAMETER)

        cost_old, _, _ = self.model.cost([u, a0, p])

        while (self.it < max_iter) and (self.converged == False):
            self.model.solveAdj(p, [u, a0, p], innerTol)

            self.model.setPointForHessianEvaluations([u, a0, p])
            gradnorm = self.model.evalGradientParameter([u, a0, p], mg)

            if self.it == 0:
                gradnorm_ini = gradnorm
                tol = max(abs_tol, gradnorm_ini * rel_tol)

            # check if solution is reached
            if (gradnorm < tol) and (self.it > 0):
                self.converged = True
                self.reason = 1
                break

            self.it += 1

            tolcg = min(cg_coarse_tolerance,
                        math.sqrt(gradnorm / gradnorm_ini))

            HessApply = ReducedHessian(self.model, innerTol, self.it < GN_iter)
            solver = CGSolverSteihaug()
            solver.set_operator(HessApply)
            solver.set_preconditioner(self.model.Rsolver())
            solver.parameters["rel_tolerance"] = tolcg
            solver.parameters["zero_initial_guess"] = True
            solver.parameters["print_level"] = print_level - 1

            solver.solve(ahat, -mg)
            self.total_cg_iter += HessApply.ncalls

            alpha = 1.0
            descent = 0
            n_backtrack = 0

            mg_ahat = mg.inner(ahat)

            while descent == 0 and n_backtrack < max_backtracking_iter:
                # update a and u
                a.zero()
                a.axpy(1., a0)
                a.axpy(alpha, ahat)
                self.model.solveFwd(u, [u, a, p], innerTol)

                cost_new, reg_new, misfit_new = self.model.cost([u, a, p])

                # Check if armijo conditions are satisfied
                if (cost_new < cost_old + alpha * c_armijo * mg_ahat) or (
                        -mg_ahat <= self.parameters["gda_tolerance"]):
                    cost_old = cost_new
                    descent = 1
                    a0.zero()
                    a0.axpy(1., a)
                else:
                    n_backtrack += 1
                    alpha *= 0.5

            if (print_level >= 0) and (self.it == 1):
                print "\n{0:3} {1:3} {2:15} {3:15} {4:15} {5:15} {6:14} {7:14} {8:14}".format(
                    "It", "cg_it", "cost", "misfit", "reg", "(g,da)",
                    "||g||L2", "alpha", "tolcg")

            if print_level >= 0:
                print "{0:3d} {1:3d} {2:15e} {3:15e} {4:15e} {5:15e} {6:14e} {7:14e} {8:14e}".format(
                    self.it, HessApply.ncalls, cost_new, misfit_new, reg_new,
                    mg_ahat, gradnorm, alpha, tolcg)

            if n_backtrack == max_backtracking_iter:
                self.converged = False
                self.reason = 2
                break

            if -mg_ahat <= self.parameters["gda_tolerance"]:
                self.converged = True
                self.reason = 3
                break

        self.final_grad_norm = gradnorm
        self.final_cost = cost_new
        return [u, a0, p]
Ejemplo n.º 3
0
    def _solve_tr(self, x):
        rel_tol = self.parameters["rel_tolerance"]
        abs_tol = self.parameters["abs_tolerance"]
        max_iter = self.parameters["max_iter"]
        innerTol = self.parameters["inner_rel_tolerance"]
        print_level = self.parameters["print_level"]
        GN_iter = self.parameters["GN_iter"]
        cg_coarse_tolerance = self.parameters["cg_coarse_tolerance"]

        eta_TR = self.parameters["TR"]["eta"]
        delta_TR = None

        u, a, p = x
        self.model.solveFwd(u, x, innerTol)

        self.it = 0
        self.converged = False
        self.ncalls += 1

        a_star = self.model.generate_vector(PARAMETER)
        ahat = self.model.generate_vector(PARAMETER)
        R_ahat = self.model.generate_vector(PARAMETER)
        mg = self.model.generate_vector(PARAMETER)

        u_star = self.model.generate_vector(STATE)

        cost_old, reg_old, misfit_old = self.model.cost(x)
        while (self.it < max_iter) and (self.converged == False):
            self.model.solveAdj(p, x, innerTol)

            self.model.setPointForHessianEvaluations(
                x, gauss_newton_approx=(self.it < GN_iter))
            gradnorm = self.model.evalGradientParameter(x, mg)

            if self.it == 0:
                gradnorm_ini = gradnorm
                tol = max(abs_tol, gradnorm_ini * rel_tol)

            # check if solution is reached
            if (gradnorm < tol) and (self.it > 0):
                self.converged = True
                self.reason = 1
                break

            self.it += 1

            tolcg = min(cg_coarse_tolerance,
                        math.sqrt(gradnorm / gradnorm_ini))

            HessApply = ReducedHessian(self.model, innerTol)
            solver = CGSolverSteihaug()
            solver.set_operator(HessApply)
            solver.set_preconditioner(self.model.Rsolver())
            if self.it > 1:
                solver.set_TR(delta_TR, self.model.prior.R)
            solver.parameters["rel_tolerance"] = tolcg
            solver.parameters["print_level"] = print_level - 1

            solver.solve(ahat, -mg)
            self.total_cg_iter += HessApply.ncalls

            if self.it == 1:
                self.model.prior.R.mult(ahat, R_ahat)
                ahat_Rnorm = R_ahat.inner(ahat)
                delta_TR = max(math.sqrt(ahat_Rnorm), 1)

            a_star.zero()
            a_star.axpy(1., a)
            a_star.axpy(1., ahat)  #a_star = a +ahat
            u_star.zero()
            u_star.axpy(1., u)  #u_star = u
            self.model.solveFwd(u_star, [u_star, a_star, p], innerTol)
            cost_star, reg_star, misfit_star = self.model.cost(
                [u_star, a_star, p])
            ACTUAL_RED = cost_old - cost_star
            #Calculate Predicted Reduction
            H_ahat = self.model.generate_vector(PARAMETER)
            H_ahat.zero()
            HessApply.mult(ahat, H_ahat)
            mg_ahat = mg.inner(ahat)
            PRED_RED = -0.5 * ahat.inner(H_ahat) - mg_ahat
            # print "PREDICTED REDUCTION", PRED_RED, "ACTUAL REDUCTION", ACTUAL_RED
            rho_TR = ACTUAL_RED / PRED_RED

            # Nocedal and Wright Trust Region conditions (page 69)
            if rho_TR < 0.25:
                delta_TR *= 0.5
            elif rho_TR > 0.75 and solver.reasonid == 3:
                delta_TR *= 2.0

            # print "rho_TR", rho_TR, "eta_TR", eta_TR, "rho_TR > eta_TR?", rho_TR > eta_TR , "\n"
            if rho_TR > eta_TR:
                a.zero()
                a.axpy(1.0, a_star)
                u.zero()
                u.axpy(1.0, u_star)
                cost_old = cost_star
                reg_old = reg_star
                misfit_old = misfit_star
                accept_step = True
            else:
                accept_step = False

            if (print_level >= 0) and (self.it == 1):
                print "\n{0:3} {1:3} {2:15} {3:15} {4:15} {5:15} {6:14} {7:14} {8:14} {9:11} {10:14}".format(
                    "It", "cg_it", "cost", "misfit", "reg", "(g,da)",
                    "||g||L2", "TR Radius", "rho_TR", "Accept Step", "tolcg")

            if print_level >= 0:
                print "{0:3d} {1:3d} {2:15e} {3:15e} {4:15e} {5:15e} {6:14e} {7:14e} {8:14e} {9:11} {10:14e}".format(
                    self.it, HessApply.ncalls, cost_old, misfit_old, reg_old,
                    mg_ahat, gradnorm, delta_TR, rho_TR, accept_step, tolcg)

            #TR radius can make this term arbitrarily small and prematurely exit.
            if -mg_ahat <= self.parameters["gda_tolerance"]:
                self.converged = True
                self.reason = 3
                break

        self.final_grad_norm = gradnorm
        self.final_cost = cost_old
        return [u, a, p]
Ejemplo n.º 4
0
def modelVerify(model,
                a0,
                innerTol,
                is_quadratic=False,
                misfit_only=False,
                verbose=True,
                eps=None):
    """
    Verify the reduced Gradient and the Hessian of a model.
    It will produce two loglog plots of the finite difference checks
    for the gradient and for the Hessian.
    It will also check for symmetry of the Hessian.
    """
    if misfit_only:
        index = 2
    else:
        index = 0

    h = model.generate_vector(PARAMETER)
    parRandom.normal(1., h)

    x = model.generate_vector()
    x[PARAMETER] = a0
    model.solveFwd(x[STATE], x, innerTol)
    model.solveAdj(x[ADJOINT], x, innerTol)
    cx = model.cost(x)

    grad_x = model.generate_vector(PARAMETER)
    model.evalGradientParameter(x, grad_x, misfit_only=misfit_only)
    grad_xh = grad_x.inner(h)

    model.setPointForHessianEvaluations(x)
    H = ReducedHessian(model, innerTol, misfit_only=misfit_only)
    Hh = model.generate_vector(PARAMETER)
    H.mult(h, Hh)

    if eps is None:
        n_eps = 32
        eps = np.power(.5, np.arange(n_eps))
        eps = eps[::-1]
    else:
        n_eps = eps.shape[0]
    err_grad = np.zeros(n_eps)
    err_H = np.zeros(n_eps)

    for i in range(n_eps):
        my_eps = eps[i]

        x_plus = model.generate_vector()
        x_plus[PARAMETER].axpy(1., a0)
        x_plus[PARAMETER].axpy(my_eps, h)
        model.solveFwd(x_plus[STATE], x_plus, innerTol)
        model.solveAdj(x_plus[ADJOINT], x_plus, innerTol)

        dc = model.cost(x_plus)[index] - cx[index]
        err_grad[i] = abs(dc / my_eps - grad_xh)

        #Check the Hessian
        grad_xplus = model.generate_vector(PARAMETER)
        model.evalGradientParameter(x_plus,
                                    grad_xplus,
                                    misfit_only=misfit_only)

        err = grad_xplus - grad_x
        err *= 1. / my_eps
        err -= Hh

        err_H[i] = err.norm('linf')

    if verbose:
        modelVerifyPlotErrors(is_quadratic, eps, err_grad, err_H)

    xx = model.generate_vector(PARAMETER)
    parRandom.normal(1., xx)
    yy = model.generate_vector(PARAMETER)
    parRandom.normal(1., yy)

    ytHx = H.inner(yy, xx)
    xtHy = H.inner(xx, yy)
    if np.abs(ytHx + xtHy) > 0.:
        rel_symm_error = 2 * abs(ytHx - xtHy) / (ytHx + xtHy)
    else:
        rel_symm_error = abs(ytHx - xtHy)
    if verbose:
        print "(yy, H xx) - (xx, H yy) = ", rel_symm_error
        if rel_symm_error > 1e-10:
            print "HESSIAN IS NOT SYMMETRIC!!"

    return eps, err_grad, err_H
Ejemplo n.º 5
0
def expectedInformationGainLaplace(model, ns, k, save_any=10, fname="kldist"):
    rank = dl.MPI.rank(dl.mpi_comm_world())
    m_MC = model.generate_vector(PARAMETER)
    u_MC = model.generate_vector(STATE)
    noise_m = dl.Vector()
    model.prior.init_vector(noise_m, "noise")
    noise_obs = dl.Vector()
    model.misfit.B.init_vector(noise_obs, 0)

    out = np.zeros((ns, 5))
    header = 'kldist, c_misfit, c_reg, c_logdet, c_tr'

    p = 20

    Omega = MultiVector(m_MC, k + p)
    parRandom.normal(1., Omega)

    for iMC in np.arange(ns):
        if rank == 0:
            print "Sample: ", iMC
        parRandom.normal(1., noise_m)
        parRandom.normal(1., noise_obs)
        model.prior.sample(noise_m, m_MC)
        model.solveFwd(u_MC, [u_MC, m_MC, None], 1e-9)
        model.misfit.B.mult(u_MC, model.misfit.d)
        model.misfit.d.axpy(np.sqrt(model.misfit.noise_variance), noise_obs)

        a = m_MC.copy()
        parameters = ReducedSpaceNewtonCG_ParameterList()
        parameters["rel_tolerance"] = 1e-9
        parameters["abs_tolerance"] = 1e-12
        parameters["max_iter"] = 25
        parameters["inner_rel_tolerance"] = 1e-15
        parameters["globalization"] = "LS"
        parameters["GN_iter"] = 5
        if rank != 0:
            parameters["print_level"] = -1

        solver = ReducedSpaceNewtonCG(model, parameters)
        x = solver.solve([None, a, None])

        if rank == 0:
            if solver.converged:
                print "\nConverged in ", solver.it, " iterations."
            else:
                print "\nNot Converged"

            print "Termination reason: ", solver.termination_reasons[
                solver.reason]
            print "Final gradient norm: ", solver.final_grad_norm
            print "Final cost: ", solver.final_cost

        model.setPointForHessianEvaluations(x, gauss_newton_approx=False)
        Hmisfit = ReducedHessian(model,
                                 solver.parameters["inner_rel_tolerance"],
                                 misfit_only=True)
        d, U = doublePassG(Hmisfit,
                           model.prior.R,
                           model.prior.Rsolver,
                           Omega,
                           k,
                           s=1,
                           check=False)
        posterior = GaussianLRPosterior(model.prior, d, U)
        posterior.mean = x[PARAMETER]

        kl_dist, c_detlog, c_tr, cr = posterior.klDistanceFromPrior(
            sub_comp=True)
        if rank == 0:
            print "KL-Distance from prior: ", kl_dist

        cm = model.misfit.cost(x)
        out[iMC, 0] = kl_dist
        out[iMC, 1] = cm
        out[iMC, 2] = cr
        out[iMC, 3] = c_detlog
        out[iMC, 4] = c_tr

        if (rank == 0) and (iMC % save_any == save_any - 1):
            all_kl = out[0:iMC + 1, 0]
            print "I = ", np.mean(all_kl), " Var[I_MC] = ", np.var(
                all_kl, ddof=1) / float(iMC + 1)
            if fname is not None:
                np.savetxt(fname + '_tmp.txt',
                           out[0:iMC + 1, :],
                           header=header,
                           comments='% ')

    if fname is not None:
        np.savetxt(fname + '.txt', out, header=header, comments='% ')

    return np.mean(out[:, 0])