繁体   English   中英

Python中3维数据的曲线拟合

[英]Curve Fitting For 3 dimensional data in python

我将(7,360,720)维(具有0.5分辨率的全局网格单元)的X和Y数据作为输入数据,并且我想用以下代码拟合Sigmoid曲线,并获得与X和Y形状相同的曲线参数:

# -*- coding: utf-8 -*-
import  os, sys
from    collections import OrderedDict  as odict
import  numpy   as np
import  pylab   as pl
import numpy.ma as ma
from scipy.optimize import curve_fit


f=open('test.csv','w')
def sigmoid(x,a,b, c):
        y = a+(b*(1 - np.exp(-c*(x**2))))
        return y
for i in range(360):
      for j in range(720):
        xdata=[0,x[0,i,j],x[1,i,j],x[2,i,j],x[3,i,j],x[4,i,j],x[5,i,j],x[6,i,j]] 
        ydata=[0,y[0,i,j],y[1,i,j],y[2,i,j],y[3,i,j],y[4,i,j],y[5,i,j],y[6,i,j]]
        popt, pcov = curve_fit(sigmoid, xdata, ydata)
        print popt
        f.write(','.join(map(str,popt)))
        f.write("\n")
f.close()

现在,此代码在3列(a,b,c)的.csv文件中写入并拟合拟合结果,但是我想在(360,720)形状的文件中将拟合结果写入并存储为网格单元。 此代码还会向我显示以下错误:RuntimeError:找不到最佳参数:函数的调用次数已达到maxfev = 800。

数据的维数(在问题的标题中引用)不是造成问题的原因。 您想做的是运行360 * 720(〜260,000)的S型函数,并使用从数组xy派生的输入。 它应该可以工作,但是它可能会很慢,因为您正在做很多事情。

如果还没有,那么绝对应该从为函数拟合几个数组开始-如果无法使3个起作用,那么尝试260,000没有意义,对吧? 因此,从1开始,然后尝试3,然后是360,然后是所有。

我怀疑您看到的问题是因为curve_fit()愚蠢地允许您显式指定参数的起始值,并且更愚蠢地将未指定的起始值分配给任意值1。这鼓励新用户不要再考虑更多仔细考虑他们要解决的问题,然后给出类似您看到的隐式错误消息,但不会明确指出“您需要更好的起始值”。 该消息说,拟合进行了多次迭代,这可能意味着拟合试图找到最佳值“迷失了”。 这种“迷路”可能是因为它“离家太远了”。

通常,曲线拟合对参数的起始值敏感。 而且您可能确实知道比a=1, b=1, c=1更好的起始值。 我怀疑您也知道幂运算可以很快变得很大或很小。 因此,取决于您的x的比例, c的值范围可能并不十分合理-例如, c可能为正,并且小于10。 同样,您可能有点了解这些范围。

让我建议使用lmfithttps://lmfit.github.io/lmfit-py/ )进行这项工作。 它提供了一种曲线拟合的替代方法, curve_fit了许多有用的改进。 对于您的问题,单次拟合可能如下所示:

import numpy as np
from lmfit import Model

def sigmoid(x, offset, scale, decay):
    return offset + scale*(1 - np.exp(-decay*(x**2)))

## set up the model and parameters from your model function
# note that parameters will be *named* using the names of the
# arguments to your model function.
model = Model(sigmoid)
# make parameters (OrderedDict-like) with initial values
params = model.make_params(offset=0, scale=1, decay=0.25) 

# you may want to set bounds on some of the parameters
params['scale'].min = 0
params['decay'].min = 0
params['decay'].max = 5

# you can also fix some parameters if desired
# params['offset'].vary = False 

## set up data
# pick arbitrary data to fit, and make sure data use np arrays.
# but also: (0, 0) isn't in your data -- do you need to assert it?
# won't that drive `offset` to 0?
i, j = 7, 12
xdata = np.array([0] + x[:, i, j])
ydata = np.array([0] + y[:, i, j])

# now fit model to data, get results
result = model.fit(params, ydata, x=xdata)

print(result.fit_report())

这将打印出具有拟合统计信息,最拟合参数值和不确定性的报告。 您可以阅读文档,了解results所有组成部分,但results.params包含最适合的参数和不确定性。

对于循环使用,此方法具有便利的功能,即每个数据集的result都是唯一的,而起始params不会因拟合而改变,并且可以重新用作所有拟合的起始值。 一个测试循环可能看起来像

results = []
for i in (50, 150, 250):
    for j in (200, 400, 600):
        xdata = np.array([0] + x[:, i, j])
        ydata = np.array([0] + y[:, i, j])

        result = model.fit(params, ydata, x=xdata)
        results.append([i, j, result.params, result.chisqr])

仍然有可能无法成功完成260,000个拟合中的某些拟合,但我认为lmfit将为您提供更好的工具来避免和识别这些情况。

暂无
暂无

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

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