Advertisement
Guest User

Untitled

a guest
Jun 22nd, 2017
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.31 KB | None | 0 0
  1. # Piecewise basis functions: splines
  2. # ch. 5 of ESL: Hastie, Tibshirani & Friedman (2009)
  3.  
  4. # one dimension (p=1)
  5. x <- seq(-0.5,1,by=0.05)[-11]
  6. y <- 2 - 5*exp(-8 * x^2) + rnorm(length(x), sd=0.5)
  7. plot(x,y, ylim=range(-3,2,y))
  8. curve(2 - 5*exp(-8 * x^2), from=-0.5, to=1, n=length(x), col=4, add=T)
  9.  
  10. # kNN regression: piecewise constant
  11. library(FNN)
  12. x.star <- seq(-0.5,1,by=0.025)
  13. kNN.fit <- knn.reg(x, y=y, test=data.frame(x=x.star))
  14. lines(x.star, kNN.fit$pred, col=2)
  15.  
  16. # linear basis: degree=1
  17. B <- splines::bs(sort(x), df=5, intercept = TRUE, Boundary.knots=c(-0.5,1), degree=1)
  18. dim(B)
  19. plot(c(0,0),c(1,1), type='n', xlab='X', ylab='B(X)',xlim=c(-0.5,1),ylim=c(0,1))
  20. #rug(x)
  21. rug(attr(B,'knots'), col=2)
  22. rug(attr(B,'Boundary.knots'), col=2)
  23. #abline(v=attr(B,"knots"), lty=2, col=4)
  24. #abline(v=attr(B,"Boundary.knots"), lty=3, col=2)
  25. bpred <- predict(B, x.star)
  26. for (i in 1:5) {
  27. lines(x.star, bpred[,i], col=i, lty=i)
  28. }
  29. title(main="5 linear B-spline basis functions")
  30. sp1 <- lm.fit(B, y)
  31. plot(x,y, ylim=range(-3,2,y))
  32. curve(2 - 5*exp(-8 * x^2), from=-0.5, to=1, n=length(x), col=4, add=T)
  33. lines(x.star, kNN.fit$pred, col=2)
  34. lines(x, sp1$fitted.values, col=3, lwd=2)
  35. rug(attr(B,'knots'), col=3, lwd=2)
  36. rug(attr(B,'Boundary.knots'), col=3, lwd=2)
  37. legend("bottomright",pch=c(NA,1,NA,NA,NA),lty=c(1,NA,1,1,1),col=c(4,1,2,3),lwd=c(1,1,1,2),
  38. legend=c("true function","observations","kNN regression","linear B-spline (5 knots)"))
  39.  
  40. # now use cubic basis
  41. B <- splines::bs(sort(x), df=7, intercept = TRUE, Boundary.knots=c(-0.5,1))
  42. plot(c(0,0),c(1,1), type='n', xlab='X', ylab='B(X)',xlim=c(-0.5,1),ylim=c(0,1))
  43. #rug(x)
  44. rug(attr(B,'knots'), col=2)
  45. rug(attr(B,'Boundary.knots'), col=2)
  46. bpred <- predict(B, x.star)
  47. for (i in 1:7) {
  48. lines(x.star, bpred[,i], col=i, lty=i)
  49. }
  50. title(main="7 cubic B-spline basis functions")
  51. sp2 <- lm.fit(B, y)
  52. plot(x,y, ylim=range(-3,2,y))
  53. curve(2 - 5*exp(-8 * x^2), from=-0.5, to=1, n=length(x), col=4, add=T)
  54. lines(x, sp1$fitted.values, col=3)
  55. lines(x, sp2$fitted.values, col=6, lwd=2)
  56. rug(attr(B,'knots'), col=6)
  57. rug(attr(B,'Boundary.knots'), col=6)
  58. legend("bottomright",pch=c(NA,1,NA,NA,NA),lty=c(1,NA,1,1,1),col=c(4,1,3,6),lwd=c(1,1,1,2),
  59. legend=c("true function","observations","linear B-spline (5 knots)",
  60. "cubic B-spline (5 knots)"))
  61.  
  62. # extrapolating outside the range of the data
  63. plot(c(-1,1.5),c(-2,2), type='n', xlab='X', ylab='B(X)',xlim=c(-1,1.5),ylim=c(-2,2))
  64. #rug(x)
  65. rug(attr(B,'knots'), col=2)
  66. rug(attr(B,'Boundary.knots'), col=2)
  67. newx <- seq(-1,1.5,by=0.025)
  68. bpred <- predict(B, newx)
  69. for (i in 1:7) {
  70. lines(newx, bpred[,i], col=i, lty=i)
  71. }
  72. range(bpred)
  73.  
  74. # natural cubic splines
  75. B <- splines::ns(sort(x), df=7, intercept = TRUE, Boundary.knots=c(-0.5,1))
  76. plot(c(-1,1.5),c(-2,2), type='n', xlab='X', ylab='B(X)',xlim=c(-1,1.5),ylim=c(-2,2))
  77. #rug(x)
  78. rug(attr(B,'knots'), col=2)
  79. rug(attr(B,'Boundary.knots'), col=2)
  80. bpred <- predict(B, newx)
  81. for (i in 1:7) {
  82. lines(newx, bpred[,i], col=i, lty=i)
  83. }
  84. range(bpred)
  85. sp3 <- lm.fit(B, y)
  86. plot(x,y, ylim=range(-3,2,y))
  87. curve(2 - 5*exp(-8 * x^2), from=-0.5, to=1, n=length(x), col=4, add=T)
  88. lines(x, sp1$fitted.values, col=3)
  89. lines(x, sp2$fitted.values, col=6)
  90. lines(x, sp3$fitted.values, col=1)
  91. legend("bottomright",pch=c(NA,1,NA,NA,NA,NA),lty=c(1,NA,1,1,1,1),col=c(4,1,3,6,1),
  92. legend=c("true function","observations","linear B-spline (5 knots)",
  93. "cubic B-spline (5 knots)","natural cublic spline"))
  94.  
  95. # increase the number of knots: overfitting!
  96. B <- splines::ns(sort(x), df=20, intercept = TRUE, Boundary.knots=c(-0.5,1))
  97. image(B)
  98. sp4 <- lm.fit(B, y)
  99. plot(x,y, ylim=range(-3,2,y))
  100. curve(2 - 5*exp(-8 * x^2), from=-0.5, to=1, n=length(x), col=4, add=T)
  101. lines(x, sp3$fitted.values, col=1)
  102. lines(x, sp4$fitted.values, col=2)
  103. rug(attr(B,'knots'), col=2)
  104. rug(attr(B,'Boundary.knots'), col=2)
  105. legend("bottomright",pch=c(NA,1,NA,NA,NA),lty=c(1,NA,1,1,1),col=c(4,1,1,2),
  106. legend=c("true function","observations","B-spline (5 knots)","B-spline (20 knots)"))
  107.  
  108. # Sect. 5.4: Penalised Splines
  109. sp4$coefficients
  110. prior.betaSD <- 3
  111. NB <- 20
  112. prior.betaCov <- diag(prior.betaSD^2, NB, NB)
  113. n.iter <- 20
  114. pen <- 0.1 # fixed smoothing penalty, lambda
  115.  
  116. # prior precision matrix for the spline coefficients, beta
  117. library(Matrix)
  118. B <- splines::bs(sort(x), df=20, intercept = TRUE, Boundary.knots=c(-0.5,1))
  119. # matrix of 2nd derivatives (Eilers & Marx, 1996)
  120. # WARNING: assumes equidistant knots!
  121. D <- diag(NB)
  122. D <- diff(diff(D))
  123. g0 <- Matrix(crossprod(D), sparse=TRUE)
  124. bTb <- Matrix(crossprod(B), sparse=TRUE)
  125. giPrecMx <- bTb + length(y)*pen*g0
  126. giChol <- Cholesky(giPrecMx)
  127. beta.mu <- as.vector(solve(giChol, crossprod(B, y)))
  128. plot(x,y, ylim=range(-3,2,y))
  129. curve(2 - 5*exp(-8 * x^2), from=-0.5, to=1, n=length(x), col=4, add=T)
  130. bpred <- predict(B, x.star)
  131. lines(x.star, bpred %*% beta.mu, col=2)
  132. #lines(x.star, bpred %*% sp4$coefficients, col=6)
  133.  
  134. # inverse gamma prior for the noise
  135. priorNoiseNu <- 4
  136. priorNoiseSD <- 1
  137. priorNoiseSS <- priorNoiseNu * priorNoiseSD^2
  138. sqDiff <- sum(diag(crossprod(y))) - sum(diag(t(beta.mu) %*% giPrecMx %*% beta.mu))
  139. newSS = (priorNoiseSS + sqDiff)/2.0
  140. sdVec = rgamma(n.iter, (priorNoiseNu + length(y))/2.0)
  141. newTau = sdVec / newSS;
  142. sigma_prop = 1/sqrt(newTau)
  143.  
  144. # posterior samples of the spline function
  145. beta.samp <- matrix(nrow=n.iter, ncol=NB)
  146. for (it in 1:n.iter) {
  147. stdNorm <- rnorm(NB)
  148. blChol <- Cholesky(giPrecMx * newTau[it])
  149. beta.samp[it,] <- as.vector(beta.mu + solve(blChol, stdNorm))
  150. lines(x.star, bpred %*% beta.samp[it,], col=2, lty=3)
  151. }
  152.  
  153. # integrated squared second derivative (Green & Silverman, 1994)
  154. B <- splines::ns(sort(x), df=20, intercept = TRUE, Boundary.knots=c(-0.5,1))
  155. t <- c(attr(B,'Boundary.knots')[1], attr(B,'knots'), attr(B,'Boundary.knots')[2])
  156. NK <- length(t)
  157. rug(t,col=2)
  158. h <- diff(t)
  159. Q <- matrix(0,nrow=NK,ncol=NK-2)
  160. for (j in 2:(NK-1)) {
  161. Q[(j-1),(j-1)] <- 1/h[j-1]
  162. Q[j,(j-1)] <- -1/h[j-1] - 1/h[j]
  163. Q[(j+1),(j-1)] <- 1/h[j]
  164. }
  165. R <- matrix(0,nrow=NK-2,ncol=NK-2)
  166. for (i in 2:(NK-2)) {
  167. R[(i-1),(i-1)] <- (h[i-1] + h[i])/3
  168. R[(i-1),i] <- R[i,(i-1)] <- h[i]/6
  169. }
  170. R[i,i] <- (h[i-1] + h[i])/3
  171. K <- Q %*% solve(R) %*% t(Q)
  172.  
  173. # Gibbs sampling for beta and lambda (Ruppert, Wand & Carroll, 2003)
  174. betaGibbs <- function(y, var_noise, giPrecMx, B) {
  175. stdNorm <- rnorm(ncol(B))
  176. giChol <- Cholesky(giPrecMx)
  177. beta.mu <- as.vector(solve(giChol, crossprod(B, y)))
  178. tau <- 1/var_noise
  179. blChol <- chol(giPrecMx * tau)
  180. return(as.vector(beta.mu + solve(blChol, stdNorm)))
  181. }
  182.  
  183. varNoiseGibbs <- function(A, n, B, ssd) {
  184. Aprime <- A + n/2
  185. Bprime <- 1/B + ssd/2
  186. return(1/rgamma(1, Aprime, Bprime))
  187. }
  188.  
  189. A_e <- B_e <- A_b <- B_b <- 0.1 # inverse gamma priors for variance
  190. n_iter <- 2000
  191. samp_SdB <- samp_SdE <- samp_L <- numeric(length=n_iter)
  192. samp_Beta <- matrix(nrow=n_iter, ncol=NK)
  193. var_noise <- 1/rgamma(1,A_e,1/B_e)
  194. var_beta <- 1/rgamma(1,A_b,1/B_b)
  195.  
  196. for (it in 1:n_iter) {
  197. lambda <- var_noise/var_beta
  198. # giPrecMx <- Matrix(diag(NK) + lambda*K, sparse=TRUE)
  199. giPrecMx <- bTb + length(y)*lambda*g0
  200. samp_Beta[it,] <- beta <- betaGibbs(y, var_noise, giPrecMx, B)
  201. ssd_beta <- crossprod(y - B %*% beta)
  202. var_noise <- varNoiseGibbs(A_e, length(y), B_e, ssd_beta)
  203. samp_SdE[it] <- sqrt(var_noise)
  204. var_beta <- varNoiseGibbs(A_b, NK, B_b, crossprod(beta))
  205. samp_SdB[it] <- sqrt(var_beta)
  206. samp_L[it] <- var_noise/var_beta
  207. }
  208.  
  209. library(coda)
  210. samp_coda <- mcmc(cbind(samp_SdE,samp_SdB,samp_L))
  211. varnames(samp_coda) <- c("sigma[epsilon]","sigma[beta]","lambda")
  212. plot(samp_coda)
  213. nburn <- n_iter/2
  214. samp_coda <- mcmc(cbind(samp_SdE,samp_SdB,samp_L,samp_Beta))
  215. varnames(samp_coda) <- c("sigma[epsilon]","sigma[beta]","lambda", paste0("beta[",1:NK,"]"))
  216. samp <- window(samp_coda, start=nburn+1)
  217. effectiveSize(samp)
  218. summary(samp)
  219.  
  220. samp_idx <- nburn + sample(1:(n_iter-nburn), 20)
  221. plot(x,y, ylim=range(-3,2,y))
  222. curve(2 - 5*exp(-8 * x^2), from=-0.5, to=1, n=length(x), col=4, add=T)
  223. bpred <- predict(B, x.star)
  224. for (idx in samp_idx) {
  225. lines(x.star, bpred %*% samp_Beta[idx,], col=2, lty=3)
  226. }
  227. legend("bottomright",legend=c("observations","true function","posterior samples"),
  228. lty=c(NA,1,3),col=c(1,4,2),pch=c(1,NA,NA), lwd=c(1,1,2))
  229. title(main=paste(length(samp_idx), "posterior samples for Bayesian P-spline"))
  230.  
  231. pen <- 1e-2
  232. giPrecMx <- Matrix(diag(NK) + pen*K, sparse=TRUE)
  233. giChol <- Cholesky(giPrecMx)
  234. beta.mu <- as.vector(solve(giChol, crossprod(B, y)))
  235. plot(x,y, ylim=range(-3,2,y))
  236. curve(2 - 5*exp(-8 * x^2), from=-0.5, to=1, n=length(x), col=4, add=T)
  237. bpred <- predict(B, x.star)
  238. lines(x.star, bpred %*% beta.mu, col=2)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement