2011-06-23 13 views
8

Tôi đã gặp khó khăn khi hiểu tài liệu về cách thức gọi S3, và lần này nó cắn tôi trở lại.S3 và thứ tự của các lớp

Tôi xin lỗi trước vì đã hỏi nhiều câu hỏi nhưng tất cả đều có liên quan chặt chẽ. Sâu trong trái tim của một tập hợp các hàm phức tạp, tôi tạo ra rất nhiều phù hợp với glmnet, đặc biệt là các logistic. Bây giờ, tài liệu glmnet chỉ định giá trị trả lại của nó để có cả hai lớp "glmnet" và (đối với hồi quy logistic) "lognet". Trong thực tế, chúng được xác định theo thứ tự này.

Tuy nhiên, hãy xem kết thúc việc triển khai glmnet, sau khi cuộc gọi đến (chức năng nội bộ) lognet, đặt lớp fit thành "lognet", tôi thấy dòng mã này ngay trước khi trả lại (của biến fit):

class(fit) = c(class(fit), "glmnet") 

Từ đó, tôi sẽ kết luận rằng thứ tự của các lớp là trong thực tế "lognet", "glmnet".

Thật không may, phù hợp tôi đã có, đã có (như doc gợi ý):

> class(myfit) 
[1] "glmnet" "lognet" 

Vấn đề ở đây là cách phương pháp S3 được cử cho nó, đặc biệt là predict. Đây là mã cho predict.lognet:

function (object, newx, s = NULL, type = c("link", "response", 
    "coefficients", "class", "nonzero"), exact = FALSE, offset, 
    ...) 
{ 
    type = match.arg(type) 
    nfit = NextMethod("predict") #<- supposed to call predict.glmnet, I think 
    switch(type, response = { 
     pp = exp(-nfit) 
     1/(1 + pp) 
    }, class = ifelse(nfit > 0, 2, 1), nfit) 
} 

Tôi đã thêm nhận xét để giải thích lý do của tôi. Bây giờ khi tôi gọi dự đoán trên myfit này với một Datamatrix mới mydatatype="response", như thế này:

predict(myfit, newx=mydata, type="response") 

, tôi không, theo các tài liệu, được xác suất dự đoán, nhưng sự kết hợp tuyến tính, mà là chính xác kết quả của việc gọi predict.glmnet ngay lập tức.

tôi đã cố gắng đảo ngược thứ tự của các lớp học, như vậy:

orgclass<-class(myfit) 
class(myfit)<-rev(orgclass) 

Và sau đó thực hiện các dự đoán gọi lại: lo and behold: nó hoạt động! Tôi làm nhận được xác suất.

Vì vậy, ở đây đến một số câu hỏi:

  1. Tôi có ngay trong 'đã học được' mà S3 phương pháp được cử theo thứ tự sự xuất hiện của các lớp?
  2. Tôi có thể giả định mã số trong glmnet sẽ gây ra thứ tự sai để gửi đi chính xác predict?
  3. Trong mã của tôi, không có gì là thao túng các lớp học một cách rõ ràng/rõ ràng với kiến ​​thức của tôi. Điều gì có thể khiến đơn đặt hàng đến số thay đổi?

Đối với đầy đủ lợi ích: đây là một số mẫu mã để chơi xung quanh với (như tôi đang làm bản thân mình bây giờ):

library(glmnet) 
y<-factor(sample(2, 100, replace=TRUE)) 
xs<-matrix(runif(100), ncol=1) 
colnames(xs)<-"x" 
myfit<-glmnet(xs, y, family="binomial") 
mydata<-matrix(runif(10), ncol=1) 
colnames(mydata)<-"x" 
class(myfit) 
predict(myfit, newx=mydata, type="response") 
class(myfit)<-rev(class(myfit)) 
class(myfit) 
predict(myfit, newx=mydata, type="response") 
class(myfit)<-rev(class(myfit))#set it back 
class(myfit) 

Tùy thuộc vào dữ liệu được tạo ra, sự khác biệt là nhiều hơn hoặc ít rõ ràng (trong tập dữ liệu thực sự của tôi, tôi nhận thấy các giá trị âm trong cái gọi là xác suất, đó là cách tôi đã chọn vấn đề), nhưng bạn thực sự sẽ thấy sự khác biệt.

Cảm ơn mọi đầu vào.

Sửa:

Tôi vừa phát hiện ra sự thật khủng khiếp: hoặc để làm việc trong glmnet 1.5.2 (đó là hiện tại trên máy chủ nơi tôi chạy mã thực tế, kết quả là phù hợp với thứ tự lớp đảo ngược), nhưng mã từ 1.6 yêu cầu thứ tự là "lognet", "glmnet". Tôi chưa kiểm tra những gì xảy ra trong 1.7.

Nhờ @Aaron để nhắc tôi về các khái niệm cơ bản về tin học (bên cạnh 'nếu mọi thứ khác không thành công, hãy khởi động lại': 'kiểm tra phiên bản của bạn'). Tôi đã nhầm tưởng rằng một gói của các vị thần học tập thống kê sẽ được bảo vệ khỏi loại lỗi này), và để @Gavin xác nhận việc tái thiết của tôi về cách thức S3 hoạt động.

+2

Khi tôi chạy mã, tôi nhận được lệnh "" lognet "" glmnet "' sau lệnh gọi 'lớp' đầu tiên, ngược lại với những gì bạn nói. Tôi có glmnet 1.7; bạn có phiên bản nào – Aaron

Trả lời

6

Có, thứ tự của công văn là theo thứ tự các lớp được liệt kê trong thuộc tính lớp. Trong trường hợp đơn giản, mỗi ngày, có, lớp được khai báo đầu tiên là lớp được chọn đầu tiên bằng cách gửi phương thức và chỉ khi không tìm được phương thức cho lớp đó (hoặc NextMethod được gọi), nó sẽ chuyển sang lớp thứ hai hoặc không tìm kiếm phương thức default.

Không, tôi không nghĩ bạn đúng là thứ tự của các lớp là sai trong mã. Tài liệu xuất hiện sai. Mục đích rõ ràng là gọi predict.lognet() trước tiên, sử dụng Workhorse predict.glmnet() để thực hiện các tính toán cơ bản cho tất cả các loại mô hình lưới thu nhỏ/đàn hồi được trang bị glmnet và cuối cùng thực hiện một số xử lý hậu kỳ của các dự đoán chung đó. Điều đó predict.glmnet()không phải được xuất từ ​​glmnet NAMESPACE trong khi các phương pháp khác có lẽ cũng đang được nói.

Tôi không chắc chắn lý do tại sao bạn nghĩ rằng sản lượng từ này:

predict(myfit, newx=mydata, type="response") 

là sai? Tôi nhận được một ma trận gồm 10 hàng và 21 cột, với các cột liên quan đến dự đoán mô hình chặn chỉ cộng với dự đoán tại 20 giá trị lambda mà tại đó các hệ số mô hình dọc theo đường dẫn net/đàn hồi đã được tính toán. Đây có vẻ không phải là kết hợp tuyến tính và là một tỷ lệ phản hồi theo yêu cầu của bạn.

Thứ tự của các lớp học không thay đổi. Tôi nghĩ rằng bạn đang hiểu lầm cách mã được cho là hoạt động. Có một lỗi trong tài liệu, vì thứ tự được nêu sai ở đó. Nhưng mã đang hoạt động như tôi nghĩ.

+0

Câu trả lời tuyệt vời, nhưng một nhỏ niggle: bạn không thể thay đổi các lớp học trong quá trình công văn: https://gist.github.com/1043952 (tốt bạn có thể, nó chỉ không ảnh hưởng đến công văn) – hadley

+0

Ngoài ra, nó có vẻ rằng ý định là 'predict_kết.lognet' rồi' predict.glmnet'. Nhưng khi tôi đọc nó, OP nói nó đang chạy 'predict.glmnet' đầu tiên trên hệ thống của mình bởi vì thứ tự của các lớp được đảo ngược. – Aaron

+0

@hadley cảm ơn vì đã chỉ ra điều đó. Tôi phải có sai lầm đó. Đã sửa lỗi. –