通过输入numpy数组无法解决optimize.curve_fit中的值错误

时间:2016-02-23 17:06:03

标签: python scipy curve-fitting

我正在尝试使用scipy.optimize.curve_fit将一些数据拟合到函数中,但是继续得到值错误,类似于this post中描述的值,但是将所有输入都按照建议的方式输入到numpy数组中评论似乎没有解决我的问题。

这是我的基本代码:

def RamanHamiltonian(k, omega, delta, epsilon):
    H = np.array([[(k+2.0)**2.0 - delta, omega/2.0, 0.0],
                  [omega/2.0, k**2.0-epsilon,omega/2.0],
                  [0.0,omega/2.0,(k-2.0)**2.0 + delta]])
    return H

def propagateHamiltonianTest(t, omega, delta, epsilon):  
    k = 0.0
    psi0 = np.array([0+1j*0.0, 1.0+1j*0.0, 0.0+1j*0.0])
    H = RamanHamiltonian(k, omega, delta ,epsilon)
    Energy, V = LA.eig(H)

    V = V + 1j*0.0
    Vinv = np.conjugate(np.transpose(V))

    U = np.diag(np.exp(-1j*np.array(Energy)*t))
    a  =np.dot(Vinv,psi0)
    b = np.dot(U,a)
    psi = np.dot(V,b)
    pop0 = np.absolute(psi[0])**2.0

    return pop0

popt, pcov = optimize.curve_fit(propagateHamiltonianTest,
                               np.array(tRecoils), 
                               np.array(frac0), 
                               p0=(3.0,0.05,0.03))

以下是tRecoilsfrac0的值,两者都是24个数组:

tRecoils = array([ 2.88597836,  1.15439135,  1.73158702,  2.19334356,  0.23087827,
    2.07790442,  0.11543913,  1.50070875,  2.77053923,  1.61614788,
    1.03895221,  2.42422183,  0.92351308,  0.80807394,  0.3463174 ,
    0.57719567,  2.6551001 ,  0.46175654,  1.84702615,  1.38526961,
    2.53966096,  0.69263481,  2.30878269,  1.96246529])
frac0 = array([ 0.15761062,  0.02044625,  0.17275937,  0.02236243,  0.07388558,
    0.00967176,  0.01886309,  0.20412516,  0.21667489,  0.21783697,
    0.00173812,  0.14038657,  0.03145599,  0.08644404,  0.13153078,
    0.18794377,  0.2139092 ,  0.17141201,  0.13021916,  0.12671806,
    0.21090369,  0.1611094 ,  0.08732627,  0.05764911])

我收到此错误:

  

U = np.diag(np.exp(-1j * np.array(Energy)* t))

     

ValueError:操作数无法与形状一起广播(3)   (24)

因此,由于某些原因,curve_fit读取整个tRecoil数组而不是按元素方式执行,我似乎无法通过更改输入格式来解决这个问题。

1 个答案:

答案 0 :(得分:0)

我认为问题在于如何评估函数propagateHamiltonianTest的模糊性。它既可以应用于t的单个值(这是你如何考虑它),也可以应用于整个数组,在这种情况下,numpy将整个数组传递给参数{{1并试图进行矢量化。

事实上,当我在你的数组t的单个元素上测试你的函数时,它可以工作,但是当你在整个数组上尝试它时,它会失败并出现相同的错误。所以这个问题与tRecoil[0]无关。如果你可以让你的函数接受整个数组,并返回一个数组,那么它应该与curve_fit一起工作。

要做到这一点,我必须使用curve_fit使用一些hacky技巧。这允许我们创建更大的块对角矩阵,其基本上具有沿对角线的每个时间步长产生的每个3×3矩阵。

您的scipy.linalg.block_diag功能的修改版本如下所示,并附有评论。我已经对它进行了测试,它应该有效。

propagateHamiltonianTest

输出:

from scipy.linalg import block_diag

def propagateHamiltonianTest(t, omega, delta, epsilon):  
    k = 0.0
    psi0 = np.array([0+1j*0.0, 1.0+1j*0.0, 0.0+1j*0.0])
    H = RamanHamiltonian(k, omega, delta ,epsilon)
    Energy, V = LA.eig(H)

    V = V + 1j*0.0
    Vinv = np.conjugate(np.transpose(V))

    # np.outer(t, Energy).flatten() creates a matrix for all t
    U = np.diag(np.exp(-1j*np.outer(t, Energy).flatten()))  
    a = np.dot(Vinv, psi0)
    # This repeats a so that the shape is consitent with U
    aa = block_diag(*([a]*t.size))                          
    # Have to add the transpose to make shapes match 
    b = np.dot(U, aa.T)                                     
    # Same block diagonal trick for eigenvector matrix
    VV = block_diag(*([V]*t.size))                          
    psi = np.dot(VV, b)
    pop0 = np.absolute(psi)**2.0                       
    # Since you want the first value, need to take every 3rd row 
    # and extract the values you want from the diagonal
    return np.diag(pop0[::3])