admin管理员组

文章数量:1410724

In the documentation for mgcv::pcls(), an example of constructing a monotonically increasing gam model is provided with the following code:

set.seed(1234) # added for reproducibility in this post only
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)
# Show regular spline fit (and save fitted object)
f.ug <- gam(y~s(x,k=10,bs="cr")); lines(x,fitted(f.ug))
# Create Design matrix, constraints etc. for monotonic spline....
sm <- smoothCon(s(x,k=10,bs="cr"),dat,knots=NULL)[[1]]
F <- mono.con(sm$xp);   # get constraints
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);  # fit spline (using s.p. from unconstrained fit)

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

This produces the follow plot (if set.seed(1234) is used):

Question:

How does one correctly constrain the monotonically increasing model so that the lower bound is 0.1 and the upper bound is 1.0? I naively initially thought one could set these values as the lower and upper bound values in mono.con. For example F<-mono(sm$xp, lower=0.1, upper=1.0), but this will return the following value for F$b:

 [1]  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
[25]  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.1 -1.0

(i.e. lower and -1*upper have been appended to F$b (and dim(F$A)[1] has similarly increased by 2), but the call to pcls(G) returns the following: Error in pcls(G) : initial parameters not feasible

Is there a modification to example code in ?pcls that can constrain the monototonically increasing gam to between the blue lines in this image below:

In the documentation for mgcv::pcls(), an example of constructing a monotonically increasing gam model is provided with the following code:

set.seed(1234) # added for reproducibility in this post only
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)
# Show regular spline fit (and save fitted object)
f.ug <- gam(y~s(x,k=10,bs="cr")); lines(x,fitted(f.ug))
# Create Design matrix, constraints etc. for monotonic spline....
sm <- smoothCon(s(x,k=10,bs="cr"),dat,knots=NULL)[[1]]
F <- mono.con(sm$xp);   # get constraints
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);  # fit spline (using s.p. from unconstrained fit)

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

This produces the follow plot (if set.seed(1234) is used):

Question:

How does one correctly constrain the monotonically increasing model so that the lower bound is 0.1 and the upper bound is 1.0? I naively initially thought one could set these values as the lower and upper bound values in mono.con. For example F<-mono(sm$xp, lower=0.1, upper=1.0), but this will return the following value for F$b:

 [1]  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0
[25]  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.1 -1.0

(i.e. lower and -1*upper have been appended to F$b (and dim(F$A)[1] has similarly increased by 2), but the call to pcls(G) returns the following: Error in pcls(G) : initial parameters not feasible

Is there a modification to example code in ?pcls that can constrain the monototonically increasing gam to between the blue lines in this image below:

Share Improve this question asked Mar 11 at 13:32 langtanglangtang 25k1 gold badge14 silver badges30 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

Here is the relevant code:

F<-mono.con(sm$xp, lower=0.1,upper=1)
F$A[4*(10-1)+1,1] <- 1
G <- list(X=sm$X,C=matrix(0,0,0),sp=f.ug$sp,p=scales::rescale(sm$xp,to=c(0.4,0.7)),y=y,w=y*0+1)
G$Ain <- F$A;G$bin <- F$b;G$S <- sm$S;G$off <- 0

p <- pcls(G)

> p
 [1] 0.1000000 0.1346833 0.2752035 0.5562702 0.7425019 0.9762224 0.9891460 1.0000000 1.0000000 1.0000000

Few notes:

  1. The error message mentions initial parameters not feasible. Therefore, we can rescale the initial parameter (G$p) to satisfy the constraint.

  2. There is a bug when constructing inequality matrix in mono.con() as the lower bound constraint becomes [0 0 0 0 0...]x >= 0.1 instead of [1 0 0 0 0]x >= 0.1. I think the issues is this where 4*n should be 4*n+lo. This is why I temporarily add F$A[4*(10-1)+1,1] <- 1 .

For decreasing constraint, we would do the following:

F<-mono.con(sm$xp,up=FALSE, lower=0.1,upper=1)
F$A[4*(10-1)+1,10] <- 1
F<-mono.con(sm$xp,up=FALSE)
G <- list(X=sm$X,C=matrix(0,0,0),sp=f.ug$sp,p=scales::rescale(sm$xp,to=c(0.7,0.4)),y=y,w=y*0+1)
G$Ain <- F$A;G$bin <- F$b;G$S <- sm$S;G$off <- 0

p <- pcls(G);  # fit spline (using s.p. from unconstrained fit)
p
[1] 1.0000000 1.0000000 1.0000000 0.9891460 0.9762224 0.7425019 0.5562702 0.2752035 0.1346833 0.1000000

Namely, sm$xp is rescaled to c(0.7,0.4) and the lower bound constraint becomes [0 0 ... 0 0 1]x>=0.1 instead of [0 0 ... 0 0 0]x>=1.

本文标签: rHow to correctly specify lower and upper bounds in mgcv monocon functionStack Overflow