Python 多次迭代scipy';s‘曲线拟合’一气呵成
考虑以下MWEPython 多次迭代scipy';s‘曲线拟合’一气呵成,python,numpy,scipy,Python,Numpy,Scipy,考虑以下MWE import numpy as np from scipy.optimize import curve_fit X=np.arange(1,10,1) Y=abs(X+np.random.randn(15,9)) def linear(x, a, b): return (x/b)**a coeffs=[] for ix in range(Y.shape[0]): print(ix) c0, pcov = curve_fit(linear, X, Y[i
import numpy as np
from scipy.optimize import curve_fit
X=np.arange(1,10,1)
Y=abs(X+np.random.randn(15,9))
def linear(x, a, b):
return (x/b)**a
coeffs=[]
for ix in range(Y.shape[0]):
print(ix)
c0, pcov = curve_fit(linear, X, Y[ix])
coeffs.append(c0)
XX=np.tile(X, Y.shape[0])
c0, pcov = curve_fit(linear, XX, Y.flatten())
我有一个问题,基本上我必须这样做,但不是15次迭代,而是数千次,而且速度相当慢
使用curve\u fit
,是否有任何方法可以一次完成所有这些迭代?我知道函数的结果应该是1D数组,所以只需像这样传递参数
c0, pcov = curve_fit(nlinear, X, Y)
这是行不通的。另外,我认为答案必须是展平Y
,这样我可以得到一个展平的结果,但我就是什么都做不到
编辑
我知道如果我这样做
XX=np.tile(X, Y.shape[0])
c0, pcov = curve_fit(nlinear, XX, Y.flatten())
然后我得到系数的“平均”值,但这不是我想要的
编辑2
为了记录在案,我使用Jacques Kvam的设置解决了这个问题,但使用Numpy实现(因为有一个限制)
然后m
是a
,得到b
:
b=np.exp(-c/m)
最小二乘法不会给出相同的结果,因为在这种情况下,噪声是通过对数变换的。如果噪声为零,两种方法给出相同的结果
import numpy as np
from numpy import random as rng
from scipy.optimize import curve_fit
rng.seed(0)
X=np.arange(1,7)
Y = np.zeros((4, 6))
for i in range(4):
b = a = i + 1
Y[i] = (X/b)**a + 0.01 * randn(6)
def linear(x, a, b):
return (x/b)**a
coeffs=[]
for ix in range(Y.shape[0]):
print(ix)
c0, pcov = curve_fit(linear, X, Y[ix])
coeffs.append(c0)
coefs
[array([ 0.99309127, 0.98742861]),
array([ 2.00197613, 2.00082722]),
array([ 2.99130237, 2.99390585]),
array([ 3.99644048, 3.9992937 ])]
我将使用scikit learn的线性回归实现,因为我相信它可以很好地伸缩
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
获取X
和Y
lX = np.log(X)[None, :]
lY = np.log(Y)
现在拟合并检查系数是否与之前相同
lr.fit(lX.T, lY.T)
lr.coef_
这给出了相似的指数
array([ 0.98613517, 1.98643974, 2.96602892, 4.01718514])
现在检查除数
np.exp(-lr.intercept_ / lr.coef_.ravel())
这给出了相似的系数,你可以看到这些方法在答案上有所不同
array([ 0.99199406, 1.98234916, 2.90677142, 3.73416501])
(显然命名错误)函数
是线性的
是您想要拟合的实际函数,还是更复杂函数的简化?@WarrenWeckesser这是实际函数。(是的,关于名字,我想做一个线性的例子,但在最后一分钟改变了,我的错!)好的,谢谢。还有一个迂腐的问题:在您的示例中,您通过将使用randn()
创建的噪波添加到X
来创建Y
。这意味着Y
可能有负值。你的真实数据会有负值吗?另外,真实的Y
是否包含0?我撒谎了——还有一个问题(但这实际上是前一个问题的一部分):在真实数据中,X
是否包含0?是否可以使用日志和线性最小二乘法?您也可以使用scipy.linalg.lstsq
或numpy.linalg.lstsq
。将噪声加回去,并将使用日志计算的结果与曲线拟合产生的结果进行比较。在某些情况下,你会发现它们完全不同。使用线性回归拟合日志可以有效地为低x值的数据加权,而不是为高x值的数据加权。[很抱歉向您发送垃圾邮件!]我不是说对x和y的日志使用线性最小二乘法是错误的,但通常不会,给出与曲线拟合相同的结果。是的,我去掉了噪音,得到了相同的答案:)因为他说,取对数并使用最小二乘法是很好的。不过,指出这一点很好。@WarrenWeckesser和JacquesKvam我已经使用这个解决方案好几个星期了,效果非常好!然而,出现了一个类似的问题,这个解决方案不起作用。您可能还对这个新问题感兴趣,您可以查看!在这个新的例子中,我试图拟合的函数是不连续的,所以它使它变得更难。干杯
array([ 0.99199406, 1.98234916, 2.90677142, 3.73416501])