整数步长在SciPy的优化最小化(Integer step size in scipy optimi

2019-06-27 13:11发布

我有一台计算机视觉算法我想调补用scipy.optimize.minimize 。 现在,我只想调整了两个参数,但参数的数量最终可能会增长,所以我想用一种技术,可以做到高维梯度搜索。 在SciPy的该内尔德 - 米德的实施似乎是一个不错的选择。

我得到了所有的代码设置,但似乎最小化功能确实希望使用浮点值与步长小于one.The当前设定的参数均为整数,一个有一个和其他的步长有两个的步长(即值必须是奇数,如果不是我想优化将其转换为奇数的东西)。 大致一个参数是在像素的窗口的尺寸和其他参数是阈值(从0到255的值)。

对于什么是值得我用从git仓库SciPy的一个新版本。 有谁知道如何告诉SciPy的使用特定的步长为每个参数? 有没有一些方法,我可以推出自己的梯度功能? 是否有SciPy的标志,可以帮助我吗? 我知道这可能是与一个简单的参数扫描来完成的,但我希望最终将此代码应用到更大的参数集。

代码本身是死的简单:

import numpy as np
from scipy.optimize import minimize
from ScannerUtil import straightenImg 
import bson

def doSingleIteration(parameters):
    # do some machine vision magic
    # return the difference between my value and the truth value

parameters = np.array([11,10])
res = minimize( doSingleIteration, parameters, method='Nelder-Mead',options={'xtol': 1e-2, 'disp': True,'ftol':1.0,}) #not sure if these params do anything
print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
print res

这是我的输出样子。 正如你可以看到,我们在重复大量的奔跑,并在最小化没有得到任何地方。

*+++++++++++++++++++++++++++++++++++++++++
[ 11.  10.]  <-- Output from scipy minimize
{'block_size': 11, 'degree': 10} <-- input to my algorithm rounded and made int
+++++++++++++++++++++++++++++++++++++++++
120  <-- output of the function I am trying to minimize
+++++++++++++++++++++++++++++++++++++++++
[ 11.55  10.  ]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.   10.5]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.55   9.5 ]
{'block_size': 11, 'degree': 9}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.1375  10.25  ]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.275  10.   ]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.    10.25]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
[ 11.275   9.75 ]
{'block_size': 11, 'degree': 9}
+++++++++++++++++++++++++++++++++++++++++
120
+++++++++++++++++++++++++++++++++++++++++
~~~
SNIP 
~~~
+++++++++++++++++++++++++++++++++++++++++
[ 11.         10.0078125]
{'block_size': 11, 'degree': 10}
+++++++++++++++++++++++++++++++++++++++++
120
Optimization terminated successfully.
         Current function value: 120.000000
         Iterations: 7
         Function evaluations: 27
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  status: 0
    nfev: 27
 success: True
     fun: 120.0
       x: array([ 11.,  10.])
 message: 'Optimization terminated successfully.'
     nit: 7*

Answer 1:

假设最小化函数是任意复杂的(非线性),这是一般非常困难的问题。 它不能保证是最优的解决,除非你想尽一切可能的选择。 我知道是否有任何整数约束的非线性优化器(有点怀疑),我会假设你知道内尔德-米德应正常工作,如果它是一个连续函数。

编辑:考虑从@Dougal我只想在这里添加注释:建立一个粗+细网格搜索第一,如果你再觉得喜欢尝试,如果你的内尔德 - 米德的作品(和收敛速度更快),点下面可以帮助...

但也许一些点,有助于:

  1. 考虑到整个整数约束如何是非常困难的,也许这将是做一些简单的插值来帮助优化的选项。 它应该仍然收敛到一个整数解。 当然,这需要计算加分,但它可能会解决很多其他问题。 (即使在线性整数规划其共同解决无约束系统第一AFAIK)
  2. 内尔德-米德开始与N + 1个点,这些是硬连线在SciPy的(至少旧版本)到(1+0.05) * x0[j] (对于j在所有维度上,除非x0[j]值为0),其你会在你的第一个评估步骤见。 也许这些都可以在新版本中提供,否则,你可能只是更改/复制SciPy的代码(它是纯粹的python),并把它设置为更合理。 或者,如果你觉得这是简单,所有规模的输入变量下,这样(1 + 0.05)* X0是明智的大小。
  3. 也许你应该缓存所有功能的评估,因为如果你使用内尔德 - 米德我猜你总是可以(至少在年底)碰上duplicat评价。
  4. 你必须检查内尔德 - 米德如何可能只会缩小到一个单一的价值而放弃,因为它总是发现相同的结果。
  5. 通常你必须检查,如果你的功能在所有很乖的......这种优化是注定的,如果功能不参数空间变化平稳,即使这样它可以很容易陷入局部极小如果您有这些的。 (因为你缓存所有的评价 - 看2 - 你至少那些情节和看看错误的风景,而无需做任何额外的evluations)


Answer 2:

不幸的是,SciPy的内置的优化工具,不要轻易允许这样做。 但不要害怕; 这听起来像你有一个凸起的问题,所以你应该能够找到一个独特的优化,即使它不会是数学漂亮。

我已经针对不同的问题实现了两个选项创建自定义的梯度下降算法,并采用了一系列单变量的问题平分。 如果你在你的调优做交叉验证,您的损失函数不幸的是不会一帆风顺(因为从不同的数据集交叉验证的噪音),但将是大致的凸。

进行数值实施梯度下降(不具有用于评估所述梯度的分析方法),选择一个试验点和第二点是delta远离您的测试点中的所有尺寸。 在评价这两点你的损失函数,可以让你数值计算本地梯度。 这是很重要的delta是足够大的,它由步交叉验证噪声产生局部极小之外。

较慢,但可能更健壮的替代方法是实施您正在测试的每个参数平分。 如果你知道,在共同的问题,在你的两个参数(或n参数)凸的,也可以分开这为n个单变量优化问题,并写了二分算法递归锤炼中的最佳参数。 这可以帮助处理一些类型quasiconvexity的(例如,如果你的损失函数有一个背景噪声值其域的一部分,并且是凸的其它区域),但需要一个好的猜测,边界为初始迭代。

如果单纯管理单元所请求的x值以整数网格无固定xtol映射到该gridsize,你的风险具有解算器请求的网格单元内的两个点,在接收到相同的输出值,并且得出的结论是它是在最小值。

没有简单的答案,很遗憾。



Answer 3:

打响花车X,Y(又名使用winsize,阈值)到你的函数的整数格,就像这样:

def func( x, y ):
    x = round( x )
    y = round( (y - 1) / 2 ) * 2 + 1  # 1 3 5 ...
    ...

然后内尔德 - 米德只能看到对电网的函数值,并且应该给你接近整数X,Y。

(如果你关心发布您的代码的某个地方,我在寻找测试用例的内尔德 - 米德用重新启动。)



Answer 4:

该内尔德 - 米德最小化方法现在允许您指定的初始单纯顶点,所以你应该能够设置单点相距甚远,然后单将翻牌周围,找到的最小和当单一尺寸低于1收敛。

https://docs.scipy.org/doc/scipy/reference/optimize.minimize-neldermead.html#optimize-minimize-neldermead



文章来源: Integer step size in scipy optimize minimize