2016-11-27 51 views
0

这篇文章建立在我刚才的问题曲线拟合优化SciPy的Python的numpy的

我有一些X数据和一些Y数据,Y数据可以适合作为X数据的加权和,和我的问题是找到最适合的系数。

我现在明白了一种方法,但我意识到它可能不是最好的或最佳的方式。

但是,我所拥有的X数据有时可能会发生偏移,因此只有在将X的每列向上或向下移动N个增量后才能获得最佳拟合。

我试图看看np.roll是否可以用来做到这一点,但我卡住了,因为我的函数现在需要np.roll的系数和整数值,可用于向上或向下移动列N以改善适合度。

我认为我的主要问题是不明白如何将这两种不同的参数传递给curvefit - 可能吗?

也许np.roll不是最好的方法吗?所以任何建议的另一种方式也将不胜感激。

在我下面的例子中,将第二列移动-1会使Xdata更适合Ydata。

xdata = np.array([[1.0, 1.0],[1.0, 1.0], [2.0, 3.0], [4.0, 2.0], [2.0, 1.0],[1.0, 1.0]]) 

ydata = np.array([3.0, 5.0, 6.0, 9.0, 5.0, 3.0]) 


def fitfunc(xdata, *params): 
    ctx = 0.0 

    # y is not yet defined by somehow I would like it to take the values passed in the second np.array defined in c below 
    # the for loop should just run twice in this example 

    for n in range(len(params)): 
     ctx = params[n]*np.roll(xdata[:,n], y, axis=0) + ctx 
    return ctx, y 

#initial guesses for fitting parameters 
c = (np.array([0.6, 0.3]), np.array([1, 1])) # the second np.array is what I would like to pass a y's 

# fit data using SciPy's Levenberg-Marquart method 
nlfit, nlpcov = scipy.optimize.curve_fit(fitfunc, xdata, ydata, p0=(c), sigma=None) 

print (nlfit) 

谢谢你提前为任何帮助

+0

您是否尝试使用形式为y = mx + b的线性模型,并且想要包含常数项b,从而将线路上下移动?或者,您的数据是一组时间序列,您不确定要使用哪些x变量的滞后(可能由np.roll暗示)? – David

+0

我的数据是光谱。所以Xdata数组可能是两列按列排列的光谱矩阵。从我之前关于这个主题的问题中,我相信我的Xdata可以将我的ydata描述为X * a + X * b ... etc = Ydata。我想在试图优化拟合时上下移动我的x数据列的原因是,实验性错误意味着这样的转变在实际数据中是常见的,因此,以及将Xdata的每列与系数相乘,I'希望有一些方法可以尝试Xdata列彼此间的相对转换,以找到最适合的方式。 – steve

+0

我希望澄清我希望实现的目标? np.roll只是我认为我可以实现列之间相对移动的一种方式。所涉及的光谱有几千个点,所以我的想法是,从一端向另一端滚动几个点,反之亦然,以获得更好的配合可能是实现这一目标的一种方式。 – steve

回答

0

curve_fit预计的参数,你可以,但是你想在fitfunc使用单个阵列。在这个例子中,我们有p列,每列都有一个斜率和一个移位,所以最后我们需要一个2 * p元素的参数数组。初始参数阵列需要看起来像这样:

c = np.array([0.6, 0.3, 1, 1]) 

内部fitfunc,我分裂参数数组成:

  • slope_params,斜率参数阵列,使用params[:cols],这需要第一p元素,和
  • shift_params,一个移位参数数组,使用params[cols:],它取最后的p个元素。

fitfunc全码:

def fitfunc(xdata, *params): 
    # Get number of columns in data 
    cols = xdata.shape[1] 

    # Get slope parameters 
    slope_params = params[:cols] 

    # Get shift parameters and convert to int 
    shift_params = [int(round(n)) for n in params[cols:]] 

    # Calculate fit 
    ctx = 0.0 
    for n in range(len(slope_params)): 
     ctx = slope_params[n] * np.roll(xdata[:,n], shift_params[n], axis=0) + ctx 

    # Show progress 
    print(params) 

    return ctx 

请注意,我们必须转变参数转换为整数,使用[int(round(n)) for n in params[cols:]]

使用这种与curve_fit不会改变在所有位移参数,并且给出一个警告:

(0.59999999999999998, 0.29999999999999999, 1.0, 1.0) 
(0.59999999999999998, 0.29999999999999999, 1.0, 1.0) 
(0.59999999999999998, 0.29999999999999999, 1.0, 1.0) 
(0.60000000894069672, 0.29999999999999999, 1.0, 1.0) 
(0.59999999999999998, 0.30000000447034836, 1.0, 1.0) 
(0.59999999999999998, 0.29999999999999999, 1.0000000149011612, 1.0) 
(0.59999999999999998, 0.29999999999999999, 1.0, 1.0000000149011612) 
(-0.40816307558733345, 3.6326528012731845, 1.0, 1.0) 
(-0.40816306950522968, 3.6326528012731845, 1.0, 1.0) 
(-0.40816307558733345, 3.6326528554039292, 1.0, 1.0) 
(-0.40816307558733345, 3.6326528012731845, 1.0000000149011612, 1.0) 
(-0.40816307558733345, 3.6326528012731845, 1.0, 1.0000000149011612) 
(-0.40816327556523363, 3.632653071646589, 1.0, 1.0) 
OptimizeWarning: Covariance of the parameters could not be estimated 
    category=OptimizeWarning) 
[-0.40816328 3.63265307 1.   1.  ] 

您可能能够调整优化设置,以获得更好的成绩,但我不认为这是你的问题最有前途的方法。

+0

感谢您解释如何最有用地看到这个机制,并且毫无疑问会对其他人有用,即使您认为对我来说也不会解决原始问题 – steve