Source code for skscope.numeric_solver
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author: Zezhi Wang
# Copyright (C) 2023 abess-team
# Licensed under the MIT License.
import numpy as np
import math
import nlopt
from scipy.optimize import minimize
[docs]
def convex_solver_nlopt(
objective_func,
value_and_grad,
init_params,
optim_variable_set,
data,
):
"""
A wrapper of ``nlopt`` solver for convex optimization.
Parameters
----------
objective_func: callable
The objective function.
``objective_func(params, data) -> loss``, where ``params`` is a 1-D array with shape (dimensionality,).
value_and_grad: callable
The function to compute the loss and gradient.
``value_and_grad(params, data) -> (loss, grad)``, where ``params`` is a 1-D array with shape (dimensionality,).
init_params: array of shape (dimensionality,)
The initial value of the parameters to be optimized.
optim_variable_set: array of int
The index of variables to be optimized, others are fixed to the initial value.
data:
The data passed to objective_func and value_and_grad.
Returns
-------
loss: float
The loss of the optimized parameters, i.e., `objective_func(params, data)`.
optimized_params: array of shape (dimensionality,)
The optimized parameters.
"""
best_loss = math.inf
best_params = None
def cache_opt_fn(x, grad):
nonlocal best_loss, best_params
# update the nonlocal variable: params
init_params[optim_variable_set] = x
if grad.size > 0:
loss, full_grad = value_and_grad(init_params, data)
grad[:] = full_grad[optim_variable_set]
else:
loss = objective_func(init_params, data)
if loss < best_loss:
best_loss = loss
best_params = np.copy(x)
return loss
nlopt_solver = nlopt.opt(nlopt.LD_LBFGS, optim_variable_set.size)
nlopt_solver.set_min_objective(cache_opt_fn)
try:
init_params[optim_variable_set] = nlopt_solver.optimize(
init_params[optim_variable_set]
)
return nlopt_solver.last_optimum_value(), init_params
except RuntimeError:
init_params[optim_variable_set] = best_params
return best_loss, init_params
[docs]
def convex_solver_BFGS(
objective_func,
value_and_grad,
init_params,
optim_variable_set,
data,
):
def fun(x):
init_params[optim_variable_set] = x
return objective_func(init_params, data)
def jac(x):
init_params[optim_variable_set] = x
_, grad = value_and_grad(init_params, data)
return grad[optim_variable_set]
res = minimize(fun, init_params[optim_variable_set], method="BFGS", jac=jac)
init_params[optim_variable_set] = res.x
return res.fun, init_params