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

如何在mgcv中正确为单调递增GAM模型指定0.1-1.0的上下界?

解决mgcv中单调递增GAM模型的上下界约束问题

原mgcv::pcls()文档中的单调递增GAM示例代码如下:

set.seed(1234) # 保证结果可复现
x <- runif(100)*4-1;x <- sort(x);
f <- exp(4*x)/(1+exp(4*x)); y <- f+rnorm(100)*0.1; plot(x,y)
dat <- data.frame(x=x,y=y)
# 无约束样条拟合
f.ug <- gam(y~s(x,k=10,bs="cr")); lines(x,fitted(f.ug))
# 构建单调样条的设计矩阵与约束
sm <- smoothCon(s(x,k=10,bs="cr"),dat,knots=NULL)[[1]]
F <- mono.con(sm$xp);   # 获取单调约束
G <- list(X=sm$X,C=matrix(0,0,0),sp=f.ug$sp,p=sm$xp,y=y,w=y*0+1)
G$Ain <- F$A;G$bin <- F$b;G$S <- sm$S;G$off <- 0

p <- pcls(G);  # 拟合单调样条

fv<-Predict.matrix(sm,data.frame(x=x))%*%p
lines(x,fv,col=2)

问题分析

直接在mono.con()中设置lower=0.1和upper=1.0会报错initial parameters not feasible,原因是:

  • mono.con的lower/upper是对样条系数的约束,而非拟合值的约束
  • 无约束拟合得到的初始参数sm$xp不满足新增的上下界约束,导致优化无法启动

解决方案:针对拟合值添加上下界约束

我们需要直接对拟合值X %*% p构建约束,同时合并单调约束,再调整初始参数到可行域:

修改后的完整代码

set.seed(1234)
x <- runif(100)*4-1;x <- sort(x);
f <- exp(4*x)/(1+exp(4*x)); y <- f+rnorm(100)*0.1; plot(x,y)
dat <- data.frame(x=x,y=y)

# 1. 先做无约束拟合,获取初始平滑参数
f.ug <- gam(y~s(x,k=10,bs="cr")); lines(x,fitted(f.ug), col = "gray")
sm <- smoothCon(s(x,k=10,bs="cr"),dat,knots=NULL)[[1]]

# 2. 构建三种约束:单调递增、拟合值下界0.1、上界1.0
# 单调约束
mono_const <- mono.con(sm$xp)
# 拟合值下界约束:X %*% p >= 0.1 → 等价于 X %*% p - 0.1 >=0
lower_const <- list(A = sm$X, b = rep(0.1, nrow(sm$X)))
# 拟合值上界约束:X %*% p <=1.0 → 等价于 -X %*% p >= -1.0
upper_const <- list(A = -sm$X, b = rep(-1.0, nrow(sm$X)))

# 合并所有约束矩阵和向量
G_Ain <- rbind(mono_const$A, lower_const$A, upper_const$A)
G_bin <- c(mono_const$b, lower_const$b, upper_const$b)

# 3. 调整初始参数到可行域:先把无约束拟合值截断到0.1-1.0,再反推初始p
init_fv <- fitted(f.ug)
init_fv_clamped <- pmax(pmin(init_fv, 1.0), 0.1)
# 用最小二乘反推可行的初始参数p
init_p <- solve(t(sm$X) %*% sm$X, t(sm$X) %*% init_fv_clamped)

# 4. 构建pcls所需的G列表
G <- list(
  X = sm$X,
  C = matrix(0,0,0),  # 无等式约束
  sp = f.ug$sp,       # 用无约束拟合的平滑参数
  p = init_p,         # 用调整后的可行初始参数
  y = y,
  w = rep(1, length(y)),
  Ain = G_Ain,
  bin = G_bin,
  S = sm$S,
  off = 0
)

# 5. 拟合约束模型
p <- pcls(G)

# 6. 计算拟合值并绘图
fv <- Predict.matrix(sm, data.frame(x=x)) %*% p
lines(x, fv, col=2, lwd=2)
# 添加上下界参考线
abline(h=0.1, col="blue", lty=2)
abline(h=1.0, col="blue", lty=2)

关键说明

  • 直接针对拟合值X%*%p构建约束,而非对样条系数,这样能精准控制拟合结果的范围
  • 初始参数必须调整到满足所有约束的可行域内,这里通过截断无约束拟合值再反推参数实现
  • 合并单调约束与上下界约束时,要注意约束的方向(上界约束需要取负号转化为>=形式)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:25:15