Scipy 最小二乘位置参数问题

Scipy least squares positional argument issue

我正在尝试对以下数据进行稳健的非线性拟合:

r_fast:

[0.2065 0.2661 0.2026 0.22   0.2065 0.2661 0.264  0.2173 0.2615 0.2682
 0.407  0.4085 0.409  0.4045 0.405  0.3985 0.5235 0.5846 0.5171 0.5385
 0.6415 0.7661 0.699  0.6523 0.7745 0.7332 0.842  0.9085 0.909  0.8445
 0.84   0.8635]

a_fast:

[-43.3  -3.  -86.8 -10.5 -56.2  -2.5  -7.2 -12.2  -4.6  -9.  -21.3  -2.
  -3.2  -2.7  -5.8  -6.8 -15.5  -1.8 -22.1  -0.5  -8.7  -0.8   0.   -3.3
  -0.8  -0.8 -12.5  -0.5  -0.7   0.3  -1.   -1.2]

我尝试了以下方法。但是,我在这一行收到错误消息:

res_soft_l1 = least_squares(f, x, loss='soft_l1', f_scale=0.1, args=(r_fast, a_fast))

错误是:

f() missing 1 required positional argument: 'x2'

所有代码如下:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import least_squares
def f(r_fast, x0, x1, x2):
    return x[0] + r_fast**x[1] * x[2]
data= pd.read_table('/Users/Hrihaan/Desktop/Data.txt', dtype=float, header=None, sep='\s+').values
r_fast=data[:,1]
a_fast=data[:,2]
r_min=np.min(r_fast)
r_max=np.max(r_fast)
x = np.array([1.0, 1.0, 0.0])
rr= np.linspace(r_min, r_max, len(r_fast))
res_soft_l1 = least_squares(f, x, loss='soft_l1', f_scale=0.1, args=(r_fast, a_fast))
aa= f(rr, *res_soft_l1.x)
plt.xlabel('r_fast', fontsize=30)
plt.ylabel('a_fast', fontsize=30)
plt.scatter(r_fast, a_fast, c='burlywood', s=10**2)
plt.plot(rr, aa, linewidth=3, label='Power law fit')
plt.legend(fontsize=25, loc=8, framealpha=1.0, edgecolor='maroon') 
plt.show()

我不知道我错过了什么。任何帮助将不胜感激。提前致谢。

这是因为 x 需要 4 个参数,但只接收 3 个。 在行 least_squares(f, x, loss='soft_l1', f_scale=0.1, args=(r_fast, a_fast)) 中,least_squares 使用以下参数调用 f

f(r_fast=x, x0=r_fast, x1=a_fast, x2=)

如您所见,缺少 x2。无论如何,其中 none 会有所帮助,因为您的函数 f 不使用 x0x1x2

您可以将函数定义更改为:

def f(x, r_fast):
    return x[0] + r_fast**x[1] * x[2]

least_squares打电话给

least_squares(f, x, loss='soft_l1', f_scale=0.1, args=(r_fast))

代码几乎没有问题。

  1. 函数必须return "residuals",即预测值和实际值 (y) 之间的误差,而不是预测值。我猜 a_fast 是你的实际值。
  2. 要优化的参数必须始终是函数的第一个参数。在这种情况下 [x0、x1 和 x2]
  3. 函数的任何其他附加参数都应作为 args 传递给 least_squares 函数。我相信 "r_fast" 是您的附加参数。

以下代码是可以运行的最少代码。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import least_squares

r_fast = np.array([0.2065 ,0.2661,0.2026,0.22,0.2065,0.2661,0.264,0.2173,0.2615,0.2682
,0.407,0.4085,0.409,0.4045,0.405,0.3985,0.5235,0.5846,0.5171,0.5385
,0.6415,0.7661,0.699,0.6523,0.7745,0.7332,0.842,0.9085,0.909,0.8445
,0.84,0.8635])
a_fast = np.array([-43.3 , -3. , -86.8 ,-10.5 ,-56.2,  -2.5 , -7.2 ,-12.2,  -4.6  ,-9., -21.3  ,-2  , -3.2,  -2.7 , -5.8 , -6.8 ,-15.5 , -1.8, -22.1 , -0.5 , -8.7,  -0.8,   0. ,  -3.3 ,  -0.8,  -0.8, -12.5,  -0.5,  -0.7,   0.3 , -1. ,  -1.2])

def f(X ,r_fast):
    x0 ,x1 ,x2 = X
    return x0 + r_fast**x1 * x2 -a_fast



x_init = np.array([1.0, 1.0, 0.0])

res_soft_l1 = least_squares(f, x_init, args= ([r_fast]) ,loss='soft_l1', f_scale=0.1)

输出:

res_soft_l1.x

array([-5.43168803e+03,  1.31665146e-03,  5.43206946e+03])