将两层模型拟合到python中的wind profile数据

时间:2016-03-04 11:51:05

标签: python model-fitting

我正在尝试将模型拟合到我的风廓线数据集中,即不同海拔u(z)的风速值z

该模型由两部分组成,我现在简化为:

u(z) = ust/k * ln(z/z0)     for z < zsl

u(z) = a*z + b              for z > zsl

在对数模型中,ustz0是自由参数k是固定的。 zsl是表面层的高度,也不是先验的。

我想让这个模型适合我的数据,我已经尝试过不同的方法。到目前为止,我得到的最好结果是:

def two_layer(z,hsl,ust,z0,a,b):
    return ust/0.4*(np.log(z/z0)) if z<hsl else a*z+b

two_layer = np.vectorize(two_layer)

def two_layer_err(p,z,u):
    return two_layer(z,*p)-u

popt, pcov ,infodict, mesg, ier = optimize.leastsq(two_layer_err,[150.,0.3,0.002,0.1,10.],(wspd_hgt,prof),full_output=1)

# wspd_hgt are my measurements heights and 
# prof are the corresponding wind speed values

这为我提供了所有参数的合理估计,除了zsl,在拟合过程中没有改变。我想这与用作阈值而不是函数参数的事实有关。在优化过程中,有什么方法可以让zsl变化吗?

我用numpy.piecewise尝试了一些东西,但是效果并不好,也许是因为我不太了解它,或者我可能完全离开这里因为它不适合我的事业。

对于这个想法,如果轴反转(z绘制而不是u),风廓线看起来像这样: Wind profile plot

1 个答案:

答案 0 :(得分:1)

我认为我终于有了解决这类问题的解决方案,我在回答similar question时遇到了。

解决方案似乎是在两个模型之间的切换处实施约束BehaviorRelay。由于没有发布数据,因此我无法在您的模型上进行尝试,因此我将展示它在其他模型上的工作方式,并且您可以根据自己的情况进行调整。我使用编写的u1 == u2包装器解决了这个问题,目的是使这种问题更加符合Python规范,称为scipy。但是,如果愿意,您可以使用symfit中的SLSQP算法来做同样的事情。

scipy

enter image description here

我认为您应该能够使此示例适应您的情况!

编辑:根据注释中的要求,也可以要求匹配的派生词。为此,上面的示例需要以下附加代码:

from symfit import parameters, variables, Fit, Piecewise, exp, Eq
import numpy as np
import matplotlib.pyplot as plt

t, y = variables('t, y')
m, c, d, k, t0 = parameters('m, c, d, k, t0')

# Help the fit by bounding the switchpoint between the models
t0.min = 0.6
t0.max = 0.9

# Make a piecewise model
y1 = m * t + c
y2 = d * exp(- k * t)
model = {y: Piecewise((y1, t <= t0), (y2, t > t0))}

# As a constraint, we demand equality between the two models at the point t0
# Substitutes t in the components by t0
constraints = [Eq(y1.subs({t: t0}), y2.subs({t: t0}))]

# Read the data
tdata, ydata = np.genfromtxt('Experimental Data.csv', delimiter=',', skip_header=1).T

fit = Fit(model, t=tdata, y=ydata, constraints=constraints)
fit_result = fit.execute()
print(fit_result)

plt.scatter(tdata, ydata)
plt.plot(tdata, fit.model(t=tdata, **fit_result.params).y)
plt.show()

这应该可以解决问题!因此,从编程的角度来看,这是非常可行的,尽管实际上取决于模型,实际上可能没有解决方案。