我管理一个内部代码库,它严重依赖于glmnet
包。在升级到最新版本(v3.0.2
)后,我的Cox模型的系数单元测试开始失败。之前的glmnet
版本是v2.0.16 (R 3.5.2)
。我现在运行的是R v3.6.2
。
我注意到有一个新的relax =
参数,它似乎在路径中使用了非正则化拟合,我认为这可能会导致拟合的轻微差异,但是默认值是relax = FALSE
,所以我怀疑这不是问题所在。
以下是一个基于mtcars
数据集的reprex
,拟合了两个随机选择的特征,并将两个变量重命名为time
和status
,以便能够拟合Cox模型。由于需要不同的R安装,正确的reprex比较很难,但这应该可以让任何人重现这个问题。
library(magrittr)library(dplyr)library(glmnet)dat <- mtcars %>% select(mpg, disp, status = vs, time = hp) %>% # 选择2个特征;分配时间和状态 mutate_at(1:2, ~ { log10(.x) %>% subtract(mean(.)) %>% divide_by(sd(.)) # 中心化和缩放 }) %>% as.matrix()glmnet(dat[, 1:2], dat[, 3:4], family = "cox", lambda = 0)$beta # 拟合模型
v3.0.2
的结果是:
#> 2 x 1 sparse Matrix of class "dgCMatrix"#> s0#> mpg 0.2293535#> disp -1.8160387
v2.0.16
的结果是:
#> 2 x 1 sparse Matrix of class "dgCMatrix"#> s0#> mpg 0.2154324#> disp -1.8172714
其他人是否也注意到了类似的差异?我有些惊讶没有发现其他人遇到同样的问题。我是否需要更新我所有的单元测试 🙁
非常感谢您的见解和/或解释。提前谢谢您。
回答:
评论稍微有点长:
- 我在Ubuntu 16.04上重现了你的结果(使用
devtools::install_version()
,见下文)。 - 从2.0-16到3.0-2跨越了几个版本(还有几个内部标记的未发布版本):NEWS文件多次提到了
coxnet
(可能是内部调用的函数,用于family="cox"
:- 2.0-20:
- 修复了内部函数coxnet.deviance中关于输入pred的错误,以及饱和对数似然(缺失)和权重
- 添加了一个coxgrad函数用于计算梯度
- 2.0-19: 修复了coxnet中关于死亡集和风险集之间联系的错误
- 2.0-20:
我建议使用
devtools::install_version("glmnet",version=...,lib=<version-specific>)
来安装从2.0-16到3.0-2(包括)之间的每一个版本,每个版本都安装在一个单独的库中,这样通过library("glmnet", lib.loc=...
可以轻松加载不同的包版本,并通过二分法找到具体的变化。(中间版本未发布,所以你会从2.0-18跳到3.0。)
我猜是那些coxnet
bug修复之一(有意或作为副作用)导致了这些变化。
如果它在一个可访问的git存储库中,你可以使用git bisect
和本地副本来自动化这个过程(对于如此少的变更点可能不值得,但看起来开发树不可用:有一个很好的pkgdown网站,但我没有看到任何链接到版本控制系统的链接。
如果你有很多时间,你可以下载所有存档的tarball并搜寻其中的变化…