如何解决在python中安装自定义函数
我正在尝试使用以下函数拟合我的数据:
我使用的数据如下:
X1:
0 1.0
1 101.0
2 201.0
3 301.0
4 401.0
5 501.0
6 601.0
7 701.0
8 801.0
9 901.0
10 1001.0
11 1101.0
12 1201.0
13 1301.0
14 1401.0
15 1501.0
16 1601.0
17 1701.0
18 1801.0
19 1901.0
Y1:
0 0.121159
1 0.195525
2 0.167305
3 0.125499
4 0.094138
5 0.071610
6 0.053848
7 0.039890
8 0.031099
9 0.023976
10 0.018271
11 0.013807
12 0.010596
13 0.008033
14 0.006710
15 0.005222
16 0.004299
17 0.003376
18 0.002976
19 0.002659
def logN(X1,mu,SD1):
return A/X1 * np.exp(-0.5 * (np.log(X1/mu)**2/np.log(SD1)**2))
params,pcov = curve_fit(logN,X1,Y1) print (params)
plt.plot(X1,Y1,"o")
plt.plot(X1,logN(X1,params[0],params[1]))
plt.show()
minpack.py:829: OptimizeWarning: Covariance of the parameters Could not be estimated
category=OptimizeWarning)
解决方法
观察
您正面临多重挑战:
- 正如您所说,您的问题是非线性回归(就系数而言),可以使用非线性算法(例如 Levenberg Marquardt(在
scipy.optimize.curve_fit
中实现))来解决 - 您没有在优化过程中考虑
A
系数,但它在您的函数中明确说明(因此它采用了您的帖子中未详细说明的全局值)并且此A
系数是相关的sigma
前者合并后者。 - 您的某些数据不适合对数正态分布(
x=1
处的点似乎可疑)并且没有对y
不确定性的估计。这可能会在执行参数优化时阻止正确收敛,然后算法无法计算协方差矩阵。
改进建议:
-
可以将您的问题改写为涉及二阶多项式的经典 OLS。那么我们就不必依赖 NLLS 算法。只需将 log-log transform 应用于您的关系以确认它是可以承受的并获得参数转换公式。如果可用,总是在 NLLS 之前优先选择 OLS。
-
删除或惩罚(权重)可疑点,最好使用客观标准。
-
调整您的模型函数(此处不考虑)。
MCVE
根据您提供的数据:
import io
import numpy as np
from scipy import optimize
import pandas as pd
import matplotlib.pyplot as plt
data = io.StringIO("""id;x;y;sy
0;1.0;0.121159;1
1;101.0;0.195525;1
2;201.0;0.167305;1
3;301.0;0.125499;1
4;401.0;0.094138;1
5;501.0;0.071610;1
6;601.0;0.053848;1
7;701.0;0.039890;1
8;801.0;0.031099;1
9;901.0;0.023976;1
10;1001.0;0.018271;1
11;1101.0;0.013807;1
12;1201.0;0.010596;1
13;1301.0;0.008033;1
14;1401.0;0.006710;1
15;1501.0;0.005222;1
16;1601.0;0.004299;1
17;1701.0;0.003376;1
18;1801.0;0.002976;1
19;1901.0;0.002659;1
""")
df = pd.read_csv(data,sep=";",index_col="id")
将您的模型函数重写为:
def func(x,A,mu,sigma):
return (A/x)*np.exp(-((np.log(x/mu)/np.log(sigma))**2)/2)
修改后的签名
然后我们可以通过向优化算法提供数据和足够智能的初始条件来天真地拟合函数:
popt,pcov = optimize.curve_fit(func,df.x,df.y,sigma=df.sy,p0=(50,100,0.1),method="lm")
但结果不是很理想(未加权):
并且由于可疑点而容易发生变化(用 x=1
惩罚 w=100
):
因此,y
测量的不确定性有助于调整拟合。
无论如何,由于问题可以线性化,我们应该依赖这个属性,权重也可以在 OLS 中使用。
线性化
如果您愿意,您可以使用 scipy.optimize.least_squares
执行 OLS。我将使用非常方便的 sklearn
框架:
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
让我们删除第一个可疑点:
df = df.loc[1:,:]
然后,我们调整输入并执行对数转换:
X = np.log(df.x.values).reshape(-1,1)
y = np.log(df.y)
我们为二阶多项式创建 OLS 管道:
poly = PolynomialFeatures(2)
linreg = LinearRegression()
model = make_pipeline(poly,linreg)
最后我们根据数据调整模型:
model.fit(X,y)
model.score(X,y) # 0.9982242621455882
导致:
对于二次方来说,这似乎是一个合理的调整。然后就是将系数转换回您想要的数量。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。