Skip to content
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

LIPO fails to explore under certain conditions, ignores boundary conditions #162

Open
shusheer opened this issue Jan 2, 2022 · 0 comments

Comments

@shusheer
Copy link

shusheer commented Jan 2, 2022

As described at http://blog.dlib.net/2017/12/a-global-optimization-algorithm-worth.html LIPO is supposed to alternate a random search of candidate values for parameters with a local optimiser. The random search depends on the Lipschitz constant (which is taken as the greatest gradient seen thus far), with the highest peak being selected as the next "random" point to choose. Therefore, for relatively flat 1D functions with a relatively sharp feature discovered, this is far from random - it's really more like choosing roughly the midpoint of the largest gap observed thus far. The video makes this obvious if viewed in this light.

lipo version 1.2.2 with dlib version 19.22.0 seems to be sensitive, under certain circumstances, to having an apparently completely different algorithm for the random search component. This apparently also can ignore boundary conditions under certain circumstances.

I found this behaviour whilst optimising a "real" problem of many parameters, but was able to generate a toy 1D function that exhibits the same behaviour when being optimised. The function has a parameter that must be positive, and we think the optimum probably lies in the range 0...6.5. The toy function does indeed have a relatively wide Gaussian peak at x=5.0, with a couple of different slopes and some asymptotic behaviour near 0. The peak at x=5.0 is relatively wide, with the entire region from 4.6 - 5.4 being more optimal than anywhere else on the function, so >10% of x-values within the 0...6.5 bounds are in the correct area. This means a truly random search should end up in the correct region after ~10 random samples. So this shouldn't be a "hard" function to optimise.

However, with certain bounds set, the optimiser goes badly wrong.

Setting the lower bound to 0.0 gives the expected behaviour, and the optimal point is found after ~12 calls. Sample output is below.

That is however unsafe, as the function is undefined at x=0, so we should set the bounds slightly higher than that. If you set the lower bound to a number higher than 0.0 but lower than about 0.006, so use 0.001 for example, things go wrong. The optimiser tries for the 6th observation a point well outside the bounds (47.9) without having tested any point higher than the starting point of 1.3, so the upper bounds expansion should not have happened by that stage. No further points are tested above the initial point, and so the false optima at around x=0.7 is found instead. The "random" search component simply seems not to have happened at all. Sample output is below.

Things get even more weird if you change from a maximizing problem to a minimizing one (make the function return +res rather than -res, and set maximize to false at init). The optimizer doesn't seem to actually minimize - the third observation is made at x=4.959837885048982,y=0.7184097543520752 yet this doesn't get exhaustively searched, and the optimum returned is the starting point of x=1.3,y=0.8061923076923078. Sample output below.

Test code:


import numpy as np

from lipo import GlobalOptimizer

# This test function makes LIPO go badly wrong if lower bound is 0.001 instead of 0.0

def testfunc(x):
    res = 0.767+0.03*x+(0.8-min(x,0.8))*0.03+0.00025/x-0.2*np.exp(-0.5*(((x-5.)/0.25)**2))
    print(f"x={x},y={res}")
    return -res

to_adj = {'x':1.3}

lower_bounds={'x':0.00}
upper_bounds={'x':6.5}
flexible_bounds = {'x':[False,True]}

print(lower_bounds,upper_bounds,flexible_bounds)

evaluations = [(to_adj, testfunc(**to_adj))]

search = GlobalOptimizer(
    testfunc,
    lower_bounds=lower_bounds,
    upper_bounds=upper_bounds,
    evaluations=evaluations,
    maximize=True,
    epsilon=0.001,
    flexible_bounds = flexible_bounds,
    flexible_bound_threshold=0.3
)

num_function_calls = 60

search.run(num_function_calls)

print("optimal:",search.optimum)

Sample output for lower_bounds = 0.0

