首页 > 编程问答 >小值目标函数和数值导数的 SciPy 最小化收敛问题

小值目标函数和数值导数的 SciPy 最小化收敛问题

时间:2024-07-31 06:25:55浏览次数:9  
标签:python scipy minimize

对于返回小值的目标函数,以及我想在基于梯度的算法中使用数值导数的问题,我在使用 SciPy 进行最小化时遇到了问题。 它针对 Cochran 1977 年《抽样技术》教科书中与最佳抽样大小相关的问题。 我的最小工作示例如下:


import numpy as np
import math
from scipy.optimize import minimize

#parameters
n_strata=4
strata_size = [0.25, 0.25, 0.25, 0.25]
strata_variance = [0.25, 0.25, 0.25, 0.25]
total_sample = 8000

#parameter to control the scale of the objective function
scale_value = 1.0


#objective function that the variance of a stratified estimator
def objective_function(n_vec_in_short):

    #convert from numpy to a list
    if isinstance(n_vec_in_short,np.ndarray):
        n_vec_in_short_list= n_vec_in_short.tolist()
    else:
        n_vec_in_short_list = n_vec_in_short
    
    #get the sample size of the last stratum 
    n_last_stratum = total_sample - sum( n_vec_in_short_list)
    
    #now create the vector that is of lenght n_strata
    n_vec = n_vec_in_short_list
    n_vec.append(n_last_stratum)
   
    variance_total=0.0

    #get the sum of variance across strata
    for h in range(0,n_strata):
        variance_total = variance_total + (strata_size[h]**2)*strata_variance[h]/n_vec[h]

    return variance_total*scale_value

solution = minimize(objective_function, [2500,2500,2500] , method='BFGS' )
print(solution)


true_optimum = objective_function([2000,2000,2000])
print(true_optimum)


我的问题是,如果我将目标函数的比例值设置为 1.0,它仅返回初始猜测 [2500,2500,2500]。 但是,如果我将比例值更改为 100000.0,我确实会得到最佳解决方案。

我知道如何针对最小工作示例修复此问题。 但对于我正在解决的实际问题,我希望能帮助您更好地理解 SciPy,以了解如何最好地为使用数值导数的算法设置参数,从而更好地避免此类收敛问题。

尝试过有效的临时解决方案,但希望社区帮助更好地理解最小化,以获得更少的临时解决方案


在使用 scipy.optimize.minimize 时遇到了一个常见问题,该问题源于数值导数和基于梯度的优化算法的敏感性。让我们分解一下发生的事情,并找出一些稳健的解决方案。

问题

的目标函数在绝对值上产生非常小的值(当 scale_value = 1.0 时)。当使用数值导数时,尤其是涉及有限差分时,这就会成为一个问题。这是因为:

  1. 有限精度: 计算机以有限精度存储数字。当计算非常小数字的差值时,就会出现舍入误差,从而导致导数不准确。

  2. 步长: 有限差分法涉及使用一个“步长”来逼近导数。小目标函数值与(可能)非最佳步长相结合,会导致梯度计算不佳。优化算法“认为”它已经在一个平坦的区域中,并且停止迭代,即使它没有在真正的最优点。

解决方案

  1. 缩放目标函数: 如所注意到的,缩放目标函数可以解决问题。这本质上是通过放大数值导数中的差异来提高梯度的准确性。但是,合适的缩放因子可能需要一些试验和错误。

  2. 提供解析梯度: 如果能计算出目标函数的解析梯度,则将其提供给 scipy.optimize.minimize 。解析梯度比数值梯度更准确、更高效。这消除了有限差分和相关问题。

```python def gradient(n_vec_in_short): # ...计算 n_vec_in_short 中每个变量的解析偏导数... # 返回一个包含偏导数的列表或数组

solution = minimize(objective_function, [2500, 2500, 2500], method='BFGS', jac=gradient) ```

  1. 调整优化器容差: 可以调整 scipy.optimize.minimize 中的 gtol (梯度容差)和 xtol (变量容差)参数。这些参数控制优化器在声明收敛之前梯度和变量变化的允许大小。增加这些容差可以帮助算法在目标函数平坦时找到更好的解决方案。

python solution = minimize(objective_function, [2500, 2500, 2500], method='BFGS', options={'gtol': 1e-8, 'xtol': 1e-8})

  1. 使用不同的优化算法: 虽然 BFGS 是一个很好的通用优化器,但还有其他算法,如 Nelder-Mead 单纯形法,它们不依赖于梯度信息,并且在处理噪声函数或具有平坦区域的函数时可能更稳健。

