Экономия места при сохранении подогнанного объекта гам (mgcv :: gam and scam :: scam)

Я оцениваю очень простую модель на большом наборе данных. Формула выглядит как

 scam::scam(formula = ratio ~ s(rate,bs="mpi"))

Эти модели затем используются для создания прогнозов для новых данных. Больше ничего о модели меня не волнует.

Моя проблема в том, что возвращаемый объект огромен (несколько ГБ), что приводит к проблемам ниже по течению.

Я считаю, что это связано с тем, что мошенничество и игра сохраняют подогнанные значения каждой из миллиона записей.

Есть ли способ сохранить только небольшой объект, содержащий минимум, необходимый для прогнозирования новых данных? Это не должно быть больше нескольких килобайт.

огромное спасибо!

edit1: вот воспроизводимый пример, демонстрирующий мое понимание ответа Гэвина:

library(mgcv)
data(iris)
library(tidyverse)
mydb <- iris %>% filter(Species == "setosa")

dim(mydb) # 50 records
model <-  mgcv::gam(formula = Sepal.Length ~ s(Sepal.Width,bs="cs"), 
                     data  = mydb)

print(object.size(model), units = "KB") # 78 KB

distinct_mydb <- mydb %>% distinct(Sepal.Width) # 16 distinct values for the independent variables
Xp <- predict(model, newdata= distinct_mydb, type = "lpmatrix")
coefs <- coef(model)
dim(Xp) # 16 records and 10 columns (one for each of the 10 knots of the spline?)
preds1 <- Xp %*% coefs %>% t()  
preds2 <- predict(model, newdata= distinct_mydb)  # preds 1 and preds2 are identical

print(object.size(Xp), units = "KB")   # 3.4 Kb
print(object.size(coefs), units = "KB") # 1.1 Kb

В этом решении я бы сохранил «Xp» (3,4 КБ) и «coefs» (1,1 КБ) всего на 4,5 КБ вместо сохранения «модели», которая занимает 78 КБ.

Что я не уверен, так это то, как я могу использовать Xp и коэффициенты на следующей неделе, чтобы предсказать Sepal. Длина цветка с невиданным ранее Sepal.Width, равным 2,5?

edit2: ответ просто создать сетку всех возможных Sepal.Width (с округлением до некоторого десятичного числа) и просто left_join этой таблице с любыми будущими данными?

fake_db <- data.frame(Sepal.Width = seq(0,max(mydb$Sepal.Width), by = 0.1))
fake_db$predicted_Sepal.Length = predict(model, newdata =  fake_db)
print(object.size(fake_db), units = "KB") # 4.3 Kb

person Zoltan    schedule 10.01.2019    source источник


Ответы (1)


Посмотрите на ?mgav:::predict.gam и информацию для аргумента type и, в частности, на "lpmatrix".

Например, вам нужен только вектор коэффициентов и выход из

predict(model, newdata, type = "lpmatrix")`

где newdata - гораздо меньшее подмножество ваших исходных данных, но охватывающее диапазоны ковариат.

Эта опция "lpmatrix" предназначена для использования ниже по течению или вне R. Общая идея состоит в том, что если "lpmatrix" как Xp, тогда Xp %*% coef(model) дает подходящие значения. Но поскольку вы можете уменьшить размер Xp с помощью newdata, вы можете уменьшить размерность объекта, необходимого для прогнозирования.

person Gavin Simpson    schedule 10.01.2019
comment
Я прочитал много ваших ответов на этот общий вопрос и думаю, что все еще что-то упускаю. Это верно? xp <- predict(original_model, newdata = original_data, type = 'lpmatrix') coefs <- coef(model) fitted_values <- xp %*% coefs %>% t() Используя этот шаблон, как мне ввести новый пакет данных для оценки? Должен ли я генерировать новую матрицу lpmatrix с каждым новым пакетом или есть lpmatrix, связанный с исходными данными обучения, которые можно сохранить и применить к каждому последующему пакету данных? - person Raphael K; 16.02.2020
comment
Подожди, думаю, я понял. Для каждого нового пакета данных вы создаете Xp с помощью predict(), а затем умножаете это на coefs, чтобы получить оценки. - person Raphael K; 18.02.2020