【问题标题】:issue with numpy arrays while curve fitting with scipy.optimize使用 scipy.optimize 进行曲线拟合时出现 numpy 数组的问题
【发布时间】:2019-08-16 13:14:37
【问题描述】:

我正在尝试拟合余弦曲线,但我收到关于数组形状的错误。仅当我将 np.cos(phi - delta) 更改为 np.cos(2*phi - delta) 时才会出现该错误。

from scipy.optimize import fmin
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import numpy as np
import math
axes = plt.gca()
axes.set_ylim([-5,0])
#bond CHARMM
def func(phi, kphi, delta):
     return kphi * (1 + np.cos(2*phi - delta))



class Dihedral:  
    def __init__(self):
        self.masses = {'H': 1, 'D': 2, 'C': 12, 'O': 16} 

    def Dihedral_fit (self,x,y):

        self.popt, pcov = curve_fit(func, x, y, p0 =(0,2.3),method='trf')
        print "Cosine fit"
        print  self.popt

        plt.plot(xdata, ydata, 'b-', label='data')

        diff=sum(abs(func(x,self.popt[0],self.popt[1])-y))/len(x)
        print "AAE is"
        print diff
        plt.plot(xdata, func(xdata, *self.popt), 'r-',label='Cos: kphi=%5.3f, delta=%5.3f' % tuple(self.popt))



if __name__ == "__main__":
    xdata = [0,15,30,45,60,75,90,105]
    ydata = [-4.24,-3.82,-3.08,-2.07,-1.04,-0.30,0,-30]
    x = np.array(xdata)
    y = np.array(ydata) 
    Harm=Dihedral()
    Harm.Dihedral_fit(x,y)

    plt.legend()
    plt.show()

任何帮助将不胜感激

【问题讨论】:

  • 您应该显示错误。其他人在没有它的情况下发现了问题,但完整的错误会使问题对我们其他人更加明显。

标签: python numpy curve-fitting


【解决方案1】:

问题出在Dihedral_fit 的最后一行。您将列表作为第一个参数传递给func,正如 Yaroslav 指出的那样,将列表与常数相乘会产生一个列表,该列表是原始列表的重复。所以将xdatax 交换,这是一个numpy 数组,代码应该按预期运行。然而,该模型并不能很好地描述您的数据。您应该为振荡周期添加一个拟合参数。

编辑:

当允许调整周期时,我得到了很好的结果(省略了最后一点,这似乎是一个异常值)。

但拟合的成功在很大程度上(一如既往)取决于良好的初始猜测。

这是修改后的代码:

from scipy.optimize import fmin
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import numpy as np
import math
axes = plt.gca()
axes.set_ylim([-5,0])
#bond CHARMM
def func(phi, kphi, om, delta):
     return kphi * (1 + np.cos(om*phi - delta))



class Dihedral:  
    def __init__(self):
        self.masses = {'H': 1, 'D': 2, 'C': 12, 'O': 16} 

    def Dihedral_fit (self,x,y):
        self.popt, pcov = curve_fit(func, x, y, p0=(-3,.03,0), method='trf')
        print "Cosine fit"
        print  self.popt

        plt.plot(x, y, 'bo', label='data')

        diff=sum(abs(func(x,*self.popt)-y))/len(x)
        print "AAE is"
        print diff
        plt.plot(x, func(x, *self.popt), 'r-',label='Cos: kphi=%5.3f, delta=%5.3f, om=%5.3f' % tuple(self.popt))


if __name__ == "__main__":
    xdata = [0,15,30,45,60,75,90]
    ydata = [-4.24,-3.82,-3.08,-2.07,-1.04,-0.30,0]
    x = np.array(xdata)
    y = np.array(ydata) 
    Harm=Dihedral()
    Harm.Dihedral_fit(x,y)

    plt.legend()
    plt.show()

【讨论】:

  • 2* 是一个数学运算,我没有尝试扩展列表,......问题是python没有使用math.cos的cos函数也破坏了代码所以我只是尝试了现在我看到的 np.cos 正在做其他事情
  • 列表乘以 2 的结果并不取决于您使用的是math.cos 还是np.cos。只有将np.array 乘以一个因子,您才会得到您所期望的,正如您所说:数学运算。
  • 您能分享您使用的代码吗?得到这个情节?
【解决方案2】:

您将列表乘以 2:

xdata = [0,15,30,45,60,75,90,105]
res = 2*xdata

等等

res = [0, 15, 30, 45, 60, 75, 90, 105, 0, 15, 30, 45, 60, 75, 90, 105]

要么重新编写代码,要么使用 pandas:

import pandas as pd

...

#xdata = [0,15,30,45,60,75,90,105]
xdata = pd.Series([0,15,30,45,60,75,90,105])

【讨论】:

    猜你喜欢
    • 2016-08-20
    • 2016-06-15
    • 2018-11-04
    • 2012-04-25
    • 1970-01-01
    • 2017-02-26
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    相关资源
    最近更新 更多