我有X和Y数据(7,360,720)维度(全局网格单元格,0.5分辨率)作为输入数据,我想用下面的代码拟合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()
现在这段代码写入和疼痛拟合导致.csv文件中有3列(a,b,c),但是我希望在文件中写入并存储拟合结果,其中(360,720)形状为网格单元格。此代码也显示以下错误: RuntimeError:找不到最佳参数:函数调用次数已达到maxfev = 800。
答案 0 :(得分:0)
您的数据的维度(在问题的标题中引用)不是您所看到的问题的原因。你要做的是对你的S形函数运行360 * 720(~260,000)单独拟合,输入来自你的数组x
和y
。它应该可以工作,但它可能很慢,因为你做了很多适合。
如果你还没有,那么你一定要先将几个阵列安装到你的功能中 - 如果你不能让3个工作,那么尝试260,000没有意义,对吧?所以,从1开始,然后尝试3,然后是360,然后是所有这些。
我怀疑你看到的问题是因为curve_fit()
愚蠢地允许你不明确指定参数的起始值,甚至更愚蠢地将未指定的起始值分配给任意这鼓励新用户不要更仔细地考虑他们试图解决的问题,然后给出一些神秘的错误信息,比如你看到的那些没有明确说出的问题"你需要更好的起始值" 。消息说,适合需要多次迭代,这可能意味着适合"迷失了#34;试图找到最佳价值。那"迷路"可能是因为它开始了#34;远离家乡"。
通常,曲线拟合对参数的起始值敏感。你可能知道起始值比a=1, b=1, c=1
更好。我怀疑你也知道取幂可以很快变得巨大或微小。因此,根据x
的比例,c
的值可能不是真正合理的范围 - 可能c
应为正数,并且例如,小于10。同样,您可能会对这些范围有所了解。
我建议您使用lmfit
(https://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
将为您提供更好的工具来避免和识别这些案例。