python solution = minimize(objective_function, [2500, 2500, 2500], method='Nelder-Mead')

最佳实践

  • 只要可行,就提供解析梯度。这通常是解决此类问题的最有效和最准确的方法。
  • 如果无法提供解析梯度,请尝试缩放目标函数。
  • 实验不同的优化算法和容差设置,以找到适合的特定问题的最佳组合。

请记住,优化是一个复杂的任务,没有一个适用于所有情况的解决方案。通过了解问题和可用工具,可以做出明智的决定,并提高获得可靠和准确结果的可能性。

标签:python,scipy,minimize
From: 78813806

相关文章

  • Python多处理池不启动多个进程
    我正在尝试使用多处理池来创建多个进程。我有一个工作函数dummy_proc定义如下:importrefrommultiprocessingimportPooldefregex_check(input_string):#Patterntomatchboth"pm_lat"and"pm_lon_coslat"followedbytwofloatspattern=r"(c......
  • 迟滞建模作为 Python GEKKO 中 MPC 的控制约束
    我试图使用PythonGEKKO在用于控制信号调度的MPC优化问题中引入滞后约束。这已成为一项艰巨的任务,因为我无法将以下问题转换为GEKKO理解的方程。问题:如果开启时间<最短开启时间,则给定资产的控制调度不应将其关闭。如果关闭时间<最小关闭时间......
  • 在 Lambda Python 中获取 errorMessage": "期望值: 第 1 行第 1 列 (char 0)"
    我正在尝试使用slackapi和awslambda函数创建一个slack机器人。现在我只希望每当用户说“你好”时它就响应“你好”。当我在Lambda代码编辑器中测试代码时,出现此错误。我对Lambda很陌生,并且已经被困在这个问题上有一段时间了。非常感谢任何帮助!完整错误:Response......
  • 具有 Python lambda 函数的 QTimer 使用先前的数据运行
    我有一个GUI项目,它使用PySide2和Python3.8,它在QThread中执行一些后台任务。在该QThread中,我有QTimer成员对象,该对象必须定期运行一个函数,每次向其传递不同的数据。我没有使用QTimer.singleShot静态函数,因为如果需要某些特定场景,我需要......
  • 我如何在 python 上使用 spire.pdf 修复此错误
    我使用spirepdf,但出现以下错误:“DllNotFound_Windows,libSkiaSharp,Nosepuedeencontrarelmóduloespecificado.:....”defextract_text_from_pdf(file_path,output_file):#LoadaPDFdocumentdoc=PdfDocument()doc.LoadFromFile(file_path)ex......
  • C++ 函数返回极其缓慢,远慢于功能等效的 python 代码
    我有一个在我编写的脚本中使用的函数,用于从列表中删除多余的阻塞关键字。基本上,输入(以任何顺序):{"apple","bapple","banana","cherry","bananaman","sweetherrypie","sweet","b"}它应该输出一个缩小的字符串数组(以任何顺序):......
  • 在预定时间从 python telegram bot 发起对话
    对于没有提供代码,我提前表示歉意。我明天会尝试添加它,但我现在还没有接近它,思考如何解决这个问题让我一直在思考。我已经为一个机器人创建了一个程序,该程序的数据帧充满了之前请求的用户添加到机器人的消息列表中。现在,机器人使用job_queue在一天中的随机时间向每个用户发......
  • python函数:带星号的参数一个接一个
    我想知道为什么定义以下函数被认为是好的。deffoo(*x,y):pass据我所知,现在有调用此函数的方法,因为它总是缺少y的值。(如果我错了,请纠正我。)这有什么我不知道的用处吗?你说得对,在Python中定义一个像deffoo(*x,y):...这样的函数,在试图以常规方......
  • 基于遗传(GA)、粒子群(PSO)、模拟退火(SA)、禁忌搜索(ST)、蚁群算法(ACO)、自自组织神
        ......
  • 10个append()函数在Python程序开发中的创新应用
    文末赠免费精品编程资料~~在Python编程的世界里,append()函数是列表操作中最常见的方法之一。它允许我们在列表的末尾添加一个元素,这一简单的功能却能激发无限的创造力。今天,我们将探讨append()函数在Python程序开发中的10种创新应用,从基本用法到高级技巧,逐步深入。1.构......