前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >「R」屠“模”记

「R」屠“模”记

作者头像
王诗翔呀
发布2020-07-02 23:04:20
发布2020-07-02 23:04:20
69000
代码可运行
举报
文章被收录于专栏:优雅R优雅R
运行总次数:0
代码可运行

在使用 R 处理逻辑回归建模问题时发现保存的模型对象非常之大,不可思议。正常情况下,我们建模之后所需要的就是模型的系数,以此对新的数据进行预测。当然,为了方便获取和处理一些模型信息,可能有一些汇总或关键的参数信息。

但是,模型结果大小远超乎我的想象,有必要彻查一番

为了了解逻辑回归模型结果中到底存储了什么信息,我先造一个简单的模型。

简单起见,我使用 Cookbook for R 中的【逻辑回归】[1]一节的第一个例子。

代码语言:javascript
代码运行次数:0
复制
data(mtcars)
dat <- subset(mtcars, select = c(mpg, am, vs))
dat
#>                      mpg am vs
#> Mazda RX4           21.0  1  0
#> Mazda RX4 Wag       21.0  1  0
#> Datsun 710          22.8  1  1
#> Hornet 4 Drive      21.4  0  1
#> Hornet Sportabout   18.7  0  0
#> Valiant             18.1  0  1
#> Duster 360          14.3  0  0
#> Merc 240D           24.4  0  1
#> Merc 230            22.8  0  1
#> Merc 280            19.2  0  1
#> Merc 280C           17.8  0  1
#> Merc 450SE          16.4  0  0
#> Merc 450SL          17.3  0  0
#> Merc 450SLC         15.2  0  0
#> Cadillac Fleetwood  10.4  0  0
#> Lincoln Continental 10.4  0  0
#> Chrysler Imperial   14.7  0  0
#> Fiat 128            32.4  1  1
#> Honda Civic         30.4  1  1
#> Toyota Corolla      33.9  1  1
#> Toyota Corona       21.5  0  1
#> Dodge Challenger    15.5  0  0
#> AMC Javelin         15.2  0  0
#> Camaro Z28          13.3  0  0
#> Pontiac Firebird    19.2  0  0
#> Fiat X1-9           27.3  1  1
#> Porsche 914-2       26.0  1  0
#> Lotus Europa        30.4  1  1
#> Ford Pantera L      15.8  1  0
#> Ferrari Dino        19.7  1  0
#> Maserati Bora       15.0  1  0
#> Volvo 142E          21.4  1  1

建模:

代码语言:javascript
代码运行次数:0
复制
# 执行逻辑回归 —— 下面两种方式等效
# logit是二项分布家族的默认模型
logr_vm <- glm(vs ~ mpg, data = dat, family = binomial)
# logr_vm <- glm(vs ~ mpg, data = dat, family = binomial(link = "logit"))
logr_vm
#> 
#> Call:  glm(formula = vs ~ mpg, family = binomial, data = dat)
#> 
#> Coefficients:
#> (Intercept)          mpg  
#>       -8.83         0.43  
#> 
#> Degrees of Freedom: 31 Total (i.e. Null);  30 Residual
#> Null Deviance:       43.9 
#> Residual Deviance: 25.5  AIC: 29.5

显示的结果还是比较简洁的,包括调用、系数及其其他模型参数。

用训练数据预测如下:

代码语言:javascript
代码运行次数:0
复制
pred <- predict(logr_vm, type = "response", newdata = dat)
pred
#>           Mazda RX4       Mazda RX4 Wag          Datsun 710      Hornet 4 Drive 
#>              0.5512              0.5512              0.7272              0.5933 
#>   Hornet Sportabout             Valiant          Duster 360           Merc 240D 
#>              0.3134              0.2607              0.0643              0.8414 
#>            Merc 230            Merc 280           Merc 280C          Merc 450SE 
#>              0.7272              0.3614              0.2365              0.1450 
#>          Merc 450SL         Merc 450SLC  Cadillac Fleetwood Lincoln Continental 
#>              0.1999              0.0919              0.0127              0.0127 
#>   Chrysler Imperial            Fiat 128         Honda Civic      Toyota Corolla 
#>              0.0754              0.9940              0.9860              0.9969 
#>       Toyota Corona    Dodge Challenger         AMC Javelin          Camaro Z28 
#>              0.6037              0.1032              0.0919              0.0428 
#>    Pontiac Firebird           Fiat X1-9       Porsche 914-2        Lotus Europa 
#>              0.3614              0.9487              0.9135              0.9860 
#>      Ford Pantera L        Ferrari Dino       Maserati Bora          Volvo 142E 
#>              0.1158              0.4124              0.0850              0.5933

大部分情况下,我们得到一个模型后想要做的事情可能仅仅只是用得到的模型系数来预测新的数据,也就是得到类似上面的结果。

到底是什么占据了大量的存储空间呢?我们实际看看这个对象到底存储了些什么:

代码语言:javascript
代码运行次数:0
复制
str(logr_vm)
#> List of 30
#>  $ coefficients     : Named num [1:2] -8.83 0.43
#>   ..- attr(*, "names")= chr [1:2] "(Intercept)" "mpg"
#>  $ residuals        : Named num [1:32] -2.23 -2.23 1.38 1.69 -1.46 ...
#>   ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#>  $ fitted.values    : Named num [1:32] 0.551 0.551 0.727 0.593 0.313 ...
#>   ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#>  $ effects          : Named num [1:32] 0.703 -2.717 0.972 1.135 -0.549 ...
#>   ..- attr(*, "names")= chr [1:32] "(Intercept)" "mpg" "" "" ...
#>  $ R                : num [1:2, 1:2] -2.03 0 -40.04 -6.31
#>   ..- attr(*, "dimnames")=List of 2
#>   .. ..$ : chr [1:2] "(Intercept)" "mpg"
#>   .. ..$ : chr [1:2] "(Intercept)" "mpg"
#>  $ rank             : int 2
#>  $ qr               :List of 5
#>   ..$ qr   : num [1:32, 1:2] -2.031 0.245 0.219 0.242 0.228 ...
#>   .. ..- attr(*, "dimnames")=List of 2
#>   .. .. ..$ : chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#>   .. .. ..$ : chr [1:2] "(Intercept)" "mpg"
#>   ..$ rank : int 2
#>   ..$ qraux: num [1:2] 1.24 1.08
#>   ..$ pivot: int [1:2] 1 2
#>   ..$ tol  : num 1e-11
#>   ..- attr(*, "class")= chr "qr"
#>  $ family           :List of 12
#>   ..$ family    : chr "binomial"
#>   ..$ link      : chr "logit"
#>   ..$ linkfun   :function (mu)  
#>   ..$ linkinv   :function (eta)  
#>   ..$ variance  :function (mu)  
#>   ..$ dev.resids:function (y, mu, wt)  
#>   ..$ aic       :function (y, n, mu, wt, dev)  
#>   ..$ mu.eta    :function (eta)  
#>   ..$ initialize:  expression({  if (NCOL(y) == 1) {  if (is.factor(y))  y <- y != levels(y)[1L]  n <- rep.int(1, nobs)  y[weights =| __truncated__
#>   ..$ validmu   :function (mu)  
#>   ..$ valideta  :function (eta)  
#>   ..$ simulate  :function (object, nsim)  
#>   ..- attr(*, "class")= chr "family"
#>  $ linear.predictors: Named num [1:32] 0.206 0.206 0.98 0.378 -0.784 ...
#>   ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#>  $ deviance         : num 25.5
#>  $ aic              : num 29.5
#>  $ null.deviance    : num 43.9
#>  $ iter             : int 6
#>  $ weights          : Named num [1:32] 0.247 0.247 0.198 0.241 0.215 ...
#>   ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#>  $ prior.weights    : Named num [1:32] 1 1 1 1 1 1 1 1 1 1 ...
#>   ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#>  $ df.residual      : int 30
#>  $ df.null          : int 31
#>  $ y                : Named num [1:32] 0 0 1 1 0 1 0 1 1 1 ...
#>   ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#>  $ converged        : logi TRUE
#>  $ boundary         : logi FALSE
#>  $ model            :'data.frame':   32 obs. of  2 variables:
#>   ..$ vs : num [1:32] 0 0 1 1 0 1 0 1 1 1 ...
#>   ..$ mpg: num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
#>   ..- attr(*, "terms")=Classes 'terms', 'formula'  language vs ~ mpg
#>   .. .. ..- attr(*, "variables")= language list(vs, mpg)
#>   .. .. ..- attr(*, "factors")= int [1:2, 1] 0 1
#>   .. .. .. ..- attr(*, "dimnames")=List of 2
#>   .. .. .. .. ..$ : chr [1:2] "vs" "mpg"
#>   .. .. .. .. ..$ : chr "mpg"
#>   .. .. ..- attr(*, "term.labels")= chr "mpg"
#>   .. .. ..- attr(*, "order")= int 1
#>   .. .. ..- attr(*, "intercept")= int 1
#>   .. .. ..- attr(*, "response")= int 1
#>   .. .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
#>   .. .. ..- attr(*, "predvars")= language list(vs, mpg)
#>   .. .. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
#>   .. .. .. ..- attr(*, "names")= chr [1:2] "vs" "mpg"
#>  $ call             : language glm(formula = vs ~ mpg, family = binomial, data = dat)
#>  $ formula          :Class 'formula'  language vs ~ mpg
#>   .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
#>  $ terms            :Classes 'terms', 'formula'  language vs ~ mpg
#>   .. ..- attr(*, "variables")= language list(vs, mpg)
#>   .. ..- attr(*, "factors")= int [1:2, 1] 0 1
#>   .. .. ..- attr(*, "dimnames")=List of 2
#>   .. .. .. ..$ : chr [1:2] "vs" "mpg"
#>   .. .. .. ..$ : chr "mpg"
#>   .. ..- attr(*, "term.labels")= chr "mpg"
#>   .. ..- attr(*, "order")= int 1
#>   .. ..- attr(*, "intercept")= int 1
#>   .. ..- attr(*, "response")= int 1
#>   .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
#>   .. ..- attr(*, "predvars")= language list(vs, mpg)
#>   .. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
#>   .. .. ..- attr(*, "names")= chr [1:2] "vs" "mpg"
#>  $ data             :'data.frame':   32 obs. of  3 variables:
#>   ..$ mpg: num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
#>   ..$ am : num [1:32] 1 1 1 0 0 0 0 0 0 0 ...
#>   ..$ vs : num [1:32] 0 0 1 1 0 1 0 1 1 1 ...
#>  $ offset           : NULL
#>  $ control          :List of 3
#>   ..$ epsilon: num 1e-08
#>   ..$ maxit  : num 25
#>   ..$ trace  : logi FALSE
#>  $ method           : chr "glm.fit"
#>  $ contrasts        : NULL
#>  $ xlevels          : Named list()
#>  - attr(*, "class")= chr [1:2] "glm" "lm"

我勒个去,看得眼睛都花了。仔细扫读一下,发现有很多的信息会随着拟合(训练)数据的增大而增大,包括残差、拟合值、效应值、模型。奇葩的是,拟合数据本身也被存储了,这是一个非常明显的负担。而且 model 项把数据又存储了一遍。

大部分的信息在预测时根本用不到,我们可以试着删除一些信息后看是否还能够进行模型预测。

存储的数据对模型预测应该没有影响:

