X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=pkg%2FR%2FoptimParams.R;h=85c21e7e696a9bad3c0edbe06f5feb36a952307e;hb=b46623addc9e63019aa1df1dd2de800b48fdd609;hp=1ef1494e74841078859d7a4ff26eadffee98e029;hpb=cf673dee64ab0ce02ccaaba0fb63a9a4589ee8aa;p=morpheus.git diff --git a/pkg/R/optimParams.R b/pkg/R/optimParams.R index 1ef1494..85c21e7 100644 --- a/pkg/R/optimParams.R +++ b/pkg/R/optimParams.R @@ -10,6 +10,7 @@ #' \item 'M' : list of moments of order 1,2,3: will be computed if not provided. #' \item 'X,Y' : input/output, mandatory if moments not given #' \item 'exact': use exact formulas when available? +#' \item weights Weights on moments when minimizing sum of squares #' } #' #' @return An object 'op' of class OptimParams, initialized so that \code{op$run(x0)} @@ -56,9 +57,14 @@ optimParams = function(K, link=c("logit","probit"), optargs=list()) M <- computeMoments(optargs$X,optargs$Y) } + weights <- optargs$weights + if (is.null(weights)) + weights <- rep(1, K) + # Build and return optimization algorithm object methods::new("OptimParams", "li"=link, "M1"=as.double(M[[1]]), - "M2"=as.double(M[[2]]), "M3"=as.double(M[[3]]), "K"=as.integer(K)) + "M2"=as.double(M[[2]]), "M3"=as.double(M[[3]]), + "weights"=weights, "K"=as.integer(K)) } # Encapsulated optimization for p (proportions), β and b (regression parameters) @@ -67,6 +73,7 @@ optimParams = function(K, link=c("logit","probit"), optargs=list()) # @field M1 Estimated first-order moment # @field M2 Estimated second-order moment (flattened) # @field M3 Estimated third-order moment (flattened) +# @field weights Vector of moments' weights # @field K Number of populations # @field d Number of dimensions # @@ -79,6 +86,7 @@ setRefClass( M1 = "numeric", #order-1 moment (vector size d) M2 = "numeric", #M2 easier to process as a vector M3 = "numeric", #M3 easier to process as a vector + weights = "numeric", #weights on moments # Dimensions K = "integer", d = "integer" @@ -132,9 +140,9 @@ setRefClass( β3 <- apply(β, 2, function(col) col %o% col %o% col) return( - sum( ( β %*% (p * .G(li,1,λ,b)) - M1 )^2 ) + - sum( ( β2 %*% (p * .G(li,2,λ,b)) - M2 )^2 ) + - sum( ( β3 %*% (p * .G(li,3,λ,b)) - M3 )^2 ) ) + weights[1] * sum( ( β %*% (p * .G(li,1,λ,b)) - M1 )^2 ) + + weights[2] * sum( ( β2 %*% (p * .G(li,2,λ,b)) - M2 )^2 ) + + weights[3] * sum( ( β3 %*% (p * .G(li,3,λ,b)) - M3 )^2 ) ) }, grad_f = function(x) @@ -166,9 +174,9 @@ setRefClass( km1 = 1:(K-1) grad <- #gradient on p - t( sweep(as.matrix(β [,km1]), 2, G1[km1], '*') - G1[K] * β [,K] ) %*% F1 + - t( sweep(as.matrix(β2[,km1]), 2, G2[km1], '*') - G2[K] * β2[,K] ) %*% F2 + - t( sweep(as.matrix(β3[,km1]), 2, G3[km1], '*') - G3[K] * β3[,K] ) %*% F3 + weights[1] * t( sweep(as.matrix(β [,km1]), 2, G1[km1], '*') - G1[K] * β [,K] ) %*% F1 + + weights[2] * t( sweep(as.matrix(β2[,km1]), 2, G2[km1], '*') - G2[K] * β2[,K] ) %*% F2 + + weights[3] * t( sweep(as.matrix(β3[,km1]), 2, G3[km1], '*') - G3[K] * β3[,K] ) %*% F3 grad_β <- matrix(nrow=d, ncol=K) for (i in 1:d) @@ -197,14 +205,17 @@ setRefClass( dβ3_right[block,] <- dβ3_right[block,] + β2 dβ3 <- dβ3_left + sweep(dβ3_right, 2, p * G3, '*') - grad_β[i,] <- t(dβ) %*% F1 + t(dβ2) %*% F2 + t(dβ3) %*% F3 + grad_β[i,] <- + weights[1] * t(dβ) %*% F1 + + weights[2] * t(dβ2) %*% F2 + + weights[3] * t(dβ3) %*% F3 } grad <- c(grad, as.double(grad_β)) grad = c(grad, #gradient on b - t( sweep(β, 2, p * G2, '*') ) %*% F1 + - t( sweep(β2, 2, p * G3, '*') ) %*% F2 + - t( sweep(β3, 2, p * G4, '*') ) %*% F3 ) + weights[1] * t( sweep(β, 2, p * G2, '*') ) %*% F1 + + weights[2] * t( sweep(β2, 2, p * G3, '*') ) %*% F2 + + weights[3] * t( sweep(β3, 2, p * G4, '*') ) %*% F3 ) grad }, @@ -213,13 +224,23 @@ setRefClass( { "Run optimization from x0 with solver..." - if (!is.numeric(x0) || any(is.na(x0)) || length(x0) != (d+2)*K-1 - || any(x0[1:(K-1)] < 0) || sum(x0[1:(K-1)]) > 1) - { - stop("x0: numeric vector, no NA, length (d+2)*K-1, sum(x0[1:(K-1) >= 0]) <= 1") - } - - op_res = constrOptim( x0, .self$f, .self$grad_f, + if (!is.list(x0)) + stop("x0: list") + if (is.null(x0$β)) + stop("At least x0$β must be provided") + if (!is.matrix(x0$β) || any(is.na(x0$β)) || ncol(x0$β) != K) + stop("x0$β: matrix, no NA, ncol == K") + if (is.null(x0$p)) + x0$p = rep(1/K, K-1) + else if (length(x0$p) != K-1 || sum(x0$p) > 1) + stop("x0$p should contain positive integers and sum to < 1") + # Next test = heuristic to detect missing b (when matrix is called "beta") + if (is.null(x0$b) || all(x0$b == x0$β)) + x0$b = rep(0, K) + else if (any(is.na(x0$b))) + stop("x0$b cannot have missing values") + + op_res = constrOptim( linArgs(x0), .self$f, .self$grad_f, ui=cbind( rbind( rep(-1,K-1), diag(K-1) ), matrix(0, nrow=K, ncol=(d+1)*K) ),