带(x-location)/scale>0约束的MLE优化:L-BFGS-B报错求解
Let's break down why you're hitting this error and fix it step by step.
The Root Cause
Your initial parameter c(100, 1000, 10) violates the critical constraint (x - location)/scale > 0:
- Your generated
xvalues come from a Pearson III distribution withlocation=6and positivescale=7, so allxare slightly larger than 6. - With
location=1000and positivescale=10,x - locationis negative for every data point. This makesssgn*(x-location)negative, anddgamma()returnsNaNwhen given negative inputs. - Taking
log(NaN)givesNaN, so your negative log-likelihood (tmp) becomesNaN, which your code converts to+Inf. L-BFGS-B can't handle non-finite function values, hence the error.
Step-by-Step Fixes
1. Guard Against Invalid Parameters in the Log-Likelihood Function
Modify your LL3 function to check constraints before computing the density. If parameters violate the constraint, return a large finite value (instead of Inf) to guide the optimizer away from bad regions:
LL3 <- function(theta, x, display) { shape <- as.numeric(theta[1]) location <- as.numeric(theta[2]) scale <- as.numeric(theta[3]) # Check shape is positive (required for gamma distribution) if (shape <= 1e-6) { return(1e10) } # Enforce (x - location)/scale > 0 for all x if (scale > 0) { # All x must be > location → location < min(x) if (location >= min(x)) { return(1e10) } } else if (scale < 0) { # All x must be < location → location > max(x) if (location <= max(x)) { return(1e10) } } else { # Scale can't be zero return(1e10) } # Compute negative log-likelihood only if parameters are valid dens_vals <- dpearson3(x, shape, location, scale, log = FALSE) tmp <- -sum(log(dens_vals)) # Fallback for any unexpected NaNs tmp <- ifelse(is.na(tmp), 1e10, tmp) if(display == 1){print(c(tmp, theta))} return(tmp) }
Note: I removed the redundant sum(tmp) since tmp is already a sum of log densities.
2. Tighten Parameter Bounds for L-BFGS-B
Since your data was generated with a positive scale, we can restrict the optimizer to only consider positive scales and valid locations. This reduces the chance of it wandering into invalid regions:
x_min <- min(x) x_max <- max(x) # Set bounds: shape > 0, location < min(x), scale > 0 lower <- c(1e-6, -Inf, 1e-6) upper <- c(Inf, x_min - 1e-6, Inf)
3. Use a Reasonable Initial Parameter
Your original starting point was way outside the valid region. Pick initial values that satisfy the constraint:
# Start with values close to the true parameters (or at least valid) param <- c(5, 5, 5)
4. Run the Optimizer
Now your optim call should work without errors:
control.list <- list(maxit = 100000, factr=1e-12, fnscale = 1) fit <- optim(par = param, fn = LL3, hessian = TRUE, method = "L-BFGS-B", lower = lower, upper = upper, control = control.list, x = x, display = 1) # Check the results fit$par
You should get estimates close to the true values shape=5, location=6, scale=7.
Why This Works
- The pre-checks in
LL3prevent the optimizer from ever computing non-finite values. - Tighter bounds guide L-BFGS-B to focus only on valid parameter space.
- A valid initial start ensures the optimizer begins in a region where the log-likelihood is finite.
内容的提问来源于stack exchange,提问作者Andrew

