简体   繁体   English

将3D数据数组拟合到具有numpy或scipy的1D函数

[英]Fitting a 3D array of data to a 1D function with numpy or scipy

4I am currently trying to fit a lot of data to a sine function. 4我目前正在尝试将大量数据用于正弦函数。 In the case where I only have one set of data (1D array), scipy.optimize.curve_fit() works fine. 在我只有一组数据(1D数组)的情况下, scipy.optimize.curve_fit()工作正常。 However it does not permit a higher dimensional data input if the function itself is only one dimensional as far as i can see. 然而,如果函数本身只是我所能看到的一维,它不允许更高维数据输入。 I don't want to iterate over the array using for loops as that works incredibly slow in python. 我不想使用for循环迭代数组,因为它在python中工作得非常慢。

My code so far should look similar to this: 到目前为止我的代码看起来应该类似于:

from scipy import optimize
import numpy as np    
def f(x,p1,p2,p3,p4): return p1 + p2*np.sin(2*np.pi*p3*x + p4)      #fit function

def fit(data,guess):
   n = data.shape[0] 
   leng = np.arange(n)
   param, pcov = optimize.curve_fit(f,leng,data,guess)
   return param, pcov

where data is a threedimensional array ( shape=(x,y,z) ) and I would like to fit each line data[:,a,b] to the function with param being a (4,y,z) shaped array as output. 其中数据是三维数组( shape=(x,y,z) ),我想将每个行data[:,a,b]拟合到函数,其中param(4,y,z)形状的数组输出。 Of course, for multidimensional data this results in a 当然,对于多维数据,这导致a

ValueError: operands could not be broadcast together with shapes (2100,2100) (5)

Maybe there is an easy solution to this but I am not sure how to do it. 也许有一个简单的解决方案,但我不知道该怎么做。 Any suggestions? 有什么建议?

Searching for an answer to my question proofed quite difficult since most topics with those keywords relate to the fitting of higher dimensional functions. 搜索我的问题的答案证明非常困难,因为这些关键字的大多数主题与更高维度函数的拟合有关。

Using np.apply_along_axis() solves your problem. 使用np.apply_along_axis()可以解决您的问题。 Just do this: 这样做:

func1d = lambda y, *args: optimize.curve_fit(f, xdata=x, ydata=y, *args)[0] #<-- [0] to get only popt
param = np.apply_along_axis( func1d, axis=2, arr=data )

See the example below: 请参阅以下示例:

from scipy import optimize
import numpy as np
def f(x,p1,p2,p3,p4):
    return p1 + p2*np.sin(2*np.pi*p3*x + p4)
sx = 50  # size x
sy = 200 # size y
sz = 100 # size z
# creating the reference parameters
tmp = np.empty((4,sy,sz))
tmp[0,:,:] = (1.2-0.8) * np.random.random_sample((sy,sz)) + 0.8
tmp[1,:,:] = (1.2-0.8) * np.random.random_sample((sy,sz)) + 0.8
tmp[2,:,:] = np.ones((sy,sz))
tmp[3,:,:] = np.ones((sy,sz))*np.pi/4
param_ref = np.empty((4,sy,sz,sx))     # param_ref in this shape will allow an
for i in range(sx):                    # one-shot evaluation of f() to create 
    param_ref[:,:,:,i] = tmp           # the data sample
# creating the data sample
x = np.linspace(0,2*np.pi)
factor = (1.1-0.9)*np.random.random_sample((sy,sz,sx))+0.9
data = f(x, *param_ref) * factor       # the one-shot evalution is here
# finding the adjusted parameters
func1d = lambda y, *args: optimize.curve_fit(f, xdata=x, ydata=y, *args)[0] #<-- [0] to get only popt
param = np.apply_along_axis( func1d, axis=2, arr=data )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM