Glmnet sử dụng sai lệch nào để so sánh các giá trị của ?


8

Một tiêu chí để chọn giá trị tối ưu của với mạng đàn hồi hoặc hồi quy bị phạt tương tự là kiểm tra sơ đồ sai lệch so với phạm vi của và chọn khi độ lệch được giảm thiểu (hoặc trong một lỗi tiêu chuẩn của tối thiểu).bước sóng bước sóng bước sóngλλλλ

Tuy nhiên, tôi đang gặp khó khăn trong việc hiểu chính xác những gì glmnethiển thị với plot.cv.glmnet, bởi vì cốt truyện được hiển thị hoàn toàn không giống với kết quả của âm mưu chống lại .λ

set.seed(4567)
N       <- 500
P       <- 100
coefs   <- NULL
for(p in 1:P){
    coefs[p]    <- (-1)^p*100*2^(-p)
}
inv.logit <- function(x) exp(x)/(1+exp(x))
X   <- matrix(rnorm(N*P), ncol=P, nrow=N)
Y   <- rbinom(N, size=1, p=inv.logit(cbind(1, X)%*%c(-4, coefs)))
plot(test   <- cv.glmnet(x=X, y=Y, family="binomial", nfolds=10, alpha=0.8))
plot(log(test$lambda), deviance(test$glmnet.fit))

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Có vẻ như âm mưu thứ hai không kết hợp hình phạt ròng đàn hồi, và cũng được chia tỷ lệ không chính xác theo chiều dọc. Tôi dựa trên yêu cầu dựa trên cơ sở rằng hình dạng của đường cong cho các giá trị lớn hơn của giống với đầu ra. Tuy nhiên, khi tôi cố gắng tự mình tính toán hình phạt, nỗ lực của tôi cũng có vẻ không chính xác.λglmnet

penalized.dev.fn    <- function(lambda, alpha=0.2, data, cv.model.obj){
    dev <- deviance(cv.model.obj$glmnet.fit)[seq_along(cv.model.obj$lambda)[cv.model.obj$lambda==lambda]]
    beta <- coef(cv.model.obj, s=lambda)[rownames(coef(cv.model.obj))!="(Intercept)"]
    penalty <- lambda * ( (1-alpha)/2*(beta%*%beta) + alpha*sum(abs(beta)) )
    penalized.dev <- penalty+dev
    return(penalized.dev)
}

out <- sapply(test$lambda, alpha=0.2, cv.model.obj=test, FUN=penalized.dev.fn)
    plot(log(test$lambda), out)

Câu hỏi của tôi là: làm thế nào để tính toán thủ công độ lệch được báo cáo trong plot.cv.glmnetsơ đồ mặc định ? Công thức của nó là gì và tôi đã làm gì sai trong nỗ lực tính toán nó?


Bạn có biết rằng cv.glmnetđang thực hiện xác nhận chéo 10 lần, phải không? Vì vậy, đó là âm mưu trung bình +/- 1 lỗi chuẩn của độ lệch trên dữ liệu giữ 10%?
Andrew M

Tôi nhận thức được điều này, vâng.
Sycorax nói phục hồi Monica

Câu trả lời:


6

Tôi chỉ muốn thêm vào đầu vào, nhưng hiện tại không có câu trả lời ngắn gọn và quá dài cho một nhận xét. Hy vọng điều này cho cái nhìn sâu sắc hơn.

Có vẻ như chức năng quan tâm nằm trong thư viện glmnet đã giải nén và được gọi là cv.lognet.R Thật khó để theo dõi rõ ràng mọi thứ, như trong mã S3 / S4, nhưng chức năng trên được liệt kê dưới dạng 'chức năng glmnet bên trong , 'được sử dụng bởi các tác giả và dường như khớp với cách cv.glmnet đang tính toán độ lệch nhị thức.

Mặc dù tôi không thấy nó ở bất cứ đâu trên tờ giấy, từ truy tìm mã glmnet đến cv.lognet, điều tôi thu thập được là nó đang sử dụng thứ gọi là sai lệch nhị thức được mô tả ở đây .

[Ylog10(E)+(1Y)log10(1E)]

