You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R中使用含分类变量的GAM模型预测的边际效应问题

问题根源与解决方案

你的问题出在模型结构设定错误:

  • model_1是针对John的单独数据拟合,所有平滑项s(speed)、s(length)、s(price)都是完全基于John的样本生成的专属曲线。
  • 而你写的model_2只是给每个用户加了一个固定截距user_id,但三个平滑项是基于所有用户数据的全局统一曲线,相当于让John的预测结果是全局平滑曲线加上他的个体截距,这和model_1里John专属的平滑曲线完全不是一回事,结果自然不一样。

正确的模型设定(二选一)

要让全数据模型能输出和单独建模一致的John边际效应,必须让平滑项随user_id单独变化,mgcv里有两种常用方式:

1. 完全独立的用户专属平滑项

这种方式和给每个用户单独建模的逻辑最接近,只是把所有用户的模型放在一起拟合:

model_2 = mgcv::gam(
  y ~ user_id + s(speed, by = user_id) + s(length, by = user_id) + s(price, by = user_id),
  data = data2
)

这里的by = user_id会为每个用户生成独立的s(speed)、s(length)、s(price)平滑曲线,和model_1的拟合逻辑几乎一致。

2. 共享复杂度的因子平滑交互项(更稳健)

如果部分用户的数据量很少,完全独立的平滑项容易过拟合,可以用因子平滑交互项,让所有用户的平滑项共享相同的"平滑程度"(即平滑参数),但曲线的位置和形状可以不同:

model_2 = mgcv::gam(
  y ~ s(speed, user_id, bs = "fs") + s(length, user_id, bs = "fs") + s(price, user_id, bs = "fs"),
  data = data2
)

bs = "fs"表示Factor Smooth,这种设定会在保证平滑项稳健性的同时,保留用户间的个体差异。

预测步骤

用上述正确的model_2后,构造测试集的逻辑和之前一致:

# 先计算John的length和price均值
mean_john_length = mean(data2$length[data2$user_id == "John"], na.rm = TRUE)
mean_john_price = mean(data2$price[data2$user_id == "John"], na.rm = TRUE)

# 构造测试集
test_set2 = data.frame(
  user_id = rep("John", length(seq(0,100,by=5))),
  speed = seq(0,100,by=5),
  length = mean_john_length,
  price = mean_john_price
)

# 获取预测结果
predictions_2 = mgcv::predict.gam(model_2, test_set2, type="response")

此时predictions_2就会和prediction_1的结果一致(或非常接近,取决于拟合的微小差异)。

用ggeffects验证

如果用ggeffects画图,直接指定用户和控制变量即可:

plot(ggeffects::ggpredict(
  model_2, 
  terms = c("speed [0:100 by=5]", "user_id [John]"),
  condition = c(length = mean_john_length, price = mean_john_price)
), facets = TRUE)

内容的提问来源于stack exchange,提问作者Telis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:43:27