{'x': 0.0} {'x': 6.5} {'x': [False, True]}
x=1.3,y=0.8061923076923078
x=1.5162723597900987,y=0.8126530488239498
x=4.95722703849875,y=0.7186731668184985
x=6.5,y=0.9620384584924656
x=3.604517329631011,y=0.8752048430127669
x=9.911823555834058,y=1.0643799290771956
x=0.002527717752752791,y=0.8899034474785563
x=2.3683306067987075,y=0.8381554777906517
x=4.778820802779248,y=0.7751898543399209
x=6.591680510885359,y=0.9647883416065474
x=8.08832701508481,y=1.0096807191929467
x=5.774453774692054,y=0.9386280407284201
x=4.491687760629993,y=0.876494592056028
x=5.365840406595402,y=0.8594690381501378
x=0.7631713242276125,y=0.791327580442377
x=5.008613687303106,y=0.7174270023797293
x=2.93936600778563,y=0.8552660325881708
x=1.9085064498987283,y=0.8243861859806463
x=8.931589697136106,y=1.0349756814519915
x=0.5075240187892668,y=0.7914925875244219
x=7.282625277828794,y=0.9855130866149089
x=1.012685255432904,y=0.7976274260741334
x=4.0479162412160345,y=0.888357454899966
x=5.045706727289335,y=0.7217355398221639
x=5.091741022264519,y=0.732824249278456
x=5.159408943151189,y=0.7586223617293624
x=5.28028598042909,y=0.8187757311079724
x=4.926534030106995,y=0.7232985851730165
x=3.25117331062826,y=0.8646120946303949
x=4.983594812750437,y=0.7169881540181297
x=2.6366565972524487,y=0.8461945149674163
x=5.022921449315891,y=0.7185762796846449
x=4.996096565081077,y=0.7169573134181799
x=4.97284620172799,y=0.7174119125369223
x=4.906372917538525,y=0.727787291036406
x=4.946521106098317,y=0.7199702089270242
x=4.965941233603543,y=0.7178759939851798
x=4.989320767092724,y=0.7169121204422222
x=5.001881883446544,y=0.7171121039878635
x=5.014968874104242,y=0.7178571033611254
x=4.978129535528367,y=0.7171579509040313
x=3.0001315480700703,y=0.8570872761214801
x=5.029698989999021,y=0.7193469551129807
x=4.986024924548875,y=0.716943128263982
x=5.004476239699825,y=0.7172162986543237
x=4.992987763620913,y=0.7169183619918317
x=4.998903082593674,y=0.7170190286045999
x=4.9804358132887625,y=0.7170747459873493
x=4.962357459273232,y=0.7181754390912892
x=4.991380063422506,y=0.7169103382141836
x=4.970134627409922,y=0.7175763645572552
x=5.057030278241193,y=0.7238971500200644
x=4.9766081803405555,y=0.7172220506053204
x=4.9947471256692,y=0.7169366097837161
x=4.988127497389713,y=0.7169193469266795
x=5.011536640376343,y=0.7176088212947616
x=4.996830014080488,y=0.7169710095933064
x=4.98209529757628,y=0.7170253068387629
x=5.000409397865307,y=0.7170625460127154
x=5.01823749819142,y=0.718128405992905
x=4.987163140607319,y=0.7169285051419512
optimal: ({'x': 4.991380063422506}, -0.7169103382141836, 0)

Sample output for lower_bounds = 0.001

{'x': 0.001} {'x': 6.5} {'x': [False, True]}
x=1.3,y=0.8061923076923078
x=0.00775261972766554,y=0.8232471640273887
x=0.8089460658276442,y=0.791577426063874
x=0.12593123546946897,y=0.7929852104131909
x=0.3282322982670415,y=0.7917616556972605
x=47.89169584204994,y=2.2037560953731608
x=0.5176292917645409,y=0.7914829711223408
x=0.0010027520582537326,y=1.0403138736961246
x=0.03243450234809584,y=0.7987078414003993
x=0.06439627524561471,y=0.7948822121162517
x=0.016358820380597078,y=0.8062822755054222
x=0.0036892062013973138,y=0.8587652552750535
x=0.20384166025502037,y=0.7922264421300692
x=0.09028426752612914,y=0.7937690317133896
x=0.04589941318069447,y=0.7964466927282015
x=0.023277210029366953,y=0.8017401187549795
x=0.011455165875757812,y=0.8128242147439407
x=0.005592049636366816,y=0.8357063270637252
x=0.002426354695223126,y=0.894035224195451
x=0.25847133160455393,y=0.7919672252564647
x=0.1602995645839013,y=0.7925595800316049
x=0.4121353171512187,y=0.7916065968860132
x=0.6460074952227348,y=0.7913869924139406
x=1.0042642683378369,y=0.7973768665097437
x=0.07639314710580519,y=0.7942725448482146
x=0.10672859212964457,y=0.7933423901225674
x=0.03880249292180548,y=0.7974428850100893
x=0.0544444788348437,y=0.7955918338342144
x=0.0196098041758155,y=0.8037487249621963
x=0.02749733807989964,y=0.8000917891496832
x=0.013795202213135885,y=0.8091222425113819
x=0.009553294900940045,y=0.8171689817588904
x=0.2913928969491262,y=0.7918579481607737
x=0.1807604446665611,y=0.7923830459449309
x=0.22960392243932284,y=0.7920888315728406
x=0.14211964091530632,y=0.7927590812810242
x=0.4619323240343351,y=0.7915412048193913
x=0.7228355034569743,y=0.7913458601560167
x=0.026099427489967006,y=0.8005787541736732
x=0.36711565230086,y=0.7916809843122546
x=0.5806799787670072,y=0.7914305297395148
x=0.8949715534354117,y=0.7941284850904594
x=1.1297381486510578,y=0.8011134346764713
x=0.11602513551757962,y=0.7931547055203579
x=0.09813374028745847,y=0.7935475437832868
x=0.07023587145308956,y=0.7945594347279791
x=0.08315935057393203,y=0.7940062764833372
x=0.05928266064114806,y=0.795217084680347
x=0.050045918931435854,y=0.7959954123200836
x=0.03558024407805522,y=0.7980263711359471
x=0.04220603185132629,y=0.796923323966599
x=0.004681671571924462,y=0.8443997304508128
x=0.006693183334427576,y=0.8283514346624992
x=0.02987013604402358,y=0.799369563487476
x=0.2745679647981154,y=0.7919105213719446
x=0.1920088990725989,y=0.792302022985432
x=0.3091918526815727,y=0.7918085594682776
x=0.5481581600041175,y=0.7914560727509704
x=0.1702716357577299,y=0.7924682421936424
x=0.3889800820904345,y=0.7916427064302534
x=0.21616602120392833,y=0.7921565184880011
optimal: ({'x': 0.7228355034569743}, -0.7913458601560167, 0)

