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 只是一个整数,xy 是整数,除非你传递一个数组数组。 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&gt;0 并将a 定义为与c 相同的大小。现在你得到了正确的插入,因为np.where 的第一个参数现在与第二个和第三个参数的大小相同。在(x&lt;a) &amp; (y&gt;0) 之前,总是评估为TrueFalse,在这种情况下这是一个标量。如果 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 曲线拟合(优化) - 使用自定义函数对条件进行矢量化以识别阈值的主要内容,如果未能解决你的问题,请参考以下文章

利用Python的scipy包实现曲线的拟合

通过更改python中的模型函数进行通用曲线拟合

python numpy/scipy曲线拟合

python 拟合曲线并求参

使用带有大数据集的SciPy曲线拟合库的RuntimeError

python数据挖掘课程十四.Scipy调用curve_fit实现曲线拟合