(Acest articol a fost publicat pentru prima dată pe mlr-orgși cu amabilitate a contribuit la R-bloggeri). (Puteți raporta problema legată de conținutul acestei pagini aici)
Doriți să vă distribuiți conținutul pe R-bloggeri? dați clic aici dacă aveți un blog, sau aici dacă nu aveți.
Obiectele model adaptate în R poartă adesea mai mult decât au nevoie pentru predicție. O glm obiectul păstrează datele de antrenament, valorile ajustate, reziduurile și mediul formulei sale. Este bine pentru un singur model. Se adună când resample() sau tune() păstrați un model pentru fiecare iterație de reeșantionare cu store_models = TRUE.
Pachetul Butcher din ecosistemul tidymodels elimină aceste componente, păstrând în același timp modelul utilizabil pentru predicție. Această postare arată cum să-l aplicați unui singur cursant și cum să-l includeți într-un apel invers, astfel încât fiecare model stocat de mlr3 și mlr3tuning să fie micșorat imediat după antrenament.
library(mlr3) library(mlr3learners) library(mlr3tuning) library(mlr3misc) library(butcher)
Măsurăm dimensiunea unui obiect prin serializarea acestuia. Acesta este numărul de octeți de care are nevoie obiectul pe disc sau când este trimis către un lucrător paralel.
serialized_size = function(x) {
round(length(serialize(x, connection = NULL)) / 1024^2, digits = 2L)
}
Antrenăm o regresie logistică asupra sarcinii de spam cu 4601 de e-mailuri și 57 de funcții.
task = tsk("spam")
learner = lrn("classif.log_reg", predict_type = "prob")
learner$train(task)
serialized_size(learner$model)
Modelul are nevoie de aproximativ 4,4 MB. Funcția weigh() listează componentele obiectului model sortate după dimensiune în MB.
weigh(learner$model)
# A tibble: 101 × 2 object size1 qr.qr 2.16 2 residuals 0.333 3 fitted.values 0.333 4 linear.predictors 0.333 5 weights 0.333 6 prior.weights 0.333 7 y 0.333 8 effects 0.0773 9 family.variance 0.0440 10 family.dev.resids 0.0440 # ℹ 91 more rows
Descompunerea QR este cea mai mare componentă. Reziduurile, valorile ajustate, predictorii liniari, ponderile și răspunsul iau fiecare încă 0,33 MB. Previziunea are nevoie doar de o fracțiune din aceasta.
Prevăzăm sarcina, tăiem modelul și îl scriem înapoi în cursant.
prediction = learner$predict(task) learner$model = butcher(learner$model) serialized_size(learner$model)
Modelul s-a micșorat la aproximativ jumătate din dimensiunea sa. Predicțiile modelului măcelărit sunt identice cu predicțiile originale.
all.equal(prediction, learner$predict(task))
Funcția butcher() elimină doar componentele pe care predict() metoda clasei model nu folosește. Păstrează descompunerea QR pentru că predict.glm() are nevoie de el pentru a calcula erorile standard.
Un model măcelărit a pierdut informații. Funcții precum summary(), residuals()sau fitted() poate eșua sau returna rezultate greșite. Doar modele de măcelar de care aveți nevoie pentru predicție.
Acum vrem să micșorăm fiecare model care resample() magazine. Callback-urile rulează cod în anumite etape ale buclei de reeșantionare. Creăm o reeșantionare apel invers cu mlr3::callback_resample(). Scena on_resample_end rulează după ce cursantul a fost instruit și și-a făcut predicțiile. Obiectul context oferă acces cursantului iterației curente.
callback = callback_resample("butcher",
on_resample_end = function(callback, context) {
context$learner$model = butcher::butcher(context$learner$model)
}
)
Sunăm butcher() cu prefixul pachetului deoarece apelul invers poate rula pe un lucrător paralel pe care butcher nu este atașată.
Efectuăm o validare încrucișată de 5 ori de două ori pe aceleași segmente, o dată fără și o dată cu apel invers.
resampling = rsmp("cv", folds = 5L)
resampling$instantiate(task)
rr = resample(task, learner, resampling, store_models = TRUE)
rr_butchered = resample(task, learner, resampling, store_models = TRUE, callbacks = callback)
Comparăm dimensiunea modelelor stocate.
serialized_size(map(rr$learners, "model"))
serialized_size(map(rr_butchered$learners, "model"))
Cele cinci modele măcelărite au nevoie de aproximativ 9 MB mai puțin. Reapelarea atinge doar modelele stocate, astfel încât estimarea performanței nu se modifică.
rr$aggregate(msr("classif.auc"))
rr_butchered$aggregate(msr("classif.auc"))
Cursanții stocați încă prezic date noi.
rr_butchered$learners((1L))$predict(task)
──for 4601 observations: ────────────────────────────────────────────────────────────────────────── row_ids truth response prob.spam prob.nonspam 1 spam spam 0.62852865 3.714714e-01 2 spam spam 0.99139839 8.601607e-03 3 spam spam 0.99999999 5.408266e-09 --- --- --- --- --- 4599 nonspam nonspam 0.03097766 9.690223e-01 4600 nonspam nonspam 0.07923412 9.207659e-01 4601 nonspam nonspam 0.02782719 9.721728e-01
benchmark() acceptă la fel callbacks argument.
Tuning cu store_models = TRUE stochează un model per iterație de reeșantionare și configurație de hiperparametru. Instanțele de reglare preiau apeluri de reglare, care pot include etapele de reeșantionare. Creăm unul cu mlr3tuning::callback_batch_tuning().
callback_tuning = callback_batch_tuning("butcher",
on_resample_end = function(callback, context) {
context$learner$model = butcher::butcher(context$learner$model)
}
)
Ajustăm parametrul de complexitate al unui arbore de decizie cu 20 de configurații aleatorii și o validare încrucișată de trei ori.
learner_rpart = lrn("classif.rpart", cp = to_tune(1e-4, 1e-1, logscale = TRUE))
instance = tune(
tuner = tnr("random_search"),
task = task,
learner = learner_rpart,
resampling = rsmp("cv", folds = 3L),
term_evals = 20L,
store_models = TRUE,
callbacks = callback_tuning
)
Arhiva conține un rezultat de referință cu cele 60 de modele măcelărite.
models = map(instance$archive$benchmark_result$resample_results$resample_result, function(rr) {
map(rr$learners, "model")
})
serialized_size(models)
The butcher pachetul elimină datele, apelurile și mediile de care un model nu are nevoie pentru predicție. Învelit într-un apel invers, micșorează fiecare model care resample(), benchmark()sau tune() magazine. Rezultatele stocate necesită mai puțină memorie și sunt mai rapid de salvat pe disc și de transferat de la lucrătorii paraleli. Cât de mult se economisește depinde de clasa de model. Pentru clasele model fără a butcher metodă, butcher() returnează modelul neschimbat. Puteți verifica ce clase sunt acceptate în documentația măcelarului.
