mgcv拟合含ti交互的GAM时plot.gam与vis.gam曲面差异问题
两个绘图函数结果差异的核心本质
函数设计的目标完全不同
plot.gam(即直接对gam对象调用plot()触发的方法)是单平滑项贡献的专属可视化工具
当你用select=2指定要展示ti(x, cov1)项时,函数只会计算这一个平滑项本身对模型线性预测的独立贡献,完全剔除模型内其他所有项的数值影响:- 纵轴尺度完全匹配这个ti项自身的取值范围
- 不计算、不叠加模型中
s(x)、ti(x,cov2)、blocking_var等其他项的贡献
针对ti()项,这个结果是正交扣除了所有单变量主效应、其他交互效应后的纯交互残差贡献,也就是ti项本身的设计定位。
vis.gam是全模型预测曲面的通用可视化工具
它没有拆分单个平滑项贡献的逻辑:当你指定view=c('x', 'cov1')时,函数会在x和cov1的取值网格上,将模型内所有其他协变量固定到指定参考值(连续变量默认取样本均值、分类变量默认取第一个水平),计算模型在该网格上的总线性预测值后绘制曲面。
计算过程中,所有和x、cov1存在关联的模型项的贡献都会被叠加,不会单独剔除某一个平滑项的影响。
不同模型结构下结果差异的具体来源
你观察到的“ti模型下两图差异极大、te模型下两图几乎一致”的现象,完全可以用两个函数的设计逻辑解释:
- 带ti项的模型结构:
y ~ s(x) + ti(x,cov1) + ti(x,cov2) + blocking_var
模型中x的效应被拆成了三个独立部分:单独的非线性主效应s(x)、和cov1的纯交互项ti(x,cov1)、和cov2的纯交互项ti(x,cov2)。plot.gam只拿出幅度很小的ti(x,cov1)纯交互项单独展示,曲面形状只反映x和cov1扣除各自主效应后的联动关系;vis.gam计算总预测时,会把幅度很大的s(x)的曲线形状、以及ti(x,cov2)在cov2固定时随x变化的分量全部叠加到曲面中,最终展示的是三个效应叠加后的总结果,自然和只看单个小ti项的曲面形状、纵轴范围产生巨大差异。
- 带te项的模型结构:
y ~ te(x,cov1) + te(x,cov2) + blocking_var
模型没有拆分x的单变量主效应,x的所有非线性影响都被包含在两个独立的张量积项te(x,cov1)、te(x,cov2)中。plot.gam单独展示te(x,cov1)项的贡献;vis.gam计算总预测时,te(x,cov1)的贡献被完整算入总曲面,剩下的te(x,cov2)在cov2固定为均值时,仅为整个曲面带来一个幅度很小的常数偏移或平缓起伏,不会改变te(x,cov1)本身的曲面形状,因此视觉上两个结果几乎完全一致。
正确使用方式
- 如果需要展示x和cov1的纯交互效应(即扣除各自独立主效应后的净联动效果),直接使用
plot.gam选择对应ti项绘图即可,这个结果反映的就是模型估计的纯交互效应,不存在偏差。 - 如果需要展示固定其他变量参考水平时,x和cov1共同变化对因变量的总预测影响,使用
vis.gam即可,但需要明确这个结果不是纯交互效应,是所有相关项贡献的叠加,纵轴对应总预测值的尺度。
补充验证:你可以通过
predict.gam(type = "terms")手动计算每个项的单独贡献,其中ti(x,cov1)列的取值范围和曲面形状,和plot.gam绘制的结果完全匹配;在固定其他变量的网格上计算全模型总预测,得到的结果和vis.gam的输出完全一致,这也能直接证明两个函数的计算逻辑差异,不存在模型拟合的bug。
内容的提问来源于stack exchange,提问作者Anke
相关产品推荐
相关产品推荐

