Scipy 曲线拟合(优化) - 使用自定义函数对条件进行矢量化以识别阈值
Posted
技术标签:
【中文标题】Scipy 曲线拟合(优化) - 使用自定义函数对条件进行矢量化以识别阈值【英文标题】:Scipy curve fit (optimization) - vectorizing a conditional to identify threshold using a custom function 【发布时间】:2021-07-19 10:51:17 【问题描述】:我正在尝试使用scipy curve_fit
来捕获a0
参数的值。到目前为止,它没有改变(总是显示为 1):
X = [[1,2,3],[4,5,6]]
def func(X, a0, c):
x1 = X[0]; x2 = X[1]
a = x1*x2
result = np.where(a(a<a0), -c*(a + np.sqrt(x2)), -c*x1)
return result
Popt, Cov = scipy.curve_fit(func, X, y)
a0, c = Popt
Predicted = func(X, a0, c) # a0 and c are constants
我得到了 c 的值,它是一个标量,没有任何问题。我无法解释为什么 a0
(也是一个标量)总是 1,我不知道如何解决它。我确实在 SO 上看到了elsewhere,np.where
可以按照我在这里使用的方式使用,但显然不适用于 curve_fit 函数。也许我需要使用不同的优化方法,我想要一些使用 scipy 方法的指针。
编辑:我尝试了 Brad 建议的结构,但不是这样。
【问题讨论】:
如果我理解正确,np.where
的第一个参数应该是一个布尔数组,它是您想要插入的数组的大小。从你的 sn-p 中不清楚,但我假设 a
只是一个整数,x
和 y
是整数,除非你传递一个数组数组。 c
也没有定义,所以我不得不猜测它是之前定义的常量,但这是你想要更改的实际数组。
我对这个问题比以前更加困惑。 curve_fit 适用于连续函数,但据我所知,您定义的函数不是连续的。您似乎正在尝试定义搜索功能。此外,作为曲线拟合优化的旁注,您需要提供 y
数组是什么。也许您可以列出您要解决的潜在问题,以便更容易理解。
当您执行 Popt, Cov = scipy.curve_fit(func, X, y)
时,您的代码中 y
的值是多少?另外,我发现你有那个外部y
有点令人困惑,但是在你的func
内部,你从X
的第二行创建另一个y
。这两个y
有什么关联吗?
我已将函数内部的 y 名称更改为 x2,函数内部的 x 现在是 x1。参数中的 y 是目标变量,可以是任何东西,我正在编造它,比如 y = [3, 5, 7]。
【参考方案1】:
更新了!
这应该可行。请注意,a
变量在此示例中是长度为 3 的向量,因为它是通过 X
的第一个和第二个元素的元素乘法计算得出的,X
是一个 2x3 矩阵。因此a0
可以是标量或长度为 3 的向量,c
也可以是标量或长度为 3 的向量。
import numpy as np
X = np.array([[1, 2, 3], [4, 5, 6]])
a0 = np.array([8,25,400])
# a0 = 2
# Code works whether C is scalar or a matrix since it can be broadcast to matrix a below.
# c = 3 # Uncomment this for scalar
c = np.array([8, 12, 2000]) # Element wise
def func(X, a0, c):
x = X[0]
y = X[1]
a = x * y
print(a.shape)
result = np.where(a < a0, c * (a + np.sqrt(y)), c * x)
return result
func(X, a0, c)
这是有效的最少代码量。请注意,我删除了y>0
并将a
定义为与c
相同的大小。现在你得到了正确的插入,因为np.where
的第一个参数现在与第二个和第三个参数的大小相同。在(x<a) & (y>0)
之前,总是评估为True
或False
,在这种情况下这是一个标量。如果 a
是一个 N 维数组,您将收到 ValueError
,因为操作数不能一起广播
import numpy as np
c = np.array([[22,34],[33,480]])
def func(X, a):
x = X[0]; y = X[1]
return np.where(c[(x<a)], -c*(a + np.sqrt(y)), -c*x)
X = [25, 600]
a = np.array([[2,14],[33,22]])
func(X,a)
如果c
是一个常量并且a
是您想要操作的数组,这也有效
import numpy as np
c = 2
def func(X, a):
x = X[0]; y = X[1]
return np.where(a[(x<a)], -c*(a + np.sqrt(y)), -c*x)
X = [25, 600]
a = np.array([[2,14],[33,22]])
func(X,a)
【讨论】:
非常感谢,布拉德。不幸的是,这不起作用。我澄清了 c 是什么并编辑了问题以使其更清楚。我感兴趣的参数是 a0,它始终以常量 (1) 的形式出现。 @SolomonVimal 我仍然不知道上面的c
是什么。是标量还是矩阵/数组?
c 是一个标量,我也会在主要问题中指定它。
我们如何将广播 a0 传递给曲线拟合函数?我的理解是curve_fit需要三个必填参数:curve_fit(func, X, y),但是func的参数没有显式传入?
函数签名是什么样的?它是您编写的自定义函数还是另一个包的一部分?或者您是否正在尝试优化刚刚创建的功能?在这种情况下,我很困惑在这种情况下优化意味着什么。以上是关于Scipy 曲线拟合(优化) - 使用自定义函数对条件进行矢量化以识别阈值的主要内容,如果未能解决你的问题,请参考以下文章