2013-06-18 27 views
0

我只是真的嘗試在R中編寫MLE命令,它的功能與外部R函數類似。在這種嘗試我試圖做一個簡單的MLE與在R中寫入我自己的MLE命令導致問題

Y = B0 + X * B1 + U

U〜N(0,SD = S0 + Z * S1)

但是,即使是這樣一個簡單的命令,我也很難編碼。我在Stata in a handful of lines

這裏寫了一個類似的命令是我在R.

normalreg <- function (beta, sigma=NULL, data, beta0=NULL, sigma0=NULL, 
         con1 = T, con2 = T) { 

    # If a formula for sigma is not specified 
    # assume it is the same as the formula for the beta. 
    if (is.null(sigma)) sigma=beta 

    # Grab the call expression 
    mf <- match.call(expand.dots = FALSE) 

    # Find the position of each argument 
    m <- match(c("beta", "sigma", "data", "subset", "weights", "na.action", 
       "offset"), names(mf), 0L) 

    # Adjust names of mf 
    mf <- mf[c(1L, m)] 

    # Since I have two formulas I will call them both formula 
    names(mf)[2:3] <- "formula" 

    # Drop unused levels 
    mf$drop.unused.levels <- TRUE 

    # Divide mf into data1 and data2 
    data1 <- data2 <- mf 
    data1 <- mf[-3] 
    data2 <- mf[-2] 

    # Name the first elements model.frame which will be 
    data1[[1L]] <- data2[[1L]] <- as.name("model.frame") 

    data1 <- as.matrix(eval(data1, parent.frame())) 
    data2 <- as.matrix(eval(data2, parent.frame())) 

    y  <- data1[,1] 
    data1 <- data1[,-1] 
    if (con1) data1 <- cbind(data1,1) 
    data2 <- unlist(data2[,-1]) 
     if (con2) data2 <- cbind(data2,1) 

    data1 <- as.matrix(data1) # Ensure our data is read as matrix 
    data2 <- as.matrix(data2) # Ensure our data is read as matrix 

    if (!is.null(beta0)) if (length(beta0)!=ncol(data1)) 
     stop("Length of beta0 need equal the number of ind. data2iables in the first equation") 

    if (!is.null(sigma0)) if (length(sigma0)!=ncol(data2)) 
     stop("Length of beta0 need equal the number of ind. data2iables in the second equation") 

    # Set initial parameter estimates 
    if (is.null(beta0)) beta0 <- rep(1, ncol(data1)) 
    if (is.null(sigma0)) sigma0 <- rep(1, ncol(data2)) 

    # Define the maximization function 
    normMLE <- function(est=c(beta0,sigma0), data1=data1, data2=data2, y=y) {   
     data1est <- as.matrix(est[1:ncol(data1)], nrow=ncol(data1)) 
     data2est <- as.matrix(est[(ncol(data1)+1):(ncol(data1)+ncol(data2))], 
           nrow=ncol(data1)) 

     ps <-pnorm(y-data1%*%data1est, 
         sd=data2%*%data2est) 
     # Estimate a vector of log likelihoods based on coefficient estimates 
     llk <- log(ps) 
     -sum(llk) 
    } 

    results <- optim(c(beta0,sigma0), normMLE, hessian=T, 
        data1=data1, data2=data2, y=y) 

    results 
    } 


    x <-rnorm(10000) 
    z<-x^2 
    y <-x*2 + rnorm(10000, sd=2+z*2) + 10 

    normalreg(y~x, y~z) 

至今寫在這一點上,最大的問題是找到一個優化程序不失敗時,一些代碼當標準偏差變爲負值時,這些值返回NA。有什麼建議麼?對不起,代碼量很大。

Francis

+2

你可以使用'日誌()' /'exp()'技巧來強制sd正面。很顯然,sd不能是負面的,所以這會引發錯誤嗎?當你爲R提供初始值時,首先對它們進行轉換(例如,你認爲sd = 5,所以提供'log(5)')。在MLE函數內部,指定sd(so'exp()''log(5)')。這迫使它積極。當你去解釋模型擬合時,再次使用估計的log()。 – rbatt

+0

好主意。我試着玩abs(),雖然它似乎糾正了這個具有NAs的特殊問題,儘管增加了樣本,但它並沒有收斂在任何接近真實參數的東西上。這表明我做錯了什麼。 – fsmart

+0

我認爲optim()中的BFGS選項讓你設置參數約束。但是,這並不能保證這會有所幫助。您可能需要仔細查看模型和數據,並查看模型是否適當地制定。但我無法確定。 – rbatt

回答

2

我包括檢查以查看是否有任何的標準偏差均小於或等於0並返回似0程度,如果是這樣的話。似乎爲我工作。你可以弄清楚將它包裝到你的函數中的細節。

#y=b0 + x*b1 + u 
#u~N(0,sd=s0 + z*s1) 

ll <- function(par, x, z, y){ 
    b0 <- par[1] 
    b1 <- par[2] 
    s0 <- par[3] 
    s1 <- par[4] 
    sds <- s0 + z*s1 
    if(any(sds <= 0)){ 
     return(log(0)) 
    } 

    preds <- b0 + x*b1 

    sum(dnorm(y, preds, sds, log = TRUE)) 
} 

n <- 100 
b0 <- 10 
b1 <- 2 
s0 <- 2 
s1 <- 2 
x <- rnorm(n) 
z <- x^2 
y <- b0 + b1*x + rnorm(n, sd = s0 + s1*z) 

optim(c(1,1,1,1), ll, x=x, z=z,y=y, control = list(fnscale = -1)) 

隨着中說,它可能不會是一個壞主意參數以這樣的方式,這是不可能去負的標準差......