Sample output for lower_bounds = 0.001 and function returning +res and minimize=False

x=1.3,y=0.8061923076923078
x=1.5247063604119921,y=0.8129051568103323
x=4.959837885048982,y=0.7184097543520752
x=0.011,y=0.8137272727272727
x=3.247179109255254,y=0.8644923631749957
x=0.7679017564555649,y=0.7913255624797031
x=6.498863085221904,y=0.9620043576933811
x=1.1452470321951007,y=0.8015757044806773
x=4.110802377411786,y=0.8900268292856839
x=1.3346547389402394,y=0.8072269565295218
x=2.3852394399306225,y=0.8386619944784195
x=1.23990126635982,y=0.804398666948505
x=5.7235853683993705,y=0.9357177581218613
x=1.287258724827208,y=0.8058119728969166
x=1.9540405164520622,y=0.8257491555223868
x=1.3109526441135702,y=0.8065192803385219
x=3.6786476313417555,y=0.8774272169455464
x=1.2991043926428203,y=0.8061655720492243
x=2.8132901455763015,y=0.8514875682906896
x=1.3050284275691808,y=0.8063424195352932
x=4.539499598859584,y=0.866574701185114
x=1.3020663684159435,y=0.8062539935540898
x=6.110385985538823,y=0.9503420871601964
x=1.3005853633975752,y=0.8062097820409895
x=5.33817099470963,y=0.8470787816894156
x=1.2998448731671057,y=0.8061876768378159
x=0.3908946621712491,y=0.7916395584902883
x=1.3002151174417411,y=0.8061987293987181
x=1.7390546747597855,y=0.8193153965051058
x=1.300029994995551,y=0.8061932031051471
x=2.169452765578605,y=0.8321988194011569
x=1.2999374340379475,y=0.8061904399692114
x=3.0302559077453335,y=0.857990178515285
x=1.2999837144993702,y=0.8061918215364168
x=2.5987471413648775,y=0.845058614442967
x=1.300006854742939,y=0.806192512320586
x=3.894431581478029,y=0.8838858075134641
x=1.299995284620121,y=0.8061921669284553
x=3.46261050137073,y=0.8709505136751297
x=1.3000010696812307,y=0.8061923396245079
x=4.324895019716321,y=0.8915862938188399
x=1.2999981771506293,y=0.8061922532764793
x=4.753159685036848,y=0.7868081804108381
x=1.299999623415912,y=0.8061922964504927
x=5.146152933595329,y=0.7528495414562079
x=1.3000003465485677,y=0.8061923180375002
x=0.201810722619439,y=0.792238784524207
x=1.2999999849822386,y=0.8061923072439965
x=0.5792091933031199,y=0.7914316229833548
x=1.300000165765403,y=0.8061923126407483
x=0.9559642061946826,y=0.7959404422534715
x=1.2999997927638298,y=0.8061923015058788
x=5.527061184497257,y=0.9111861874196071
x=1.299999896381915,y=0.8061923045990933
x=6.303653046195853,y=0.9561490018580749
x=1.3000000518090427,y=0.8061923092389149
x=5.916640598150331,y=0.9443006075802054
x=1.2999999740954788,y=0.8061923069190041
x=1.3786203659987348,y=0.8085399516928703
x=1.3000000129522606,y=0.8061923080789595
x=1.2571337849710367,y=0.8049128786206046
optimal: ({'x': 1.3}, 0.8061923076923078, 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant