Python scipy.optimize.least_squares使用方法及参数详解

最优化作业,要用一个老师给出的一个线性加非线性的模型

来拟合

太菜了,手搓不了,只能直接用scipy.optimize.least_squares,充分利用到least_squares各个参数,之后拟合效果还是挺好的。

def least_squares(

        fun, x0, jac='2-point', bounds=(-np.inf, np.inf), method='trf',

        ftol=1e-8, xtol=1e-8, gtol=1e-8, x_scale=1.0, loss='linear',

        f_scale=1.0, diff_step=None, tr_solver=None, tr_options={},

        jac_sparsity=None, max_nfev=None, verbose=0, args=(), kwargs={}):

fun

fun参数是least_squares函数的一个重要参数,它应该是一个计算模型预测值和实际值之间差异(即残差)的函数。这个函数需要接受两个参数:

一个一维数组,表示模型的参数。

一个可选的一维数组,表示额外的参数。

函数的返回值应该是一个一维数组,表示每个观测值的残差。

例如,如果你有一个线性模型y = a * x + b,你的数据是x和y,你想要找到最佳的a和b,你可以定义如下的fun函数:

def fun(params, x, y):

    a = params[0]

    b = params[1]

    return a * x + b – y

然后你可以将这个函数和你的数据传递给least_squares函数:

from scipy.optimize import least_squares

# 假设你的数据是:

x_data = np.array([1, 2, 3, 4, 5])

y_data = np.array([2, 4, 6, 8, 10])

# 初始猜测值

initial_guess = np.array([1.0, 1.0])

result = least_squares(fun, initial_guess, args=(x_data, y_data))

在这个例子中,fun函数计算了模型预测值a * x + b和实际值y之间的差异。least_squares函数会尝试找到最小化这个差异的a和b。

x0

x0参数是least_squares函数的一个重要参数,它表示优化问题的初始猜测值。这个参数应该是一个一维数组,其长度等于你的模型参数的数量

例如,如果你的模型是一个线性模型y = a * x + b,那么你有两个参数a和b,你需要提供一个长度为2的数组作为x0。

这个初始猜测值不需要非常精确,但是一个好的初始猜测值可以帮助优化算法更快地收敛到最优解。

例如:

# 初始猜测值

x0 = np.array([1.0, 1.0])

在这个例子中,我们假设a和b的初始值都是1.0。然后我们可以将这个初始猜测值传递给least_squares函数:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0)

least_squares函数会从这个初始猜测值开始,尝试找到最小化残差的参数值。

jac

jac='2-point'是least_squares函数的一个参数,表示用于计算雅可比矩阵(Jacobian matrix)的方法。

雅可比矩阵是一个函数的一阶偏导数以一定方式排列成的矩阵,其元素是偏导数。在最小二乘问题中,雅可比矩阵用于描述模型函数关于参数的局部线性性质。

'2-point'表示使用二点差分法来估计雅可比矩阵。这是一种数值方法,通过在每个参数上加减一个小的扰动,然后计算函数值的变化来估计偏导数。

除了'2-point',least_squares函数还支持其他的雅可比矩阵计算方法,如'3-point'(三点差分法),'cs'(复步长差分法),以及直接提供一个计算雅可比矩阵的函数。

'2-point'选项在least_squares函数中使用了二点差分法来估计雅可比矩阵。二点差分法是一种数值微分方法,用于估计一个函数在某一点的导数(或梯度)。

以下是二点差分法的基本步骤:

对于每个参数x[i],增加一个小的正扰动h,计算函数在x[i] + h处的值,记为f_plus。

同样,减去一个小的正扰动h,计算函数在x[i] – h处的值,记为f_minus。

使用公式(f_plus – f_minus) / (2 * h)来估计函数在x[i]处的导数。

在least_squares函数中,这个过程被应用于每个参数,以构建雅可比矩阵。注意,这个过程需要函数能够对每个参数单独进行扰动,这通常意味着函数需要接受一个向量作为输入。

这种方法的一个主要优点是它不需要显式地提供导数函数,只需要能够计算函数值。但是,它可能会受到数值精度问题的影响,特别是当h非常小的时候。

ftol

ftol参数是least_squares函数的一个可选参数,用于指定优化过程的终止条件之一。这个参数应该是一个非负的浮点数。

ftol表示相对误差的容忍度,在优化过程中,如果连续两次迭代的残差之间的相对变化小于ftol,则认为优化过程已经收敛,优化过程将停止。

例如,如果你设置ftol=1e-8,那么当连续两次迭代的残差之间的相对变化小于1e-8时,优化过程将停止。

这个参数可以帮助你控制优化过程的精度和计算时间。如果你需要更精确的结果,你可以设置一个更小的ftol;如果你希望优化过程更快,你可以设置一个更大的ftol。

bounds

bounds参数是least_squares函数的一个可选参数,用于指定模型参数的边界。这个参数应该是一个长度为2的元组,元组的第一个元素是下界,第二个元素是上界。

下界和上界可以是一个数(对所有参数使用相同的边界),也可以是一个数组(对每个参数使用不同的边界)。如果你不想对某个参数设置边界,你可以使用-np.inf表示下界,np.inf表示上界。

例如,如果你有两个参数a和b,你想要a在0到1之间,b在1到2之间,你可以这样设置bounds:

bounds = ([0, 1], [1, 2])

如果你不想对a和b设置任何边界,你可以这样设置bounds:

bounds = (-np.inf, np.inf)

在这个例子中,-np.inf表示没有下界,np.inf表示没有上界。这意味着a和b可以取任何实数值。

method

method参数是least_squares函数的一个可选参数,用于指定优化算法。'trf'是其中一种可选的方法,表示Trust Region Reflective算法。

Trust Region Reflective算法是一种用于非线性最小二乘优化的算法,特别适用于大规模问题和具有边界约束的问题。

least_squares函数还支持其他的优化方法,如'lm'(Levenberg-Marquardt算法)和'dogbox'(dogleg算法与box约束的结合)。

如果你不指定method参数,least_squares函数会根据问题的性质(是否有边界约束,问题的规模等)自动选择一个合适的方法。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, method='trf')

在这个例子中,我们指定使用Trust Region Reflective算法来进行优化。

ftol

ftol参数是least_squares函数的一个可选参数,用于指定优化过程的终止条件之一。这个参数应该是一个非负的浮点数。

ftol表示相对误差的容忍度,在优化过程中,如果连续两次迭代的残差之间的相对变化小于ftol,则认为优化过程已经收敛,优化过程将停止。

例如,如果你设置ftol=1e-8,那么当连续两次迭代的残差之间的相对变化小于1e-8时,优化过程将停止。

这个参数可以帮助你控制优化过程的精度和计算时间。如果你需要更精确的结果,你可以设置一个更小的ftol;如果你希望优化过程更快,你可以设置一个更大的ftol。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, ftol=1e-8)

在这个例子中,我们设置ftol=1e-8,表示我们希望优化过程的精度达到1e-8。

xtol

xtol是一个用于确定优化过程停止的阈值。当连续两次迭代之间的参数变化小于xtol时,优化过程将停止。xtol应该是一个非负的浮点数。例如,如果你希望当参数变化小于0.001时停止优化,你可以设置xtol=0.001。

gtol

gtol参数是least_squares函数的一个可选参数,用于指定优化过程的另一个终止条件。这个参数应该是一个非负的浮点数。

gtol表示梯度范数的容忍度,在优化过程中,如果梯度的范数小于gtol,则认为优化过程已经收敛,优化过程将停止。

例如,如果你设置gtol=1e-8,那么当梯度的范数小于1e-8时,优化过程将停止。

这个参数可以帮助你控制优化过程的精度和计算时间。如果你需要更精确的结果,你可以设置一个更小的gtol;如果你希望优化过程更快,你可以设置一个更大的gtol。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, gtol=1e-8)

在这个例子中,我们设置gtol=1e-8,表示我们希望梯度的范数小于1e-8。

x_scale

x_scale参数是least_squares函数的一个可选参数,用于对模型参数进行缩放。这个参数可以是一个正数,或者一个长度等于模型参数数量的数组。

如果x_scale是一个正数,那么所有的模型参数都会被这个数值缩放。例如,如果你设置x_scale=1.0,那么模型参数不会被缩放。

如果x_scale是一个数组,那么每个模型参数会被对应的数组元素缩放。例如,如果你有两个参数a和b,你可以设置x_scale=[1.0, 2.0],那么a不会被缩放,b会被缩放2倍。

参数缩放可以帮助改善优化问题的条件,使得优化算法更容易找到最优解。特别是当模型参数的量级差距很大时,参数缩放可以显著提高优化算法的性能。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, x_scale=1.0)

在这个例子中,我们设置x_scale=1.0,表示我们不对模型参数进行缩放。

模型参数的量级差距很大 举例:假设你正在使用一个包含两个参数的模型,其中一个参数的值通常在1e-5的范围内,而另一个参数的值通常在1e5的范围内。这就是一个模型参数的量级差距很大的例子。

在这种情况下,如果你使用一个不进行参数缩放的优化算法,可能会遇到问题。因为大的参数值可能会主导优化过程,导致小的参数值被忽视,从而使得优化算法难以找到最优解。

为了解决这个问题,你可以使用x_scale参数对模型参数进行缩放。例如,你可以设置x_scale=[1e5, 1e-5],这样,两个参数在优化过程中就会被视为同等重要。

loss参数(区分残residual 和损失loss)是least_squares函数的一个可选参数,用于指定损失函数。损失函数用于度量模型预测值和实际值之间的差异。

'linear'是其中一种可选的损失函数,表示线性损失函数。线性损失函数就是残差的绝对值,即loss(y, f(x)) = abs(y – f(x))。

least_squares函数还支持其他的损失函数,如'soft_l1'(平滑的L1损失函数),'huber'(Huber损失函数),'cauchy'(Cauchy损失函数),'arctan'(反正切损失函数)。

如果你不指定loss参数,least_squares函数默认使用'linear'损失函数。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, loss='linear')

在这个例子中,我们指定使用线性损失函数来度量模型预测值和实际值之间的差异。

f_scale

f_scale参数是least_squares函数的一个可选参数,用于确定损失函数的缩放因子。这个参数应该是一个正数。

f_scale参数的作用是将残差除以这个缩放因子然后再计算损失函数。这样可以帮助改善优化问题的条件,使得优化算法更容易找到最优解。

例如,如果你设置f_scale=1.0,那么残差就不会被缩放。

如果你的残差的量级非常大,你可以设置一个大于1的f_scale;如果你的残差的量级非常小,你可以设置一个小于1的f_scale。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, f_scale=1.0)

在这个例子中,我们设置f_scale=1.0,表示我们不对残差进行缩放。

diff_step

diff_step参数是least_squares函数的一个可选参数,用于指定计算雅可比矩阵的有限差分近似时使用的步长。这个参数可以是一个正数,或者一个长度等于模型参数数量的数组。

如果diff_step是一个正数,那么所有的模型参数在计算有限差分近似时都会使用这个步长。例如,如果你设置diff_step=1e-6,那么所有的模型参数在计算有限差分近似时都会使用1e-6作为步长。

如果diff_step是一个数组,那么每个模型参数在计算有限差分近似时都会使用对应的步长。例如,如果你有两个参数a和b,你可以设置diff_step=[1e-6, 1e-8],那么在计算a的有限差分近似时会使用1e-6作为步长,在计算b的有限差分近似时会使用1e-8作为步长。

如果你不指定diff_step参数,least_squares函数会自动选择一个合适的步长。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, diff_step=None)

在这个例子中,我们没有指定diff_step参数,least_squares函数会自动选择一个合适的步长来计算雅可比矩阵的有限差分近似。

tr_solver

tr_solver参数是least_squares函数的一个可选参数,用于指定用于求解信赖区域子问题的算法。这个参数可以是'exact','lsmr'或者'cg'。

'exact':表示使用精确的算法来求解信赖区域子问题。这个方法在问题规模较小或者雅可比矩阵是稀疏的情况下效率较高。

'lsmr':表示使用LSMR算法来求解信赖区域子问题。这个方法在问题规模较大且雅可比矩阵是密集的情况下效率较高。

'cg':表示使用共轭梯度算法来求解信赖区域子问题。这个方法在问题规模较大且雅可比矩阵是密集的情况下效率较高。

如果你不指定tr_solver参数,least_squares函数会根据问题的性质(问题的规模,雅可比矩阵的稠密程度等)自动选择一个合适的方法。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, tr_solver=None)

在这个例子中,我们没有指定tr_solver参数,least_squares函数会自动选择一个合适的方法来求解信赖区域子问题。

tr_options

tr_options参数是least_squares函数的一个可选参数,用于指定信赖区域求解器的选项。这个参数应该是一个字典。

这个字典的键是选项的名称,值是选项的值。可用的选项取决于你选择的信赖区域求解器。

例如,如果你选择的信赖区域求解器是'exact',那么你可以设置tr_options={'regularize': True},表示在求解过程中使用正则化。

如果你选择的信赖区域求解器是'lsmr'或者'cg',那么你可以设置tr_options={'atol': 1e-6, 'btol': 1e-6},表示设置LSMR或者CG算法的终止条件。

如果你不指定tr_options参数,least_squares函数会使用默认的选项。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, tr_options={})

在这个例子中,我们没有指定tr_options参数,least_squares函数会使用默认的选项。

信赖域方法是一种迭代优化算法,用于求解非线性优化问题。在每次迭代中,它在当前点附近定义一个“信赖域”,并在这个区域内寻找一个改进的点。

信赖域的大小反映了我们对模型在当前点附近的“信赖”程度。如果模型在当前点的预测效果很好,那么我们可以“信赖”模型,选择一个较大的信赖域;如果模型在当前点的预测效果不好,那么我们对模型的“信赖”程度就较低,应该选择一个较小的信赖域。

信赖域方法的一个关键步骤是求解信赖区域子问题,即在给定的信赖域内找到一个改进的点。这个子问题通常是一个二次优化问题,可以使用各种数值方法来求解,如精确方法、共轭梯度方法等。

信赖域方法的优点是它可以有效地处理非线性优化问题,特别是当目标函数和约束条件都是非线性的情况。此外,它还可以处理存在噪声或者不确定性的优化问题。

jac_sparsity

jac_sparsity参数是least_squares函数的一个可选参数,用于指定雅可比矩阵的稀疏性结构。这个参数可以是一个二维数组,或者一个scipy.sparse矩阵。

如果你知道雅可比矩阵的稀疏性结构,你可以通过这个参数传入一个布尔数组,数组的形状应该是(m, n),其中m是目标函数的维度,n是模型参数的数量。数组中的元素应该是True或者False,表示对应的雅可比矩阵元素是否可能为非零。

如果你不知道雅可比矩阵的稀疏性结构,或者雅可比矩阵是密集的,你可以设置jac_sparsity=None。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, jac_sparsity=None)

在这个例子中,我们没有指定jac_sparsity参数,least_squares函数会假设雅可比矩阵是密集的。

max_nfev

max_nfev参数是least_squares函数的一个可选参数,用于指定目标函数评估的最大次数。这个参数应该是一个正整数。

如果你设置了max_nfev参数,那么least_squares函数在目标函数评估次数达到这个值时就会停止迭代,即使最优解还没有找到。

如果你不设置max_nfev参数,那么least_squares函数会根据问题的规模自动选择一个合适的值。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, max_nfev=None)

在这个例子中,我们没有指定max_nfev参数,least_squares函数会根据问题的规模自动选择一个合适的目标函数评估的最大次数。

verbose

verbose参数是least_squares函数的一个可选参数,用于控制函数的详细输出级别。这个参数应该是一个整数,可以是0、1或2。

如果设置verbose=0,那么least_squares函数不会输出任何详细信息。

如果设置verbose=1,那么least_squares函数会输出一些关键的详细信息,如每次迭代的结果。

如果设置verbose=2,那么least_squares函数会输出更多的详细信息,如每次迭代的详细过程。

例如:

from scipy.optimize import least_squares

# 定义你的fun函数和其他参数…

result = least_squares(fun, x0, verbose=0)

在这个例子中,我们设置verbose=0,表示我们不需要least_squares函数输出任何详细信息。

args

args参数是least_squares函数的一个可选参数,用于传递给目标函数的额外参数。这个参数应该是一个元组。

例如,如果你的目标函数定义如下:

def fun(x, a, b):

    return a * x + b

你可以通过args参数传入a和b的值:

from scipy.optimize import least_squares

# 定义你的初始参数x0…

result = least_squares(fun, x0, args=(a, b))

在这个例子中,我们通过args参数传入了a和b的值,这些值会被传递给fun函数。

如果你的目标函数不需要额外的参数,你可以设置args=()。

kwargs={}

kwargs={}在Python中是一个特殊的语法,用于处理传递给函数的关键字参数。kwargs是一个字典,其中键是参数名,值是传递的参数值。

这是一个使用kwargs的例子:

def greet(**kwargs):

    for key, value in kwargs.items():

        print(f"{key} : {value}")

greet(name="Alice", age=25)

物联沃分享整理
物联沃-IOTWORD物联网 » Python scipy.optimize.least_squares使用方法及参数详解

发表评论