簡體   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