Python 旋转优化器的域?
我正在努力找出如何设置参数优化方法的界限(最小/最大)。Twiddle是优化算法:。如何确保p(参数)保持在某个域内?下面是我在Python中的Twiddle实现:Python 旋转优化器的域?,python,algorithm,optimization,parameters,Python,Algorithm,Optimization,Parameters,我正在努力找出如何设置参数优化方法的界限(最小/最大)。Twiddle是优化算法:。如何确保p(参数)保持在某个域内?下面是我在Python中的Twiddle实现: def twiddle(objFunction, args, init=0.5, tolerance=0.00001, domain=(0,float("inf"))): """Optimize a single parameter given an objective function. This is a local
def twiddle(objFunction, args, init=0.5, tolerance=0.00001, domain=(0,float("inf"))):
"""Optimize a single parameter given an objective function.
This is a local hill-climbing algorithm. Here is a simple description of it:
https://www.youtube.com/watch?v=2uQ2BSzDvXs
@param args (tuple) Arguments necessary for the objective function.
@param tolerance (float) Number used to determine when optimization has
converged to a sufficiently good score.
@param objFunction(function)Objective Function used to quantify how good a
particular parameter choice is.
@param init (float) Initial value of the parameter.
@param domain (tuple) Domain of parameter values, as (min, max).
@return (dict) Contains:
"parameter" (float) Threshold that returns the largest score from the
Objective function.
"score" (float) The score from the objective function given the
threshold.
"""
pastCalls = {}
x = init
delta = 0.1
bestScore = objFunction(x, args)
pastCalls[x] = bestScore
while delta > tolerance: #and x >= domain[0]+tolerance and x <= domain[1]-tolerance:
x += delta
if x not in pastCalls:
score = objFunction(x, args)
pastCalls[x] = score
score = pastCalls[x]
if score > bestScore:
bestScore = score
delta *= 2
else:
x -= 2*delta
if x not in pastCalls:
score = objFunction(x, args)
pastCalls[x] = score
score = pastCalls[x]
if score > bestScore:
bestScore = score
delta *= 2
else:
x += delta
delta *= 0.5
print "Parameter:", x
print "Best score:", bestScore
print "delta:", delta
print
return {"parameter": x,
"score": bestScore}
def twidle(objFunction,args,init=0.5,tolerance=0.00001,domain=(0,float(“inf”):
“”“优化给定目标函数的单个参数。
这是一个局部爬山算法。下面是对它的简单描述:
https://www.youtube.com/watch?v=2uQ2BSzDvXs
@目标函数所需的参数args(元组)参数。
@参数公差(浮点)数,用于确定何时进行优化
收敛到一个足够好的分数。
@param objFunction(函数)用于量化
具体的参数选择是。
@param init(float)参数的初始值。
@参数值的参数域(元组)域,如(最小值,最大值)。
@返回(dict)包含:
“参数”(float)阈值,从
目标函数。
“分数”(float)给定目标函数的分数
门槛。
"""
pastCalls={}
x=init
增量=0.1
bestScore=objFunction(x,args)
pastCalls[x]=最佳分数
而δ>公差:#和x>=域[0]+公差和x最佳分数:
最佳分数
增量*=2
其他:
x-=2*delta
如果x不在pastCalls中:
分数=objFunction(x,args)
pastCalls[x]=分数
分数=过去的通话次数[x]
如果得分>最佳得分:
最佳分数
增量*=2
其他:
x+=δ
增量*=0.5
打印“参数:”,x
打印“最佳分数:”,最佳分数
打印“增量:”,增量
打印
返回{“参数”:x,
“得分”:最佳得分}
例如,我希望以
objFunction
的形式运行正弦函数,但域设置为[0,2*pi]。明白了!与@AlexMartelli的评论类似,该算法需要防止在x的每次递增/递减时超出界限。为了保持爬山算法的核心功能,必须将步长delta
调整为当前位置与外部边界之间距离的一半。这样,该算法仍然倾向于沿边界方向移动,如果最大值位于边界,则可以到达该方向,如果需要,还可以从边界向后移动。代码如下:
def twiddle(objFunction, args, init=0.5, tolerance=0.00001, domain=(float("-inf"), float("inf"))):
"""Optimize a single parameter given an objective function.
This is a local hill-climbing algorithm. Here is a simple description of it:
https://www.youtube.com/watch?v=2uQ2BSzDvXs
@param args (tuple) Arguments necessary for the objective function.
@param tolerance (float) Number used to determine when optimization has
converged to a sufficiently good score.
@param objFunction(function)Objective Function used to quantify how good a
particular parameter choice is.
@param init (float) Initial value of the parameter.
@param domain (tuple) Domain of parameter values, as (min, max).
@return (dict) Contains:
"parameter" (float) Threshold that returns the largest score from the
Objective function.
"score" (float) The score from the objective function given the
threshold.
"""
pastCalls = {}
x = init
delta = 0.1
bestScore = objFunction(x, args)
pastCalls[x] = bestScore
while delta > tolerance:
# Keep x within bounds
if x+delta > domain[1]:
delta = abs(domain[1] - x) / 2
x += delta
if x not in pastCalls:
score = objFunction(x, args)
pastCalls[x] = score
score = pastCalls[x]
if score > bestScore:
bestScore = score
delta *= 2
else:
# Keep x within bounds
if x-delta < domain[0]:
delta = abs(domain[0] - x) / 2
x -= 2*delta
if x not in pastCalls:
score = objFunction(x, args)
pastCalls[x] = score
score = pastCalls[x]
if score > bestScore:
bestScore = score
delta *= 2
else:
x += delta
delta *= 0.5
print "Parameter:", x
print "Best score:", bestScore
print "Step size:", delta
print
return {"parameter": x,
"score": bestScore}
def twidle(objFunction,args,init=0.5,tolerance=0.00001,domain=(float(“-inf”),float(-inf”):
“”“优化给定目标函数的单个参数。
这是一个局部爬山算法。下面是对它的简单描述:
https://www.youtube.com/watch?v=2uQ2BSzDvXs
@目标函数所需的参数args(元组)参数。
@参数公差(浮点)数,用于确定何时进行优化
收敛到一个足够好的分数。
@param objFunction(函数)用于量化
具体的参数选择是。
@param init(float)参数的初始值。
@参数值的参数域(元组)域,如(最小值,最大值)。
@返回(dict)包含:
“参数”(float)阈值,从
目标函数。
“分数”(float)给定目标函数的分数
门槛。
"""
pastCalls={}
x=init
增量=0.1
bestScore=objFunction(x,args)
pastCalls[x]=最佳分数
而δ>公差:
#保持x在一定范围内
如果x+增量>域[1]:
delta=abs(域[1]-x)/2
x+=δ
如果x不在pastCalls中:
分数=objFunction(x,args)
pastCalls[x]=分数
分数=过去的通话次数[x]
如果得分>最佳得分:
最佳分数
增量*=2
其他:
#保持x在一定范围内
如果x-delta<域[0]:
delta=abs(域[0]-x)/2
x-=2*delta
如果x不在pastCalls中:
分数=objFunction(x,args)
pastCalls[x]=分数
分数=过去的通话次数[x]
如果得分>最佳得分:
最佳分数
增量*=2
其他:
x+=δ
增量*=0.5
打印“参数:”,x
打印“最佳分数:”,最佳分数
打印“步长:”,增量
打印
返回{“参数”:x,
“得分”:最佳得分}
在每次x+=
或x-=
之后,将x
设置为下限(如果它位于下限之下),将其设置为上限(如果它位于上限之上)(我不确定,但为了稳定性,在这种情况下,您可能需要相应地重新计算delta
)。答案似乎太简单了,这就是为什么这只是一个注释:-)@AlexMartelli不太有效,因为步长delta
仍然会被调整,就好像算法正在朝正确的方向移动(即使它可能会越界)。也就是说,将x硬设置为max会告诉算法它应该继续增加x。这就是为什么我想你可能需要重新计算delta
。但本质上,当max位于边界时,您描述的行为与预期的一样——重新计算delta
最终将其归零,因为它一直试图将x
推出边界,因此while
循环退出。