scipy-optimize-minimize 不执行优化 - CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL

2024-05-04

我试图最小化定义如下的函数:

utility(decision) = decision * (risk - cost)

其中变量采用以下形式:

决策 = 二进制数组

风险 = 浮点数数组

成本=常数

我知道解决方案将采取以下形式:

决定=1如果(风险 >= 阈值)

决定 = 0否则

因此,为了最小化这个函数,我可以假设我将函数效用转换为仅依赖于这个阈值。我对 scipy 的直接翻译如下:

def utility(threshold,risk,cost):

     selection_list = [float(risk[i]) >= threshold for i in range(len(risk))]
     v = np.array(risk.astype(float)) - cost

     total_utility = np.dot(v, selection_list)

     return -1.0*total_utility

result = minimize(fun=utility, x0=0.2, args=(r,c),bounds=[(0,1)], options={"disp":True} )

这给了我以下结果:

fun: array([-17750.44298655])  hess_inv: <1x1 LbfgsInvHessProduct with
dtype=float64>
jac: array([0.])   
message: b'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL'
nfev: 2
nit: 0    status: 0   success: True
x: array([0.2])

但是,我知道结果是错误的,因为在这种情况下它必须等于cost。最重要的是,无论我使用什么 x0,它总是返回它作为结果。查看结果,我发现 jacobian=0 并且没有正确计算 1 次迭代。

更深入地研究该功能。我将其绘制出来并观察到它在边界的限制上不是凸的,但我们可以清楚地看到最小值为 0.1。但是,无论我如何将边界调整为仅在凸部分,结果仍然相同。

我可以做什么来最小化这个功能?


错误消息告诉您梯度在某个点太小,因此在数值上与零相同。这可能是由于您在计算时执行的阈值selection_list。你说那儿float(risk[i]) >= threshold,它几乎到处都有导数 0。因此,几乎每个起始值都会向您发出收到的警告。

解决方案可能是对阈值操作应用一些平滑。所以而不是float(risk[i]) >= threshold,您将使用连续函数:

def g(x):
    return 1./(1+np.exp(-x))

使用此函数,您可以将阈值操作表示为g((risk[i] - threshold)/a),其中一个参数a。较大的a,这个修改后的误差函数与您目前所做的越接近。在类似的事情a=20或者这样,你可能会拥有与现在几乎相同的东西。因此,您将得出一系列解决方案,从以下开始a=1然后将该解决方案作为同一问题的起始值a=2,将该解作为问题的起始值a=4, 等等。在某些时候,你会注意到改变a不再改变解决方案,你就完成了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

scipy-optimize-minimize 不执行优化 - CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL 的相关文章

随机推荐