我总是无法理解有关如何调用S3方法的文档,而这次它正在咬我.
我会在前面道歉,提出不止一个问题,但他们都是密切相关的.在一系列复杂功能的核心深处,我创造了许多glmnet
契合,特别是后勤功能.现在,glmnet
文档指定其返回值以使类"glmnet"和(对于逻辑回归)"lognet".实际上,这些是按此顺序指定的.
但是,看看执行结束glmnet
后,调用(内部函数)之后的righter lognet
,将类设置fit
为"lognet",我在返回(变量fit
)之前看到这行代码:
class(fit) = c(class(fit), "glmnet")
Run Code Online (Sandbox Code Playgroud)
由此,我得出结论,类的顺序实际上是"lognet","glmnet".
不幸的是,我曾经拥有过(就像文档建议的那样):
> class(myfit)
[1] "glmnet" "lognet"
Run Code Online (Sandbox Code Playgroud)
这方面的问题是特别是为它调度S3方法的方式predict
.这是以下代码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)
}
Run Code Online (Sandbox Code Playgroud)
我添加了一条评论来解释我的推理.现在,当我打电话预测这个myfit
用新的数据矩阵mydata
和type="response"
,就像这样:
predict(myfit, newx=mydata, type="response")
Run Code Online (Sandbox Code Playgroud)
,根据文档,我不会得到预测的概率,但是线性组合,这正是predict.glmnet
立即调用的结果.
我试过颠倒类的顺序,如下:
orgclass<-class(myfit)
class(myfit)<-rev(orgclass)
Run Code Online (Sandbox Code Playgroud)
然后再次做预测电话:瞧瞧:它有效!我确实得到了概率.
所以,这里有一些问题:
glmnet
会导致错误的顺序正确派遣
predict
?为了完整起见:这里有一些示例代码(正如我现在自己做的那样):
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)
Run Code Online (Sandbox Code Playgroud)
根据生成的数据,差异或多或少是显而易见的(在我的真实数据集中,我注意到所谓的概率中的负值,这就是我提出问题的方式),但你确实应该看到差异.
感谢您的任何意见.
编辑:
我刚刚发现了一个可怕的事实:无论是在glmnet 1.5.2中运行的命令(它存在于运行实际代码的服务器上,导致与类顺序相反),但1.6中的代码需要命令是"lognet","glmnet".我还没有检查1.7中发生的事情.
感谢@Aaron提醒我信息学的基础知识(除了'如果所有其他方法都失败了,重启':'检查你的版本').我错误地认为统计学习之神的包装将受到保护,免受此类错误的影响),并且@Gavin确认我重建了S3的工作方式.
是的,调度顺序是在类属性中列出类的顺序.在简单的,每天的情况下,是的,第一个声明的类是首先通过方法调度选择的类,并且只有当它找不到该类的方法(或被NextMethod
调用)时才会转移到第二个类,或者没有找到default
方法.
不,我不认为你的代码顺序错误是正确的.文档显示错误.目的显然是predict.lognet()
首先调用,使用主力predict.glmnet()
对glmnet所安装的所有类型的套索/弹性网模型进行基本计算,最后对这些一般预测进行一些后处理.这predict.glmnet()
是不是从出口glmnet NAMESPACE而其他方法也许是告诉,也.
我不确定你为什么认为这个输出:
predict(myfit, newx=mydata, type="response")
Run Code Online (Sandbox Code Playgroud)
是错的?我得到10行和21列的矩阵,其中列与仅截距模型预测相关,加上在20个λ值的预测,在该值处计算了沿套索/弹性网路径的模型系数.这些似乎不是线性组合,并且是您请求的响应比例.
类的顺序没有改变.我认为你误解了代码应该如何工作.文档中有一个错误,因为那里的排序错误.但是代码正在按照我的想法运作.