davisking / dlib

A toolkit for making real world machine learning and data analysis applications in C++

Home Page:http://dlib.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Deterministic versions of find_max_global and find_min_global

oulenz opened this issue · comments

Expected Behavior

I'm looking for a way to use find_min_global in Python that is 100% deterministic/reproducible.

Current Behavior

I sometimes get slightly different results in different runs.

Looking at the source code, it seems clear that find_max_global is not in fact deterministic, because it changes its behaviour based on the runtime of the target function, which depends on the architecture, whatever else is running at the same time and potentially the parameter values that are being evaluated. Specifically, it scales back the Monte Carlo sampling when that takes too much time compared to evaluating the target function, and ultimately resorts to random searching.

Steps to Reproduce

I've managed to reproduce this issue with a modified version of the example code:

import dlib
from math import sin,cos,pi,exp,sqrt

def holder_table(x0,x1):
    # Do some extra work
    for i in range(100):
        i = i**2
    return -abs(sin(x0)*cos(x1)*exp(abs(1-sqrt(x0*x0+x1*x1)/pi)))

x,y = dlib.find_min_global(holder_table,
                           [-10,-10],
                           [10,10],
                           80)

print("optimal inputs: {}".format(x))
print("optimal output: {}".format(y))

I mostly get:

optimal inputs: [-8.055023486163353, -9.664590009526423]
optimal output: -19.208502567886732

but sometimes one of these:

optimal inputs: [-8.064969430503735, 9.662303063982197]
optimal output: -19.20747862796451
optimal inputs: [7.628545844250482, 9.5718335077948]
optimal output: -17.454451199912715
optimal inputs: [10.0, 10.0]
optimal output: -15.140223856952055

You may not be able to reproduce this, as I'm currently running two intensive calculations in the background. I haven't been able to increase the chance of getting one of the alternative results by simply making the target function computationally more intensive. When I run the unmodified example code I always seem to get the same result.

  • Version: 19.22.0
  • Where did you get dlib: conda-forge
  • Platform: Ubuntu 20.04.4 LTS
  • Compiler: N/A

Question

I guess what I am asking for is how the global_function_search object can be use to exactly replicate the behaviour of find_min_global, without scaling back the Monte Carlo sampling. (Also, I don't need the log conversion, since I handle that myself.)

I've come up with the following:

import dlib
from math import sin,cos,pi,exp,sqrt

def holder_table(x0,x1):
    return -abs(sin(x0)*cos(x1)*exp(abs(1-sqrt(x0*x0+x1*x1)/pi)))

spec = dlib.function_spec(bound1=[-10, -10], bound2=[10, 10])
search = dlib.global_function_search(spec)
for i in range(80):
    next = search.get_next_x()
    x0, x1 = next.x
    next.set(-holder_table(x0, x1))

x, y, _ = search.get_best_function_eval()

print("optimal inputs: {}".format(list(x)))
print("optimal output: {}".format(-y))

Which results in:

optimal inputs: [8.055023473597158, 9.664590011114276]
optimal output: -19.20850256788674

This is not exactly the same result as above, but it's very close, so may be due to rounding?

Is there anything extra that find_max_global does that I've missed?

(Longterm, it could also be nice for find_max_global and find_min_global to have a parameter controlling this behaviour.)

Yeah that's what you do. global_function_search is the real tool here. find_max_global is just a convenience function so someone can "just do it" without thinking about anything. Like about if log scaling makes sense or if they should use faster but less smart sampling (e.g. it's pointless to spend 1s thinking about what point to sample if the objective function is so fast you can evaluate it a million times per second).

So more sophisticated users should just use global_function_search directly :)

Warning: this issue has been inactive for 35 days and will be automatically closed on 2022-06-02 if there is no further activity.

If you are waiting for a response but haven't received one it's possible your question is somehow inappropriate. E.g. it is off topic, you didn't follow the issue submission instructions, or your question is easily answerable by reading the FAQ, dlib's official compilation instructions, dlib's API documentation, or a Google search.