代码语言:javascript
代码运行次数:0
复制
logr_vm$data <- NULL
predict(logr_vm, type = "response", newdata = dat)
#>           Mazda RX4       Mazda RX4 Wag          Datsun 710      Hornet 4 Drive 
#>              0.5512              0.5512              0.7272              0.5933 
#>   Hornet Sportabout             Valiant          Duster 360           Merc 240D 
#>              0.3134              0.2607              0.0643              0.8414 
#>            Merc 230            Merc 280           Merc 280C          Merc 450SE 
#>              0.7272              0.3614              0.2365              0.1450 
#>          Merc 450SL         Merc 450SLC  Cadillac Fleetwood Lincoln Continental 
#>              0.1999              0.0919              0.0127              0.0127 
#>   Chrysler Imperial            Fiat 128         Honda Civic      Toyota Corolla 
#>              0.0754              0.9940              0.9860              0.9969 
#>       Toyota Corona    Dodge Challenger         AMC Javelin          Camaro Z28 
#>              0.6037              0.1032              0.0919              0.0428 
#>    Pontiac Firebird           Fiat X1-9       Porsche 914-2        Lotus Europa 
#>              0.3614              0.9487              0.9135              0.9860 
#>      Ford Pantera L        Ferrari Dino       Maserati Bora          Volvo 142E 
#>              0.1158              0.4124              0.0850              0.5933

删除残差和拟合值:

代码语言:javascript
代码运行次数:0
复制
logr_vm$residuals <- NULL
logr_vm$fitted.values <- NULL
predict(logr_vm, type = "response", newdata = dat)
#>           Mazda RX4       Mazda RX4 Wag          Datsun 710      Hornet 4 Drive 
#>              0.5512              0.5512              0.7272              0.5933 
#>   Hornet Sportabout             Valiant          Duster 360           Merc 240D 
#>              0.3134              0.2607              0.0643              0.8414 
#>            Merc 230            Merc 280           Merc 280C          Merc 450SE 
#>              0.7272              0.3614              0.2365              0.1450 
#>          Merc 450SL         Merc 450SLC  Cadillac Fleetwood Lincoln Continental 
#>              0.1999              0.0919              0.0127              0.0127 
#>   Chrysler Imperial            Fiat 128         Honda Civic      Toyota Corolla 
#>              0.0754              0.9940              0.9860              0.9969 
#>       Toyota Corona    Dodge Challenger         AMC Javelin          Camaro Z28 
#>              0.6037              0.1032              0.0919              0.0428 
#>    Pontiac Firebird           Fiat X1-9       Porsche 914-2        Lotus Europa 
#>              0.3614              0.9487              0.9135              0.9860 
#>      Ford Pantera L        Ferrari Dino       Maserati Bora          Volvo 142E 
#>              0.1158              0.4124              0.0850              0.5933

删除权重:

代码语言:javascript
代码运行次数:0
复制
logr_vm$weights <- NULL
logr_vm$prior.weights <- NULL
predict(logr_vm, type = "response", newdata = dat)
#>           Mazda RX4       Mazda RX4 Wag          Datsun 710      Hornet 4 Drive 
#>              0.5512              0.5512              0.7272              0.5933 
#>   Hornet Sportabout             Valiant          Duster 360           Merc 240D 
#>              0.3134              0.2607              0.0643              0.8414 
#>            Merc 230            Merc 280           Merc 280C          Merc 450SE 
#>              0.7272              0.3614              0.2365              0.1450 
#>          Merc 450SL         Merc 450SLC  Cadillac Fleetwood Lincoln Continental 
#>              0.1999              0.0919              0.0127              0.0127 
#>   Chrysler Imperial            Fiat 128         Honda Civic      Toyota Corolla 
#>              0.0754              0.9940              0.9860              0.9969 
#>       Toyota Corona    Dodge Challenger         AMC Javelin          Camaro Z28 
#>              0.6037              0.1032              0.0919              0.0428 
#>    Pontiac Firebird           Fiat X1-9       Porsche 914-2        Lotus Europa 
#>              0.3614              0.9487              0.9135              0.9860 
#>      Ford Pantera L        Ferrari Dino       Maserati Bora          Volvo 142E 
#>              0.1158              0.4124              0.0850              0.5933

从以上操作来看基本上与拟合模型数据等量级的信息在预测时都不会用到,如果模型结果很大时可以考虑删除。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 优雅R 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档