使用Python拟合分段函数

2 投票
3 回答
2169 浏览
提问于 2025-04-17 06:32

我正在尝试用Numpy来拟合一个分段的绝对值函数。

这个数学函数是这样的:

当x小于p[1]时:y = 1 + p[0] * abs((size + x - p[1]) / size - size / 2)

当x大于等于p[1]时:y = 1 + p[0] * abs((x - p[1]) / size - size / 2)

这是我的Python函数:

fitfunc = lambda p, x: \
    x < p[1] and\
    1 + p[0] * abs((data['n1'].size + x - p[1]) / data['n1'].size - data['n1'].size / 2) or\
    1 + p[0] * abs((x - p[1]) / data['n1'].size - data['n1'].size / 2)

不过,我遇到了一个错误:

The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

但是,任何和所有的操作都会把整个列表评估为一个单一的布尔值。

更多信息:

我之前用过lambda函数来把数据拟合到正弦波,使用的代码是:

fitfunc = lambda p, x: 1 + p[0] * sin(pi * x / data['n1'].size + p[1])
errfunc = lambda p, x, y: fitfunc(p, x) - y # Distance to the target function

然后在一个循环中:

data = np.genfromtxt(dataFileName, names=('n1', 'n2'))
xAxisSeries = scipy.linspace(0., data['n1'].max(), data['n1'].size)

p0 = [489., 123.] # Initial guess for the parameters
p1, success = scipy.optimize.leastsq(errfunc, p0[:], args=(xAxisSeries, data['n2']))

#time says which points from the sine wave will be plotted
time = scipy.linspace(0., data['n1'].max(), 100)
pylab.plot(time, fitfunc(p1, time), 'r-')

我想使用lambda函数,因为优化库中的optimize.leastsq需要一个。我用的代码基本上是一样的,唯一的区别是fitfunc被更改了。

3 个回答

0

老实说,我不太明白你想用你的lambda函数做什么。可能是我这边的时间有点问题...

无论如何,请注意,any(somelist)和np.array().any()是一样的,只是叫法不同。

In [2]: a=np.ones(4)

In [3]: a
Out[3]: array([ 1.,  1.,  1.,  1.])
In [4]: a.any()
Out[4]: True

In [8]: a[1]=0

In [9]: a.all()
Out[9]: False

In [11]: somelist=["1","1","a","3"]

In [12]: any(somelist)
Out[12]: True

另外,请告诉我,你是怎么调用这个函数的?能不能多发点代码?

0

使用def和scipy.optimize.curve_fit()。

import scipy.optimize as so

def fitfunc(p, x):
    '''Define fit function'''
    if x < p[1]:
        return 1 + p[0] * abs((data['n1'].size + x - p[1]) / data['n1'].size - data['n1'].size / 2)
    else:
        return 1 + p[0] * abs((x - p[1]) / data['n1'].size - data['n1'].size / 2)

popt, pcov = so.curve_fit(fitfunc, x, y)
2

上面的代码看起来不太规范,反而让事情变得复杂了。 :)

如果你想定义一个函数并给它起个名字,通常的做法是用 def,而不是 lambda

fitfunc = lambda p, x: ...  ## you're making a named function, so just do...

def fitfunc(p, x): ...

一旦你这样做了,就不需要用 'and' 和 'or' 来模拟短路逻辑了:你可以直接使用 if。试图模拟 if 会让你遇到麻烦。

撰写回答