Nothing
scls <- function(y, x, xnew = NULL, nbcores = 4) {
if ( inherits(y, "sparseMatrix") | inherits(x, "sparseMatrix") ) {
res <- .scls_osqp(y, x, xnew)
} else {
py <- dim(y)[2] ; px <- dim(x)[2]
pyx <- py * px ; n <- dim(y)[1]
if ( identical( class(x)[1], "FBM") ) {
xx <- bigstatsr::big_crossprodSelf(x)
xx <- xx[1:px, 1:px]
a1 <- bigstatsr::FBM(px, py)
dvec <- bigstatsr::big_apply(y, function(X, ind, x, res) {
res[, ind] <- bigstatsr::big_cprodMat(x, X[, ind, drop = FALSE])
}, a.combine = "c", block.size = 500, ncores = nbcores, x = x, res = a1)
dvec <- dvec[1:pyx]
} else {
dvec <- as.vector( crossprod(x, y) )
xx <- crossprod(x)
}
XX <- matrix(0, pyx, pyx)
ind <- matrix( 1:pyx, ncol = px, byrow = TRUE )
for ( i in 1:py ) XX[ ind[i, ], ind[i, ] ] <- xx
A <- matrix(0, pyx, pyx)
for ( i in 1:px ) A[i, ind[, i]] <- 1
A <- t( rbind( A, diag(pyx) ) )
A <- A[, -c( (px + 1): pyx) ]
bvec <- c( rep(1, px), rep(0, pyx) )
f <- try( quadprog::solve.QP( Dmat = XX, dvec = dvec, Amat = A, bvec = bvec,
meq = px ), silent = TRUE )
if ( identical(class(f), "try-error") ) {
f <- quadprog::solve.QP( Dmat = Matrix::nearPD(XX)$mat, dvec = dvec, Amat = A, bvec = bvec, meq = px )
}
be <- matrix( abs(f$solution), ncol = py)
mse <- ( sum(y^2) + 2 * f$value ) / n
if ( is.null( colnames(y) ) ) {
colnames(be) <- paste("Y", 1:py, sep = "")
} else colnames(be) <- colnames(y)
if ( is.null( colnames(x) ) ) {
rownames(be) <- paste("X", 1:px, sep = "")
} else rownames(be) <- colnames(x)
est <- NULL
if ( !is.null(xnew) ) {
est <- xnew %*% be
}
res <- list( mse = mse, be = be, est = est )
}
res
}
.scls_osqp <- function(y, x, xnew = NULL) {
py <- ncol(y) ; px <- ncol(x)
pyx <- py * px ; n <- nrow(y)
# Convert inputs to sparse if not already
if ( !inherits(y, "sparseMatrix") ) y <- Matrix::Matrix(y, sparse = TRUE)
if ( !inherits(x, "sparseMatrix") ) x <- Matrix::Matrix(x, sparse = TRUE)
xx <- Matrix::crossprod(x) # sparse
xy <- Matrix::crossprod(x, y) # sparse
# Construct sparse P via Kronecker product
P <- 2 * Matrix::kronecker(Matrix::Diagonal(py), xx)
# q vector (usually dense, but keep efficient)
q <- -2 * as.vector( as.matrix(xy) )
# Equality: sum-to-one for each predictor
A_eq <- Matrix::kronecker(Matrix::Diagonal(px), Matrix::Matrix(rep(1, py), nrow = 1, sparse = TRUE))
# Inequality: non-negativity
A_ineq <- Matrix::Diagonal(pyx)
# Stack constraints (both sparse)
A <- rbind(A_eq, A_ineq)
l <- c(rep(1, px), rep(0, pyx))
u <- c(rep(1, px), rep(Inf, pyx))
# Solve with OSQP
settings <- osqp::osqpSettings(verbose = FALSE, eps_abs = 1e-8, eps_rel = 1e-8)
model <- osqp::osqp(P = P, q = q, A = A, l = l, u = u, pars = settings)
res <- model$Solve()
be <- matrix(res$x, ncol = py)
#fitted <- x %*% be
#mse <- sum( (as.matrix(y) - as.matrix(fitted))^2 ) / n
mse <- ( model$Solve()$info$obj_val + sum(y^2) ) / n
if (is.null(colnames(y))) {
colnames(be) <- paste0("Y", 1:py)
} else colnames(be) <- colnames(y)
if (is.null(colnames(x))) {
rownames(be) <- paste0("X", 1:px)
} else rownames(be) <- colnames(x)
est <- NULL
if ( !is.null(xnew) ) {
if (!inherits(xnew, "sparseMatrix")) {
xnew <- Matrix::Matrix(xnew, sparse = TRUE)
}
est <- as.matrix(xnew %*% be)
}
list(mse = mse, be = be, est = est)
}
# ols.compcomp_newer <- function(y, x, xnew = NULL) {
# py <- dim(y)[2] ; px <- dim(x)[2]
# pyx <- py * px
# xxinv <- solve( crossprod(x) )
# m <- numeric( px )
# dvec <- - 2 * as.vector( crossprod(x, y) )
# yy <- sum( diag( crossprod(y) ))
# ols <- function(be, yy, dvec, m, xxinv) {
# be <- matrix(be, ncol = py)
# be <- be / rowSums(be)
# be1 <- as.vector(be)
# yy + sum(dvec * be1) + sum( Rfast::mahala(t(be), m, xxinv) )
# }
# runtime <- proc.time()
# mod <- optim( runif(pyx), ols, yy = yy, dvec = dvec, m = m, xxinv = xxinv,
# method = "L-BFGS-B", lower = rep(0, pyx),
# upper = rep(1, pyx), control = list(maxit = 10000) )
# mod <- optim( mod$par, ols, yy = yy, dvec = dvec, m = m, xxinv = xxinv,
# method = "L-BFGS-B", lower = rep(0, pyx),
# upper = rep(1, pyx), control = list(maxit = 10000) )
# runtime <- proc.time() - runtime
# be <- mod$par
# be <- matrix(be, ncol = py)
# be <- be / rowsums(be)
# if ( is.null( colnames(y) ) ) {
# colnames(be) <- paste("Y", 1:py, sep = "")
# } else colnames(be) <- colnames(y)
# if ( is.null( rownames(y) ) ) {
# rownames(be) <- paste("X", 1:px, sep = "")
# } else rownames(be) <- colnames(x)
# est <- NULL
# if ( !is.null(xnew) ) {
# est <- xnew %*% be
# }
# list( runtime = runtime, mse = mod$value / dim(y)[1], be = be, est = est )
# }
# ols.compcomp_old <- function(y, x, xnew = NULL) {
# py <- dim(y)[2] ; px <- dim(x)[2]
# pyx <- py * px
# ols <- function(be) {
# be <- matrix(be, ncol = py)
# be <- be / rowsums(be)
# mu <- x %*% be
# sum( (y - mu)^2 )
# }
# runtime <- proc.time()
# mod <- optim( runif(pyx), ols, method = "L-BFGS-B", lower = rep(0, pyx),
# upper = rep(1, pyx), control = list(maxit = 10000) )
# mod <- optim( mod$par, ols, method = "L-BFGS-B", lower = rep(0, pyx),
# upper = rep(1, pyx), control = list(maxit = 10000) )
# runtime <- proc.time() - runtime
# be <- mod$par
# be <- matrix(be, ncol = py)
# be <- be / rowsums(be)
# if ( is.null( colnames(y) ) ) {
# colnames(be) <- paste("Y", 1:py, sep = "")
# } else colnames(be) <- colnames(y)
# if ( is.null( rownames(y) ) ) {
# rownames(be) <- paste("X", 1:px, sep = "")
# } else rownames(be) <- colnames(x)
# est <- NULL
# if ( !is.null(xnew) ) {
# est <- xnew %*% be
# }
# list( runtime = runtime, mse = mod$value / dim(y)[1], be = be, est = est )
# }
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.