tiền tố là một ma trận của các giá trị xác suất giới hạn (E, 1-E) cho mỗi lambda, được so sánh với các giá trị bổ sung của y và y dẫn đến lp. Sau đó, chúng được đặt ở dạng lệch 2 * (ly-lp) và tính trung bình trên các nếp gấp được xác thực chéo để lấy cvm - Lỗi xác thực chéo trung bình - và phạm vi cv, mà bạn đã vẽ trong hình ảnh đầu tiên.

Tôi nghĩ rằng chức năng lệch thủ công (ô thứ 2) không được tính giống như hàm nội bộ này (ô thứ 1).

    # from cv.lognet.R

    cvraw=switch(type.measure,
    "mse"=(y[,1]-(1-predmat))^2 +(y[,2]-predmat)^2,
    "mae"=abs(y[,1]-(1-predmat)) +abs(y[,2]-predmat),
    "deviance"= {
      predmat=pmin(pmax(predmat,prob_min),prob_max)
      lp=y[,1]*log(1-predmat)+y[,2]*log(predmat)
      ly=log(y)
      ly[y==0]=0
      ly=drop((y*ly)%*%c(1,1))
      2*(ly-lp)

   # cvm output
   cvm=apply(cvraw,2,weighted.mean,w=weights,na.rm=TRUE)

Cảm ơn bạn đã trả lời, vỗ. Điều này giải quyết tất cả các câu hỏi mà tôi có về cách thức hoạt động của quy trình và các khái niệm thống kê cơ bản, không chỉ phần mềm.
Sycorax nói Phục hồi lại

2

Vì vậy, tôi đã truy cập trang web CRAN và tải xuống những gì tôi nghĩ là nguồn của gói glmnet . Trong ./glmnet/R/plot.cv.glmnet.R có vẻ như bạn sẽ tìm thấy mã nguồn mà bạn đang theo dõi. Nó khá ngắn gọn vì vậy tôi sẽ dán ở đây nhưng có lẽ tốt nhất nếu bạn tự kiểm tra để chắc chắn rằng đó thực sự là mã đang chạy.

plot.cv.glmnet=function(x,sign.lambda=1,...){
  cvobj=x
  xlab="log(Lambda)"
  if(sign.lambda<0)xlab=paste("-",xlab,sep="")
  plot.args=list(x=sign.lambda*log(cvobj$lambda),y=cvobj$cvm,ylim=range(cvobj$cvup,cvobj$cvlo),xlab=xlab,ylab=cvobj$name,type="n")
      new.args=list(...)
      if(length(new.args))plot.args[names(new.args)]=new.args
    do.call("plot",plot.args)
    error.bars(sign.lambda*log(cvobj$lambda),cvobj$cvup,cvobj$cvlo,width=0.01,col="darkgrey")
  points(sign.lambda*log(cvobj$lambda),cvobj$cvm,pch=20,col="red")
axis(side=3,at=sign.lambda*log(cvobj$lambda),labels=paste(cvobj$nz),tick=FALSE,line=0)
abline(v=sign.lambda*log(cvobj$lambda.min),lty=3)
    abline(v=sign.lambda*log(cvobj$lambda.1se),lty=3)
  invisible()
}

1
Các phương thức S3 hơi bị ẩn trong R, nhưng để xem chính xác những gì đang chạy, bạn có thể nhập getS3method('plot', 'cv.glmnet')mà không gặp sự cố khi tải xuống gói nguồn. (Bên trong, glmnetvừa xác định một hàm được gọi plot.cv.glmnetnhưng chưa xuất nó. Bạn vẫn có thể thấy nó bằng cách nhìn trộm bên trong bảng tên với :::toán tử glmnet:::plot.cv.glmnet:).
Andrew M

(+1) Cảm ơn bạn đã trả lời, Diego. Điều này chỉ cho tôi đi đúng hướng, và ngầm chỉ ra tôi đã sai ở đâu. Tuy nhiên, hiện tại tôi sẽ không thể chấp nhận vì điều này không trả lời câu hỏi thống kê cụ thể (phó lập trình), được nêu ở cuối bài viết của tôi.
Sycorax nói phục hồi Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.