From f9c8ae08b9b362d66ac2928c32340a22914fe8b8 Mon Sep 17 00:00:00 2001 From: Le Roux Erwan <erwan.le-roux@irstea.fr> Date: Wed, 16 Oct 2019 09:41:35 +0200 Subject: [PATCH] [EXTREME ESTIMATOR][GEV MARGIN FIT][BAYESIAN] add fevd.R to use fedv package in the Bayesian mode. Also, fix fevd method, by creating my own method "myfevd" that avoid code crash when using mode use.phi=FALSE --- extreme_estimator/margin_fits/gev/fevd.R | 99 -- .../margin_fits/gev/fevd_fixed.R | 967 ++++++++++++++++++ .../margin_fits/gev/main_fevd_fixed.R | 83 ++ 3 files changed, 1050 insertions(+), 99 deletions(-) delete mode 100644 extreme_estimator/margin_fits/gev/fevd.R create mode 100644 extreme_estimator/margin_fits/gev/fevd_fixed.R create mode 100644 extreme_estimator/margin_fits/gev/main_fevd_fixed.R diff --git a/extreme_estimator/margin_fits/gev/fevd.R b/extreme_estimator/margin_fits/gev/fevd.R deleted file mode 100644 index d1018f17..00000000 --- a/extreme_estimator/margin_fits/gev/fevd.R +++ /dev/null @@ -1,99 +0,0 @@ -# Title : TODO -# Objective : TODO -# Created by: erwan -# Created on: 04/10/2019 -library(extRemes) -library(stats4) -library(SpatialExtremes) - -set.seed(42) -N <- 1000 -loc = 0; scale = 1; shape <- 0.1 -x_gev <- rgev(N, loc = loc, scale = scale, shape = shape) -start_loc = 0; start_scale = 1; start_shape = 1 -# res = fevd(x_gev, method='GMLE') - -fevdPriorMy <- function (theta, q, p, log = FALSE){ - x = theta["shape"] + 0.5 - - print(theta) - print(theta["location"]) - print(dunif(theta["location"])) - print(theta[0]) - dfun <- function(th) dbeta(th[1], shape1 = th[2], shape2 = th[3], - log = log) - th <- cbind(theta, q, p) - res <- apply(th, 1, dfun) - return(prod(res)) -} - -fevdPriorMyMy <- function (theta, q, p, log = FALSE){ - print(theta) - print(q) - print(p) - x = theta[length(theta)] - # + 0.5 enables to shift the Beta law in the interval [-0.5, 0.5] - res = dbeta(x + 0.5, q, p, log = TRUE) - return(res) -} - - -print(pbeta(1.0, 1, 1)) -print(pbeta(0.5, 1, 1)) -print(fevdPriorMy(2.0, 0.0, 0.0)) - -res = fevd(x_gev, method='Bayesian', priorFun="fevdPriorMyMy", priorParams=list(q=c(6), p=c(9)), iter=5000) -print(res) -# res = fevd(x_gev, method='Bayesian') -# print(res) - -priorFun="shapePriorBeta" -shapePriorBeta -# -# -# print(shapePriorBeta(0.0, 6, 9)) -# priorParams=list(q=c(1, 1, 6), p=c(1, 1, 9)) -# p.i <- do.call(priorFun, c(list(1.0), priorParams)) -# print(p.i) - -# priorFun <- "shapePriorBeta" -# priorParams <- list(q = 6, p = 9) -# priorFun <- "fevdPriorDefault" -# priorParams <- list(q = 6, p = 9) -# e = do.call(priorFun, c(list(0.0), priorParams)) -# print(e) -# -# print(res$method) -# print(res$priorFun) -# print(res$priorParams) -# m = res$results -# print(m[2,1]) -# print(class(res$chain.info)) -# print(res$chain.info[[1]]) -# # summary(res) -# print(attributes(res)) -# print('here') -# print(attr(res, 'chain.info')) -# print(attr(res, "method")) -# print(attr(res, "x")) -# print(attr(res, "priorParams")) - -# print(res.method) - - -# p.i <- do.call(shapePriorBeta, c(list(theta = c(-0.12572432087762, -0.0567634605386987, 0.133782230298093)), priorParams=list(q = 6, p = 9))) -# print(p.i) -# a = fevd(x_gev, method='Bayesian', priorFun="shapePriorBeta", priorParams=list(q = 6, p = 9)) - -# priorParams=list(v=c(0.1, 10, 0.1)), -# initial=list(location=0, scale=0.1, shape=-0.5)), - -# print(a) -# -# # S3 method for fevd.bayesian -# summary(a, FUN = "mean", burn.in = 499) - -# print(a.results) - -# Bayesian method is using a normal distribution functions for the shape parameter -# GMLE distribution is using a Beta distribution for the shape parameter diff --git a/extreme_estimator/margin_fits/gev/fevd_fixed.R b/extreme_estimator/margin_fits/gev/fevd_fixed.R new file mode 100644 index 00000000..22e932f2 --- /dev/null +++ b/extreme_estimator/margin_fits/gev/fevd_fixed.R @@ -0,0 +1,967 @@ +# Created on: 16/10/2019 +library(extRemes) +library(stats4) +library(SpatialExtremes) + +# TODO: send bug report on CRAN +fevd_fixed <- function (x, data, threshold = NULL, threshold.fun = ~1, location.fun = ~1, + scale.fun = ~1, shape.fun = ~1, use.phi = FALSE, type = c("GEV", + "GP", "PP", "Gumbel", "Exponential"), method = c("MLE", + "GMLE", "Bayesian", "Lmoments"), initial = NULL, span, + units = NULL, time.units = "days", period.basis = "year", + na.action = na.fail, optim.args = NULL, priorFun = NULL, + priorParams = NULL, proposalFun = NULL, proposalParams = NULL, + iter = 9999, weights = 1, blocks = NULL, verbose = FALSE) +{ + if (verbose) + begin.tiid <- Sys.time() + out <- list() + inout <- list() + out$call <- match.call() + if (!missing(data)) { + out$data.name <- c(deparse(substitute(x)), deparse(substitute(data))) + } + else { + out$data.name <- c(deparse(substitute(x)), "") + } + type <- match.arg(type) + method <- match.arg(method) + out$weights <- weights + if (!missing(data)) { + if (is.element(out$data.name[1], colnames(data))) { + out$in.data <- TRUE + wc <- out$data.name[1] == colnames(data) + x <- c(data[, wc]) + x.fun <- ifelse(out$data.name[1] == "substitute(x)", + deparse(x), out$data.name[1]) + x.fun <- formula(paste(x.fun, "~ 1")) + out$x.fun <- x.fun + } + else if (is.formula(x)) { + out$in.data <- TRUE + x.fun <- x + out$x.fun <- x.fun + x <- model.response(model.frame(x.fun, data = data)) + } + else out$in.data <- FALSE + if (length(x) != nrow(data)) + stop("fevd: data must have same number of rows as the length of x.") + if (!identical(weights, 1) && length(x) != length(weights)) + stop("fevd: weights should be the same length as x.") + out$missing.values <- is.na(x) + tmp <- cbind(x, data) + tmp <- na.action(tmp) + x <- tmp[, 1] + data <- tmp[, -1, drop = FALSE] + } + else { + out$missing.values <- is.na(x) + if (is.formula(x)) + stop("fevd: Must provide data argument if you supply a formula to the x argument.") + x <- na.action(x) + out$in.data <- FALSE + } + if (!out$in.data) { + data.pointer <- as.character(substitute(x)) + if (length(data.pointer) > 1) + out$x <- x + else out$data.pointer <- data.pointer + } + if (!is.null(blocks)) { + if (type == "PP") { + if (!is.element("nBlocks", names(blocks))) { + if (is.element("data", names(blocks))) { + blocks$nBlocks <- nrow(blocks$data) + } + else stop("fevd: When supplying blocks, must provide 'blocks$nBlocks' if 'blocks$data' is not provided.") + } + if (!is.element("weights", names(blocks))) + blocks$weights <- 1 + if (!is.element("proportionMissing", names(blocks))) + blocks$proportionMissing <- 0 + if (!is.element("threshold", names(blocks)) && !is.null(threshold)) { + if (length(threshold) == 1) { + blocks$threshold <- threshold + } + else { + stop("fevd: No blocks$threshold specified and threshold is not constant. User must supply the threshold for each block via blocks$threshold.") + } + } + } + else { + warning("fevd: Blocks are used only for type 'PP'; ignoring blocks argument.") + blocks <- NULL + } + } + cat('here1') + out$x <- x + if (!missing(data)) + out$cov.data <- data + if (method == "MLE" && !is.null(priorFun)) + method <- "GMLE" + else if (method == "GMLE" && is.null(priorFun)) { + if (shape.fun != ~1) + stop("fevd: must supply a prior function for GMLE method when shape parameter varies.") + if (is.element(type, c("GEV", "GP", "PP"))) { + priorFun <- "shapePriorBeta" + if (is.null(priorParams)) + priorParams <- list(q = 6, p = 9) + } + else { + warning("fevd: Using method MLE. No default for specified arguments.") + method <- "MLE" + } + } + if (method == "GMLE") { + out$priorFun <- priorFun + out$priorParams <- priorParams + } + out$method <- method + method <- tolower(method) + out$type <- type + type <- tolower(type) + out$period.basis <- period.basis + out$optim.args <- optim.args + out$units <- units + if (method == "bayesian" && missing(use.phi)) { + use.phi <- TRUE + if (verbose) + cat("\n", "Setting use.phi argument to TRUE for greater stability in estimation (default with Bayesian method). Use use.phi=FALSE if you prefer that.\n") + } + out$par.models <- list(threshold = threshold.fun, location = location.fun, + scale = scale.fun, log.scale = use.phi, shape = shape.fun, + term.names = list(threshold = all.vars(threshold.fun), + location = all.vars(location.fun), scale = all.vars(scale.fun), + shape = all.vars(shape.fun))) + pars <- list() + if (is.element(type, c("gp", "pp", "exponential", "beta", + "pareto"))) { + const.thresh <- check.constant(threshold.fun) & check.constant(threshold) + out$const.thresh <- const.thresh + } + if (is.element(type, c("gev", "pp", "gumbel", "weibull", + "frechet"))) { + const.loc <- check.constant(location.fun) + out$const.loc <- const.loc + } + const.scale <- check.constant(scale.fun) + out$const.scale <- const.scale + const.shape <- check.constant(shape.fun) + out$const.shape <- const.shape + if (is.element(type, c("pp", "gp", "exponential", "beta", + "pareto"))) { + if (missing(span)) { + if (is.null(blocks)) { + tiden <- attributes(x)$times + n <- length(x) + if (is.null(tiden)) { + tiden <- 1:n + start <- 1 + end <- n + span <- end - start + } + else { + start <- tiden[1] + end <- tiden[n] + span <- as.numeric(difftime(as.POSIXlt(tiden)[n], + as.POSIXlt(tiden)[1], units = time.units)) + } + } + else { + span <- blocks$nBlocks + } + } + if (time.units == "days") + npy <- 365.25 + else if (time.units == "months") + npy <- 12 + else if (time.units == "years") + npy <- 1 + else if (time.units == "hours") + npy <- 24 * 365.25 + else if (time.units == "minutes") + npy <- 60 * 24 * 365.25 + else if (time.units == "seconds") + npy <- 60 * 60 * 24 * 365.25 + else { + tmp.units <- unlist(strsplit(time.units, split = "/")) + if (length(tmp.units) != 2) + stop("fevd: invalid time.units argument.") + numper <- as.numeric(tmp.units[1]) + if (is.na(numper)) + stop("fevd: invalid time.units argument.") + pertiid <- tmp.units[2] + if (!is.element(pertiid, c("day", "month", "year", + "hour", "minute", "second"))) + stop("fevd: invalid time.units argument.") + if (pertiid == "year") + npy <- numper + else if (pertiid == "month") + npy <- numper * 12 + else if (pertiid == "day") + npy <- numper * 365.25 + else if (pertiid == "hour") + npy <- numper * 24 * 365.25 + else if (pertiid == "minute") + npy <- numper * 60 * 24 * 365.25 + else if (pertiid == "second") + npy <- numper * 60 * 60 * 24 * 365.25 + } + if (!is.null(blocks)) + span <- span * npy + out$time.units <- time.units + out$span <- span/npy + out$npy <- npy + if (verbose) + cat("\n", "Data span ", span/npy, "years", "\n") + } + else npy <- NULL + n <- length(x) + out$n <- n + out$na.action <- deparse(substitute(na.action)) + if (!is.null(initial)) { + if (!is.list(initial)) + stop("fevd: initial must be NULL or a list object.") + find.init <- FALSE + if (is.null(initial$location) && is.element(type, c("gev", + "pp", "gumbel", "weibull", "frechet"))) + find.init <- TRUE + if (use.phi && is.null(initial$log.scale)) + find.init <- TRUE + if (!use.phi && is.null(initial$scale)) + find.init <- TRUE + if (!is.element(type, c("gumbel", "exponential")) && + is.null(initial$shape)) + find.init <- TRUE + } + else { + initial <- list() + find.init <- TRUE + } + if (method != "lmoments") { + if (verbose) + cat("Setting up parameter model design matrices.\n") + designs <- list() + if (!missing(data)) { + if (is.element(type, c("gp", "pp", "exponential", + "beta", "pareto"))) + X.u <- setup.design(x = threshold.fun, data = data, + n = n, dname = "threshold.fun") + if (is.element(type, c("gev", "pp", "gumbel", "weibull", + "frechet"))) { + X.loc <- setup.design(x = location.fun, data = data, + n = n, const = const.loc, dname = "location.fun") + designs$X.loc <- X.loc + } + X.sc <- setup.design(x = scale.fun, data = data, + n = n, const = const.scale, dname = "scale.fun") + designs$X.sc <- X.sc + if (!is.element(type, c("gumbel", "exponential"))) { + X.sh <- setup.design(x = shape.fun, data = data, + n = n, const = const.shape, dname = "shape.fun") + designs$X.sh <- X.sh + } + } + else { + if (is.element(type, c("gp", "pp", "exponential", + "beta", "pareto"))) + X.u <- setup.design(x = threshold.fun, n = n, + dname = "threshold.fun") + if (is.element(type, c("gev", "pp", "gumbel", "weibull", + "frechet"))) { + X.loc <- setup.design(x = location.fun, n = n, + const = const.loc, dname = "location.fun") + designs$X.loc <- X.loc + } + X.sc <- setup.design(x = scale.fun, n = n, const = const.scale, + dname = "scale.fun") + designs$X.sc <- X.sc + if (!is.element(type, c("gumbel", "exponential"))) { + X.sh <- setup.design(x = shape.fun, n = n, const = const.shape, + dname = "shape.fun") + designs$X.sh <- X.sh + } + } + if (!is.null(blocks)) { + blocks$designs <- list() + if (is.element("data", names(blocks))) { + blocks$X.u <- setup.design(x = threshold.fun, + data = blocks$data, n = blocks$nBlocks, dname = "threshold.fun") + blocks$designs$X.loc <- setup.design(x = location.fun, + data = blocks$data, n = blocks$nBlocks, const = const.loc, + dname = "location.fun") + blocks$designs$X.sc <- setup.design(x = scale.fun, + data = blocks$data, n = blocks$nBlocks, const = const.scale, + dname = "scale.fun") + blocks$designs$X.sh <- setup.design(x = shape.fun, + data = blocks$data, n = blocks$nBlocks, const = const.shape, + dname = "shape.fun") + } + else { + blocks$X.u <- setup.design(x = threshold.fun, + n = blocks$nBlocks, dname = "threshold.fun") + blocks$designs$X.loc <- setup.design(x = location.fun, + n = blocks$nBlocks, const = const.loc, dname = "location.fun") + blocks$designs$X.sc <- setup.design(x = scale.fun, + n = blocks$nBlocks, const = const.scale, dname = "scale.fun") + blocks$designs$X.sh <- setup.design(x = shape.fun, + n = blocks$nBlocks, const = const.shape, dname = "shape.fun") + } + } + if (verbose) + cat("Parameter model design matrices set up.\n") + } + if (is.element(type, c("gp", "pp", "exponential", "beta", + "pareto"))) { + if (method != "lmoments") + threshold <- rowSums(matrix(threshold, n, ncol(X.u), + byrow = TRUE) * X.u) + if (!is.null(blocks)) + blocks$threshold <- rowSums(matrix(blocks$threshold, + blocks$nBlocks, ncol(blocks$X.u), byrow = TRUE) * + blocks$X.u) + excess.id <- x > threshold + if (all(threshold == threshold[1])) + out$threshold <- threshold[1] + else out$threshold <- threshold + out$rate <- mean(excess.id) + } + out$blocks <- blocks + if (method == "lmoments" || find.init) { + if (method == "lmoments") { + if (verbose) + cat("Beginning estimation procedure.\n") + is.constant <- unlist(lapply(list(u = threshold, + loc = location.fun, scale = scale.fun, sh = shape.fun), + check.constant)) + if (!all(is.constant)) + warning("fevd: For method Lmoments, this function does not handle covariates in the parameters. Fitting w/o covariates.") + if (!is.element(type, c("gev", "gp"))) + stop("fevd: currently, Lmoments are only handled for estimation of GEV and GP distribution parameters.") + } + xtemp <- x + class(xtemp) <- "lmoments" + ipars1 <- try(initializer(xtemp, model = type, threshold = threshold, + npy = npy, blocks = blocks), silent = TRUE) + if (class(ipars1) != "try-error") { + if (ipars1["scale"] <= 0) + ipars1["scale"] <- 1e-08 + if (method == "lmoments") { + out$results <- ipars1 + class(out) <- "fevd" + return(out) + } + } + else { + ipars1 <- NULL + if (method == "lmoments") + stop("fevd: Sorry, could not find L-moments estimates.") + } + } + if ((method != "lmoments") && find.init) { + xtemp <- x + class(xtemp) <- "moms" + ipars2 <- try(initializer(xtemp, model = type, threshold = threshold, + npy = npy, blocks = blocks), silent = TRUE) + if (class(ipars2) != "try-error") { + if (ipars2["scale"] <= 0) + ipars2["scale"] <- 1e-08 + } + else ipars2 <- NULL + if (!is.element(type, c("pp", "gp", "exponential", "beta", + "pareto", "gumbel"))) { + if (!is.null(ipars1)) + testLmoments <- levd(x, location = ipars1["location"], + scale = ipars1["scale"], shape = ipars1["shape"], + type = out$type, npy = npy) + else testLmoments <- Inf + if (!is.null(ipars2)) + testMoments <- levd(x, location = ipars2["location"], + scale = ipars2["scale"], shape = ipars2["shape"], + type = out$type, npy = npy) + else testMoments <- Inf + } + else if (type == "pp") { + if (!is.null(ipars1)) { + if (!is.null(blocks)) { + blocks$location = ipars1["location"] + blocks$scale = ipars1["scale"] + blocks$shape = ipars1["shape"] + } + testLmoments <- levd(x, threshold = threshold, + location = ipars1["location"], scale = ipars1["scale"], + shape = ipars1["shape"], type = out$type, npy = npy, + blocks = blocks) + } + else testLmoments <- Inf + if (!is.null(ipars2)) { + if (!is.null(blocks)) { + blocks$location = ipars2["location"] + blocks$scale = ipars2["scale"] + blocks$shape = ipars2["shape"] + } + testMoments <- levd(x, threshold = threshold, + location = ipars2["location"], scale = ipars2["scale"], + shape = ipars2["shape"], type = out$type, npy = npy, + blocks = blocks) + } + else testMoments <- Inf + if (!is.null(blocks)) + blocks$location <- blocks$scale <- blocks$shape <- NULL + } + else if (!is.element(type, c("gumbel", "exponential"))) { + if (!is.null(ipars1)) + testLmoments <- levd(x, threshold = threshold, + scale = ipars1["scale"], shape = ipars1["shape"], + type = out$type, npy = npy) + else testLmoments <- Inf + if (!is.null(ipars2)) + testMoments <- levd(x, threshold = threshold, + scale = ipars2["scale"], shape = ipars2["shape"], + type = out$type, npy = npy) + else testMoments <- Inf + } + else if (type == "gumbel") { + if (!is.null(ipars1)) + testLmoments <- levd(x, location = ipars1["location"], + scale = ipars1["scale"], type = out$type, npy = npy) + else testLmoments <- Inf + if (!is.null(ipars2)) + testMoments <- levd(x, location = ipars2["location"], + scale = ipars2["scale"], type = out$type, npy = npy) + else testMoments <- Inf + } + else if (type == "exponential") { + if (!is.null(ipars1)) + testLmoments <- levd(x, threshold = threshold, + scale = ipars1["scale"], shape = 0, type = out$type, + npy = npy) + else testLmoments <- Inf + if (!is.null(ipars2)) + testMoments <- levd(x, threshold = threshold, + scale = ipars2["scale"], shape = 0, type = out$type, + npy = npy) + else testMoments <- Inf + } + if (is.finite(testLmoments) || is.finite(testMoments)) { + if (testLmoments < testMoments) { + if (is.null(initial$location) && !is.element(type, + c("gp", "exponential", "beta", "pareto"))) + initial$location <- ipars1["location"] + if (is.null(initial$log.scale) && use.phi) + initial$log.scale <- log(ipars1["scale"]) + else if (is.null(initial$scale)) + initial$scale <- ipars1["scale"] + if (!is.element(type, c("gumbel", "exponential")) && + is.null(initial$shape)) + initial$shape <- ipars1["shape"] + if (verbose) + cat("Using Lmoments estimates as initial estimates. Initial value =", + testLmoments, "\n") + } + else { + if (is.null(initial$location) && !is.element(type, + c("gp", "exponential", "beta", "pareto"))) + initial$location <- ipars2["location"] + if (is.null(initial$log.scale) && use.phi) + initial$log.scale <- log(ipars2["scale"]) + else if (is.null(initial$scale)) + initial$scale <- ipars2["scale"] + if (!is.element(type, c("gumbel", "exponential")) && + is.null(initial$shape)) + initial$shape <- ipars2["shape"] + if (verbose) + cat("Initial estimates found where necessary (not from Lmoments). Initial value =", + testMoments, "\n") + } + } + else { + if (is.null(initial$location) && !is.element(type, + c("gp", "exponential", "beta", "pareto"))) + initial$location <- 0 + if (is.null(initial$log.scale) && use.phi) + initial$log.scale <- 0 + else if (is.null(initial$scale)) + initial$scale <- 1 + if (!is.element(type, c("gumbel", "exponential")) && + is.null(initial$shape)) + initial$shape <- 0.01 + warning("fevd: L-moments and Moment initial parameter estimates could not be calculated. Using arbitrary starting values.") + } + inout <- list(Lmoments = list(pars = ipars1, likelihood = testLmoments), + MOM = list(pars = ipars2, likelihood = testMoments)) + } + if (!is.null(initial$location)) { + if (ncol(X.loc) != length(initial$location)) { + if ((length(initial$location) == 1) && ncol(X.loc) > + 1) + initial$location <- c(initial$location, rep(0, + ncol(X.loc) - 1)) + else stop("fevd: initial parameter estimates must have length 1 or number of parameters present. Incorrect number for location parameter.") + } + if (length(initial$location) == 1) + names(initial$location) <- "location" + else names(initial$location) <- paste("mu", 0:(ncol(X.loc) - + 1), sep = "") + } + if (use.phi && (ncol(X.sc) != length(initial$log.scale))) { + if ((length(initial$log.scale) == 1) && ncol(X.sc) > + 1) + initial$log.scale <- c(initial$log.scale, rep(0, + ncol(X.sc) - 1)) + else stop("fevd: initial parameter estimates must have length 1 or number of parameters present. Incorrect number for log(scale) parameter.") + } + else if (!use.phi && (ncol(X.sc) != length(initial$scale))) { + if ((length(initial$scale) == 1) && ncol(X.sc) > 1) + initial$scale <- c(initial$scale, rep(0, ncol(X.sc) - + 1)) + else stop("fevd: initial parameter estimates must have length 1 or number of parameters present. Incorrect number for scale parameter.") + } + if (use.phi) { + if (length(initial$log.scale) == 1) + names(initial$log.scale) <- "log.scale" + else names(initial$log.scale) <- paste("phi", 0:(ncol(X.sc) - + 1), sep = "") + } + else { + if (length(initial$scale) == 1) + names(initial$scale) <- "scale" + else names(initial$scale) <- paste("sigma", 0:(ncol(X.sc) - + 1), sep = "") + } + if (!is.element(type, c("gumbel", "exponential"))) { + if (ncol(X.sh) != length(initial$shape)) { + if ((length(initial$shape) == 1) && ncol(X.sh) > + 1) + initial$shape <- c(initial$shape, rep(0, ncol(X.sh) - + 1)) + else stop("fevd: initial parameter estimates must have length 1 or number of parameters present. Incorrect number for shape parameter.") + } + if (length(initial$shape) == 1) + names(initial$shape) <- "shape" + else names(initial$shape) <- paste("xi", 0:(ncol(X.sh) - + 1), sep = "") + } + if (is.element(method, c("mle", "gmle"))) { + if (use.phi) + init.pars <- c(initial$location, initial$log.scale, + initial$shape) + else init.pars <- c(initial$location, initial$scale, + initial$shape) + if (type == "exponential" && const.scale) { + if (method == "gmle") + warning("Method MLE used.") + res <- list() + excess.id <- x > threshold + mle <- mean(x[excess.id] - threshold[excess.id]) + names(mle) <- "scale" + res$par <- mle + k <- sum(excess.id) + res$n <- k + res$value <- k * (log(mle) + 1) + } + else { + if (!is.null(a <- optim.args)) { + anam <- names(a) + if (!is.element("gr", anam)) { + if (method == "mle") + opt.gr <- grlevd + else opt.gr <- NULL + } + else opt.gr <- a$gr + if (is.null(a$method) && use.phi) + opt.method <- ifelse(is.element(type, c("gev", + "gp", "pp", "gumbel")), "BFGS", "L-BFGS-B") + else opt.method <- a$method + if (is.element(type, c("weibull", "beta", "frechet", + "pareto"))) + opt.method <- "L-BFGS-B" + if (is.element(opt.method, c("L-BFGS-B", "Brent"))) { + if (is.null(a$lower)) { + if (!is.element(type, c("frechet", "pareto"))) + opt.lower <- -Inf + else opt.lower <- c(rep(-Inf, length(init.pars) - + 1), 0) + } + else { + if (is.element(type, c("frechet", "pareto"))) + opt.lower <- c(a$lower[1:(length(init.pars) - + 1)], 0) + else opt.lower <- a$lower + } + if (is.null(a$upper)) { + if (!is.element(type, c("weibull", "beta"))) + opt.upper <- Inf + else opt.upper <- c(rep(Inf, length(init.pars) - + 1), 0) + } + else { + if (is.element(type, c("weibull", "beta"))) + opt.upper <- c(a$upper[1:(length(init.pars) - + 1)], 0) + else opt.upper <- a$upper + } + } + else { + opt.lower <- -Inf + opt.upper <- Inf + } + if (is.null(a$control)) + opt.control <- list() + else opt.control <- a$control + anam <- names(a$control) + if (!is.element("trace", anam) && verbose) + opt.control$trace <- 6 + if (is.null(a$hessian)) + opt.hessian <- TRUE + else opt.hessian <- a$hessian + } + else { + if (method == "mle") + opt.gr <- grlevd + else opt.gr <- NULL + if (is.element(type, c("gev", "gp", "pp", "gumbel"))) + opt.method <- "BFGS" + else opt.method <- "L-BFGS-B" + if (!is.element(type, c("frechet", "pareto"))) + opt.lower <- -Inf + else opt.lower <- c(rep(-Inf, length(init.pars) - + 1), 0) + if (!is.element(type, c("weibull", "beta"))) + opt.upper <- Inf + else opt.upper <- c(rep(Inf, length(init.pars) - + 1), 0) + if (verbose) + opt.control <- list(trace = 6) + else opt.control <- list() + opt.hessian <- TRUE + } + parnames <- names(init.pars) + out$parnames <- parnames + if (verbose && (method != "lmoments")) { + cat("Initial estimates are:\n") + print(init.pars) + cat("Beginning estimation procedure.\n") + } + if (type == "pp" && find.init) { + if (verbose) + cat("\n", "First fitting a GP-Poisson model in order to try to get a good initial estimate as PP likelihoods can be very unstable.\n") + look <- out + look$type <- "GP" + des2 <- designs + des2$X.loc <- NULL + if (!missing(data)) + resGP <- optim(init.pars[-(1:ncol(X.loc))], + oevd, gr = opt.gr, o = look, des = des2, + x = x, data = data, u = threshold, npy = npy, + phi = use.phi, method = opt.method, lower = opt.lower, + upper = opt.upper, control = opt.control, + hessian = opt.hessian) + else resGP <- optim(init.pars[-(1:ncol(X.loc))], + oevd, gr = opt.gr, o = look, des = des2, x = x, + u = threshold, npy = npy, phi = use.phi, method = opt.method, + lower = opt.lower, upper = opt.upper, control = opt.control, + hessian = opt.hessian) + tmpi <- resGP$par + if (is.null(blocks)) { + lrate <- npy * mean(x > threshold) + } + else { + lrate <- sum(x > threshold)/(blocks$nBlocks * + mean(blocks$weights)) + } + xi3 <- tmpi[(ncol(X.sc) + 1):length(tmpi)] + if (!use.phi) + sigma3 <- exp(tmpi[1:ncol(X.sc)] + xi3 * log(lrate)) + else sigma3 <- tmpi[1:ncol(X.sc)] + xi3 * log(lrate) + lp <- lrate^(-xi3) - 1 + if (all(is.finite(lp))) + mu3 <- mean(threshold) - (sigma3/xi3) * lp + else mu3 <- mean(x) + nloc <- ncol(X.loc) + if (length(mu3) < nloc) + mu3 <- c(mu3, rep(0, nloc - length(mu3))) + else mu3 <- mu3[1] + if (!is.null(blocks)) { + blocks$location <- rowSums(matrix(mu3, blocks$nBlocks, + nloc) * blocks$designs$X.loc) + blocks$scale = rowSums(matrix(sigma3, blocks$nBlocks, + ncol(blocks$designs$X.sc)) * blocks$designs$X.sc) + blocks$shape = rowSums(matrix(xi3, blocks$nBlocks, + ncol(blocks$designs$X.sh)) * blocks$designs$X.sh) + } + if (all(is.finite(c(mu3, sigma3, xi3)))) { + testGPmle <- try(levd(x = x, threshold = threshold, + location = rowSums(matrix(mu3, n, nloc) * + X.loc), scale = rowSums(matrix(sigma3, + n, ncol(X.sc)) * X.sc), shape = rowSums(matrix(xi3, + n, ncol(X.sh)) * X.sh), type = "PP", npy = npy, + blocks = blocks), silent = TRUE) + if (class(testGPmle) == "try-error") + testGPmle <- Inf + } + else testGPmle <- Inf + if (!is.null(blocks)) + blocks$location <- blocks$scale <- blocks$shape <- NULL + if (is.finite(testLmoments) || is.finite(testMoments) || + is.finite(testGPmle)) { + if ((testGPmle < testLmoments) && (testGPmle < + testMoments)) { + if (verbose) + cat("\n", "Changing initial estimates to those based on GP MLEs. They are: \n") + if (use.phi) + init.pars <- c(mu3, log(sigma3), xi3) + else init.pars <- c(mu3, sigma3, xi3) + names(init.pars) <- parnames + if (verbose) + print(init.pars) + } + else if (verbose) + cat("\n", "Sticking with originally chosen initial estimates.\n") + } + inout$PoissonGP <- list(pars = c(mu3, sigma3, + xi3), likelihood = testGPmle) + } + if (method == "mle") { + if (!missing(data)) { + res <- optim(init.pars, oevd, gr = opt.gr, + o = out, des = designs, x = x, data = data, + u = threshold, span = span/npy, npy = npy, + phi = use.phi, blocks = blocks, method = opt.method, + lower = opt.lower, upper = opt.upper, control = opt.control, + hessian = opt.hessian) + } + else { + res <- optim(init.pars, oevd, gr = opt.gr, + o = out, des = designs, x = x, u = threshold, + span = span/npy, npy = npy, phi = use.phi, + blocks = blocks, method = opt.method, lower = opt.lower, + upper = opt.upper, control = opt.control, + hessian = opt.hessian) + } + } + else if (method == "gmle") { + if (!missing(data)) { + res <- optim(init.pars, oevdgen, gr = opt.gr, + o = out, des = designs, x = x, data = data, + u = threshold, span = span/npy, npy = npy, + phi = use.phi, blocks = blocks, priorFun = priorFun, + priorParams = priorParams, method = opt.method, + lower = opt.lower, upper = opt.upper, control = opt.control, + hessian = opt.hessian) + } + else { + res <- optim(init.pars, oevdgen, gr = opt.gr, + o = out, des = designs, x = x, u = threshold, + span = span/npy, npy = npy, phi = use.phi, + blocks = blocks, priorFun = priorFun, priorParams = priorParams, + method = opt.method, lower = opt.lower, upper = opt.upper, + control = opt.control, hessian = opt.hessian) + } + } + } + if (is.element("shape", names(res$par))) { + if (is.element(type, c("frechet", "pareto"))) { + res$par["shape"] <- abs(res$par["shape"]) + if (res$par["shape"] == 0) { + warning("fevd: shape parameter estimated to be zero. Re-setting to be 1e16.") + res$par["shape"] <- 1e+16 + } + } + else { + if (is.element(type, c("weibull", "beta"))) + res$par["shape"] <- -abs(res$par["shape"]) + if (res$par["shape"] == 0) { + warning("fevd: shape parameter estimated to be zero. Re-setting to be -1e16.") + res$par["shape"] <- -1e+16 + } + } + } + res$num.pars <- list(location = ncol(designs$X.loc), + scale = ncol(designs$X.sc), shape = ncol(designs$X.sh)) + out$results <- res + } + else if (method == "bayesian") { + if (is.element(type, c("gev", "gumbel", "weibull", "frechet", + "pp"))) { + nloc <- ncol(X.loc) + loc.names <- names(initial$location) + } + else { + nloc <- 0 + loc.names <- NULL + } + nsc <- ncol(X.sc) + if (use.phi && is.null(initial$log.scale)) { + initial$log.scale <- log(initial$scale) + if (nsc == 1) + names(initial$log.scale) <- "log.scale" + else names(initial$log.scale) <- paste("phi", 0:(nsc - + 1), sep = "") + } + # The 6 following lines correspond to the bug fix. The case use.phi = FALSE was not handle properly before + if (use.phi){ + sc.names = names(initial$log.scale) + } + else { + sc.names = names(initial$scale) + } + if (!is.element(type, c("gumbel", "exponential"))) { + nsh <- ncol(X.sh) + sh.names <- names(initial$shape) + } + else { + nsh <- 0 + sh.names <- NULL + } + np <- nloc + nsc + nsh + find.priorParams <- FALSE + if (is.null(priorFun) && is.null(priorParams)) + find.priorParams <- TRUE + else if (is.null(priorFun) && (is.null(priorParams$m) || + is.null(priorParams$v))) + find.priorParams <- TRUE + else if (!is.null(priorFun)) { + if (priorFun == "fevdPriorDefault") { + if (is.null(priorParams)) + find.priorParams <- TRUE + else if (is.null(priorParams$m) || is.null(priorParams$v)) + find.priorParams <- TRUE + } + } + if (is.null(priorFun) || find.priorParams) { + if (is.null(priorFun)) + priorFun <- "fevdPriorDefault" + if (find.priorParams) { + xtemp <- x + class(xtemp) <- "mle" + if (verbose) + cat("\n", "Finding MLE to obtain prior means and variances.\n") + if (missing(data)) { + if (missing(span)) + hold <- initializer(xtemp, u = threshold, + use.phi = use.phi, type = out$type, time.units = time.units, + period.basis = period.basis, blocks = blocks) + else hold <- initializer(xtemp, u = threshold, + use.phi = use.phi, type = out$type, span = span, + time.units = time.units, period.basis = period.basis, + blocks = blocks) + } + else { + if (missing(span)) + hold <- initializer(xtemp, data = data, u = threshold, + u.fun = threshold.fun, loc.fun = location.fun, + sc.fun = scale.fun, sh.fun = shape.fun, + use.phi = use.phi, type = out$type, time.units = time.units, + period.basis = period.basis, blocks = blocks) + else hold <- initializer(xtemp, data = data, + u = threshold, u.fun = threshold.fun, loc.fun = location.fun, + sc.fun = scale.fun, sh.fun = shape.fun, use.phi = use.phi, + type = out$type, span = span, time.units = time.units, + period.basis = period.basis, blocks = blocks) + } + if (is.null(priorParams)) + priorParams <- list(m = hold[1:np], v = rep(10, + np)) + else if (is.null(priorParams$m)) + priorParams$m <- hold[1:np] + else if (is.null(priorParams$v)) + priorParams$v <- rep(10, np) + } + } + out$priorFun <- priorFun + out$priorParams <- priorParams + if (is.null(proposalFun)) { + proposalFun <- "fevdProposalDefault" + if (is.null(proposalParams)) + proposalParams <- list(sd = rep(0.1, np)) + } + out$proposalFun <- proposalFun + out$proposalParams <- proposalParams + chain.info <- matrix(NA, iter, np + 2) + print(dim(chain.info)) + print(c(loc.names, sc.names, sh.names, "loglik", "prior")) + colnames(chain.info) <- c(loc.names, sc.names, sh.names, + "loglik", "prior") + chain.info[2:iter, 1:np] <- 0 + res <- matrix(NA, iter, np + 1) + res[, np + 1] <- 0 + colnames(res) <- c(loc.names, sc.names, sh.names, "new") + if (nloc > 0) + res[1, 1:nloc] <- initial$location + if (use.phi) + res[1, (nloc + 1):(nloc + nsc)] <- initial$log.scale + else res[1, (nloc + 1):(nloc + nsc)] <- initial$scale + if (type != "Gumbel") + res[1, (nloc + nsc + 1):np] <- initial$shape + theta.i <- res[1, 1:np] + if (verbose) { + cat("\n", "Finding log-Likelihood of initial parameter values:\n") + print(theta.i) + } + if (!missing(data)) + ll.i <- -oevd(p = res[1, ], o = out, des = designs, + x = x, data = data, u = threshold, span = span, + npy = npy, phi = use.phi, blocks = blocks) + else ll.i <- -oevd(p = res[1, ], o = out, des = designs, + x = x, u = threshold, span = span, npy = npy, phi = use.phi, + blocks = blocks) + if (verbose) + cat("\n", "Finding prior df value of initial parameter values.\n") + p.i <- do.call(priorFun, c(list(theta = theta.i), priorParams)) + chain.info[1, np + 1] <- ll.i + chain.info[1, np + 2] <- p.i + if (verbose) + cat("\n", "Beginning the MCMC iterations (", iter, + " total iterations)\n") + for (i in 2:iter) { + if (verbose && i <= 10) + cat(i, " ") + if (verbose && i%%100 == 0) + cat(i, " ") + ord <- sample(1:np, np) + theta.star <- theta.i + acc <- 0 + for (j in ord) { + par.star <- do.call(proposalFun, c(list(p = theta.i, + ind = j), proposalParams)) + theta.star[j] <- par.star[j] + if (!missing(data)) + ll.star <- -oevd(p = theta.star, o = out, des = designs, + x = x, data = data, u = threshold, span = span, + npy = npy, phi = use.phi, blocks = blocks) + else ll.star <- -oevd(p = theta.star, o = out, + des = designs, x = x, u = threshold, span = span, + npy = npy, phi = use.phi, blocks = blocks) + prior.star <- do.call(priorFun, c(list(theta = theta.star), + priorParams)) + look <- will.accept(ll.i = ll.i, prior.i = p.i, + ll.star = ll.star, prior.star = prior.star, + log = TRUE) + if (look$accept) { + p.i <- prior.star + ll.i <- ll.star + theta.i <- theta.star + acc <- acc + 1 + chain.info[i, j] <- 1 + } + } + res[i, ] <- c(theta.i, acc) + chain.info[i, (np + 1):(np + 2)] <- c(ll.i, p.i) + } + if (verbose) + cat("\n", "Finished MCMC iterations.\n") + out$results <- res + out$chain.info <- chain.info + } + else stop("fevd: invalid method argument.") + out$initial.results <- inout + if (verbose) + print(Sys.time() - begin.tiid) + if (method == "GMLE") + cl <- "mle" + else cl <- tolower(method) + class(out) <- "fevd" + return(out) +} + diff --git a/extreme_estimator/margin_fits/gev/main_fevd_fixed.R b/extreme_estimator/margin_fits/gev/main_fevd_fixed.R new file mode 100644 index 00000000..9ed5d7e9 --- /dev/null +++ b/extreme_estimator/margin_fits/gev/main_fevd_fixed.R @@ -0,0 +1,83 @@ +# Title : TODO +# Objective : TODO +# Created by: erwan +# Created on: 04/10/2019 +library(extRemes) +library(stats4) +library(SpatialExtremes) +source('myfevd.R') +# Sample from a GEV +set.seed(42) +N <- 1000 +loc = 0; scale = 1; shape <- 0.1 +x_gev <- rgev(N, loc = loc, scale = scale, shape = shape) + +# fevdPriorMy <- function (theta, q, p, log = FALSE){ +# x = theta["shape"] + 0.5 +# +# print(theta) +# print(theta["location"]) +# print(dunif(theta["location"])) +# print(theta[0]) +# dfun <- function(th) dbeta(th[1], shape1 = th[2], shape2 = th[3], +# log = log) +# th <- cbind(theta, q, p) +# res <- apply(th, 1, dfun) +# return(prod(res)) +# } + +fevdPriorMyMy <- function (theta, q, p, log = FALSE){ + # print(theta) + # print(q) + # print(p) + x = theta[length(theta)] + # + 0.5 enables to shift the Beta law in the interval [-0.5, 0.5] + res = dbeta(x + 0.5, q, p, log = TRUE) + return(res) +} + +print(pbeta(1.0, 1, 1)) +print(pbeta(0.5, 1, 1)) +print(fevdPriorMyMy(2.0, 0.0, 0.0)) + + + + +# res = fevd(x_gev, method='Bayesian', priorFun="fevdPriorMyMy", priorParams=list(q=c(6), p=c(9)), iter=5000, verbose=TRUE, use.phi=FALSE) +res = fevd_fixed(x_gev, method='Bayesian', priorFun="fevdPriorMyMy", priorParams=list(q=c(6), p=c(9)), iter=5000, verbose=TRUE, use.phi=FALSE) +# res = fevd(x_gev, method='GMLE', iter=5000, verbose=TRUE, use.phi=FALSE) +print(res) + + +print(res$method) +print(res$priorFun) +print(res$priorParams) +m = res$results +print(dim(m)) +print(m) +print(m[1,]) +print(m[1,1]) + + + + +# print(class(res$chain.info)) +# ch = res$chain.info +# print(dim(ch)) +# print(ch) + +# # summary(res) +print(attributes(res)) +# print('here') +# print(attr(res, 'chain.info')) +# print(attr(res, "method")) +# print(attr(res, "x")) +# print(attr(res, "priorParams")) + +# print(res.method) + + + + +# Bayesian method is using a normal distribution functions for the shape parameter +# GMLE distribution is using a Beta distribution for the shape parameter -- GitLab