数据集越大GAMM曲线越尖锐?求建模问题排查方案
问题背景
基于结构一致但规模不同的数据集构建GAMM模型,小数据集约15k行,最大数据集达400k行。发现数据集越大,可视化的曲线越尖锐、呈棱角状,与“数据越多曲线越平滑”的预期不符。已尝试调整k值、gamma值(1.1-1.9)、n.grid值(10-200),均无改善。
数据集结构
glimpse(df.long) Rows: 37,689 Columns: 37 $ word <fct> ciepło, człowieczej, człowiek, człowiek, człowiek, człowiek, płaczu, słońce, właściwie, właśnie, wykłada… $ C <chr> "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w", "w",… $ V2 <fct> ɔ, ɔ, ɔ, ɔ, ɔ, ɔ, a, ɔ, a, a, a, ɔ, ɔ, ɔ, ɔ, ɔ, ɔ, ɔ, a, ɔ, a, a, a, ɔ, ɔ, ɔ, ɔ, ɔ, ɔ, ɔ, a, ɔ, a, a, a,… $ speaker <fct> JP, JP, JP, JP, JP, JP, JP, JP, JP... $ stress <fct> unstressed, unstressed, stressed, stressed, stressed, stressed, stressed, stressed, unstressed, stressed… $ F3 <dbl> 2018, 1883, 1870, 2082, 1982, 1866, 2109, 1933, 1839, 1891, 1923, 1683, 2011, 1929, 1872, 2008, 2013, 19… $ time.i <dbl> 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.5625, … $ logdurz <dbl[,1]> <matrix[43 x 1]> $ period <fct> 1921-1940, 1921-1940, 1921-1940, 1921-1940, 1921-1940, 1921-1940, 1921-1940, 1921-1940, 1921-1940, 1… $ period_num <dbl> 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 19… $ start.event <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALS… $ C1bis.ord <ord> labials, dentals, dentals, dentals, dentals, dentals, labials, dentals, labials, labials, velars, dental… $ V2.ord <ord> ɔ, ɔ, ɔ, ɔ, ɔ, ɔ, a, ɔ, a, a, a, ɔ, ɔ, ɔ, ɔ, ɔ, ɔ, ɔ, a, ɔ, a, a, a, ɔ, ɔ, ɔ, ɔ, ɔ, ɔ, ɔ, a, ɔ, a, a, a,… $ stress.ord <ord> unstressed, unstressed, stressed, stressed, stressed, stressed, stressed, stressed, unstressed, stressed… $ V2.stress.ord <ord> ɔ_unstressed, ɔ_unstressed, ɔ_stressed, ɔ_stressed, ɔ_stressed, ɔ_stressed, a_stressed, ɔ_stressed, a_un…
GAMM模型代码
g.PS.CV.dur.AR <- bam(F3 ~ V2.ord + C1bis.ord + stress.ord + #level 1 smooth terms s(time.i, bs="cr", k=4) + s(period_num, bs="cr", k=4) + s(logdurz, bs="cr", k=4) + #level 2 by terms s(time.i, by=stress.ord, k=4) + s(time.i, by=V2.ord, k=4) + s(time.i, by=C1bis.ord, k=4) + s(period_num, by=C1bis.ord, k=4) + s(period_num, by=V2.ord, k=4) + s(period_num, by=stress, k=4) + #level 2: 2d smooth ti(time.i, logdurz, k=c(4,4)) + ti(time.i, period_num, k=c(4,4)) + #level 3: 2d smooth by terms ti(time.i, period_num, k=c(4,4), by=stress.ord) + ti(time.i, period_num, k=c(4,4), by=V2.ord) + ti(time.i, period_num, k=c(4,4), by=C1bis.ord) + #random terms s(time.i, speaker, bs="fs", m=1, k=4) + s(mot, bs="re"), data = ds.w.CV.long, method = "fREML", nthreads=12, rho=r1, AR.start = ds.w.CV.long$start.event, gamma = 1.75, select = TRUE) saveRDS(g.PS.CV.dur.AR, "g.PS.CV.dur.AR")
绘图基础代码
c1_levels <- unique(ds.w.CV.long$C1bis.ord) all.period.plots <- do.call(rbind, lapply(c1_levels, function(level) { temp_plot <- plot_smooth(g.PS.CV.dur.AR, view = "time.i", plot_all = "period_num", rm.ranef = FALSE, n.grid = 100, cond = list(C1bis.ord = level), return.plot = TRUE)$fv temp_plot$C1bis.ord <- level temp_plot }))
可能原因与排查方向
模型基函数数量不足
所有平滑项的k值都设为4,这是极低的基数。当数据量从15k跃升至400k时,有限的基函数无法适配数据中更精细的模式,但大数据量下模型拟合精度更高,会强行用有限的基去贴合密集数据,最终导致曲线出现棱角。建议逐步提升k值(比如先试k=10、k=15),同时用gam.check()检查模型自由度是否充足,配合gamma值微调避免过拟合。自相关处理的适配问题
当前使用AR模型处理序列自相关,大数据量下自相关模式可能更复杂,现有AR设置(比如固定的rho值)可能未充分捕捉相关性,导致残差噪声被平滑项过度拟合,表现为曲线尖锐。可以:- 对比不同数据集的rho估计值,检查是否合理
- 尝试调整AR阶数(比如从AR(1)升级到AR(2))
- 暂时移除AR项,观察曲线是否恢复平滑,验证是否为自相关处理导致的问题
随机效应的拟合能力受限
随机效应项s(time.i, speaker, bs="fs", m=1, k=4)的k值同样过小,无法容纳大数据集中更多的speaker异质性,迫使固定效应平滑项去弥补这部分差异,进而出现尖锐波动。建议提升随机效应的k值,同时检查不同规模数据集的分组变量(如speaker、period_num)分布是否存在显著差异。绘图逻辑的视觉干扰
plot_smooth中plot_all="period_num"的设置,可能因大数据集中period_num取值更密集,导致不同period的曲线衔接处出现视觉上的棱角。可以:- 单独绘制单个period的曲线,排查是否是多period叠加导致的干扰
- 检查
temp_plot中的预测值是否本身存在跳跃,排除绘图插值的问题
数据集本身的分布差异
大数据集可能包含更多小数据集中未覆盖的极端值或协变量组合(比如特定word、V2.ord类别),这些新增数据会打破原有拟合模式,导致曲线波动。建议:- 对比不同规模数据集的变量分布(用
table()或密度图),排查是否存在显著差异 - 检查模型残差分布,看大数据集的残差是否存在异常聚类或波动
- 对比不同规模数据集的变量分布(用
内容的提问来源于stack exchange,提问作者Jul2415

