首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将pygam模型转换为SciPy BSpline

如何将pygam模型转换为SciPy BSpline
EN

Stack Overflow用户
提问于 2020-11-19 01:10:08
回答 2查看 129关注 0票数 1

我想在两个世界中取长补短: Scipy和pygam。具体地说,我想使用自定义的pygam惩罚函数惩罚我的数据的三阶导数,然后我想使用结果作为Scipy BSpline。后者允许容易地计算数据的n阶导数。当然,gam.coef_给了我模型的系数,但是结点是什么呢?如果使用gam.terms.get_coef_indices()-1来接近,但结果实际上应该与gam.predict(x)相同,即

在ev-br的有用评论之后,我们现在知道我们可以通过pygam.utils.get_knot_edges获得结边。因此,一段有希望的代码将是

代码语言:javascript
复制
plt.figure()
res0=pygam.LinearGAM(terms=pygam.terms.s(0),n_splines=len(x),penalties=MyPenalty,lam=0.3,fit_intercept=False, basis='ps').fit(x,y,1/np.sqrt(w))
plt.plot(x,y,'x',zorder=10, label='data')
knot_edges=utils.gen_edge_knots(x,dtype='numerical')
knots=np.linspace(knot_edges[0],knot_edges[-1],len(res0.coef_))
plt.plot(x,res0.predict(x), label='PyGAM fit')
plt.plot(x,scipy.interpolate.BSpline(knots,res0.coef_,3)(x), label='BSpline from PyGAM parameters')
   
    
plt.legend()

遗憾的是,输出结果并不令人满意:

EN

回答 2

Stack Overflow用户

发布于 2020-11-19 02:42:08

根据https://github.com/dswah/pyGAM/issues/265的说法,pyfam适合统一的结。可以通过pygam.utils.gen_edge_knots提取第一个和最后一个结的位置。

票数 0
EN

Stack Overflow用户

发布于 2021-10-28 08:41:00

不幸的是,B样条方法没有标准化(我在过去的40年里开发了五种不同的B样条拟合算法,没有一种算法与其他算法兼容!),仔细检查pygam和scipy的结果表明,不幸的是不兼容。首先,节点要么被移动和缩放(scipy splprep),要么没有(pygam),第二,由于不同的计算方法,B样条坐标和系数是不兼容的。尽管它们之间的转换可能是可能的,但这可能会被证明是几乎难以处理的。

另一点是,如果你想使用平滑,splprep提供了这一点(同意,它可能不像pygam方法那样容易和优雅)。

这里是一种方法(使用数值微分),与一组树木生长数据的spldev导数相比,该方法可能适用于pygam。

代码语言:javascript
复制
import numpy as np
import scipy
from scipy.interpolate import interp1d, splprep, splev
from scipy.sparse import csr_matrix
import matplotlib.pyplot as plt
import pandas as pd
import math

from pygam import LinearGAM, s, f, utils
import pygam as pygam

X = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]

Y = [5,5,5.045,5.234,5.369,5.558,5.693,
     5.819,5.864,5.882,5.882,5.882,5.882,
     5.882,5.906,6.074,6.398,6.674,6.842,
     6.998,7.07,7.082,7.082,7.082
    ]


plt.figure()
# Plot data
plt.plot(X,Y,'x',zorder=10, label='data')

# First, pygam
GAM=pygam.LinearGAM(terms=pygam.terms.s(0),n_splines=len(X),
                     lam=0.3,fit_intercept=False,
                     basis='ps').fit(X,Y)

knot_edges=utils.gen_edge_knots(X,dtype='numerical')
knots=np.linspace(knot_edges[0],knot_edges[-1],len(GAM.coef_))
print('GAM Knots')
print(knots)
coeffs = GAM.coef_
print('GAM Coefficients')
print(coeffs)
GAMY = GAM.predict(X)
plt.plot(X,GAMY, label='PyGAM fit')
print('GAMY fit')
print(GAMY)

# Second, splprep
tck, u = splprep([X,Y],s=0) # force interpolation by s=0
# where t = knots (scaled 0 to 1)
#       c = coefficients
#       k = degree of spline (default = 3)
#       u = An array of the values of the parameter.
new_points = splev(u,tck, der=0)
plt.plot(new_points[0], new_points[1], '.', color='k', label='splprep fit')
print('tck')
print(tck)
print('u')
print(u)

#Ynew = scipy.interpolate.BSpline(knots,res0.coef_,3)
#plt.plot(X,Ynew)
         #(X,label='BSpline from PyGAM parameters'))
   
plt.legend()
plt.show()

# Derivatives, splev
dev_points_x, dev_points_y = splev(u, tck, der=1) # first derivative
plt.plot(u*23+1, dev_points_y/23, '--ro', label='splev derivative')
#u and y must be scaled and shifted

# Deriv, GAM (by numerical difference method)
XX = GAM.generate_X_grid(term=0, n=200)
#now do derivative(s)
Yprime = np.zeros(200) ## Y prime
GAMY = GAM.predict(XX) # fitted Y on XX
for i in range(1,len(Yprime)-1):
    Yprime[i] = (GAMY[i+1] - GAMY[i-1])/(XX[i+1] - XX[i-1])
# compute central difference on XX[i]
# now fix up Yp1[0] and Yp1[end]
#Yp1[0] = Yp1[1] # just substitution
Yprime[0] =  (GAMY[1] - GAMY[0])/(XX[1] - XX[0])  # forward difference
#Yp1[len(Yp1)-1] = Yp1[len(Yp1) - 2] # just substitution
last = len(Yprime)-1
Yprime[last] = (GAMY[last] - GAMY[last-1])/(XX[last] - XX[last-1]) # backward diff


plt.plot(XX,Yprime,'-b',label='GAM numerical deriv' )

plt.legend()
plt.show()

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64897920

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档