-
Notifications
You must be signed in to change notification settings - Fork 224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Finding the minimizer to high precision #1120
Comments
Yes it should be mentioned. The whole section on options and tolerances need to be updated. See also #1102 . Currently, Optim's defaults are So yes, you can set the two tolerances to NaN or to negative values (I believe). Do you need this level of precision? I'm am curious, because if you need that level of precision have you considered using another number type? In my other package NLSolvers.jl I support DoubleFloats
|
Hi @pkofod, thanks for your reply. It's great to know that setting
Our application is quantum magnetism. The physical observables (excitation energies, associated with scattering of neutron or x-ray beams) can depend somewhat sensitively on the accuracy of the minimizer "x" (magnetic configuration) not just on the accuracy of the "f" function (ground state energy). Now we can easily get "x" to 12 digits of accuracy, which is enough. We're also speed sensitive, so it's nice to be able to use Float64. |
Great. The actionable item here is to improve documentation then. |
Yes, correct. Also, could you please consider including a test like this to make sure that this feature continues to work in future releases? import Optim
import Test: @test
rosenbrock(x) = (1.0 - x[1])^2 + 100.0 * (x[2] - x[1]^2)^2
# Need high-precision gradient to impose tight tolerances below
function g_rosenbrock!(g, x)
g[1] = 2 * (1.0 - x[1]) * (-1) + 2 * 100 * (x[2] - x[1]^2) * (-2 * x[1])
g[2] = 2 * 100 * (x[2] - x[1]^2)
end
# To set tight tolerance on gradient g, need to disable any check on f
options = Optim.Options(g_tol=1e-10, f_reltol=NaN, f_abstol=NaN)
result = Optim.optimize(rosenbrock, g_rosenbrock!, zeros(2), Optim.ConjugateGradient(), options)
@test Optim.g_residual(result) < 1e-10
# To set tight tolerance on x, need to also disable default gradient tolerance, g_tol=1e-8
options = Optim.Options(x_tol=1e-10, g_tol=NaN, f_reltol=NaN, f_abstol=NaN)
result = Optim.optimize(rosenbrock, g_rosenbrock!, zeros(2), Optim.ConjugateGradient(), options)
@test Optim.x_abschange(result) < 1e-10 |
Convergence of$\epsilon$ (about 16 digits), but the minimizer, and the gradient of the cost function, will be converged to a much reduced precision of $\sqrt{\epsilon}$ (about 8 digits). This makes sense when considering a quadratic cost function of the form $f(x) = -c x^2$ ; convergence in $x$ will be much slower than convergence in $f$ . Optim will by default terminate when the value of $f$ converges, even if
optimize
typically finds the cost function minimum to full numerical precisiong_tol
is set to a very tight tolerance.For some applications, it's important to have the true minimizer$x$ to high precision. I discovered that this is possible by setting two fields in $f$ in its termination condition, and will then respect a very tight
Options
, namelyf_reltol=NaN, f_abstol=NaN
. With both set, theConjugateGradient
method will ignore convergence ofg_tol
. And these options seem to be correctly propagated to the internal line search that conjugate gradient uses!Is setting
f_reltol=NaN, f_abstol=NaN
an "officially supported" use of Optim?If so, it seems like
f_reltol
andf_abstol
both need to be mentioned in the documentation (finding them currently requires reading the source code). Note that settingf_tol=NaN
alone does not seem to work. It would also be great to have test cases to check this use case.The text was updated successfully, but these errors were encountered: