I am building a classifier on a stream of data, and I am trying to develop an efficient way to update the features of the model. The situation is like this:
- I train the model on the historical data of the company.
- For that, I need to derive some inherently time-dependent features.
- Then, new data comes in, and I want to classify, say 1 or 0.
- My current solution is to load the whole data, derive the features of the entire dataset, and then classify the new data points.
Here is a sample code:
library(data.table)
library(magrittr)
set.seed(9194694859)
# Simulate data
d <- data.table(CLASS = sample(0:1, size = 1000, replace = T),
DATE = seq.Date(Sys.Date() - 999, to = Sys.Date(), by = 1),
FEAT_1 = rnorm(1000),
FEAT_2 = rnorm(1000) %>% cumsum(.),
FEAT_3 = sample(0:1, size = 1000, replace = T)
)
d[, Date := as.Date(DATE)]
# Simulate new data arrival
old_data <- d[Date < "2020-02-20"]
new_data <- d[Date >= "2020-02-20"]
# Derive new features
old_data[, DFEAT_1 := frollmean(FEAT_2, n = 10, fill = NA)]
old_data[, DFEAT_2 := frollmean(FEAT_2, n = 20, fill = NA)]
old_data[, DFEAT_3 := frollmean(FEAT_2, n = 50, fill = NA)]
old_data[, c("LAG_1", "LAG_2") := .(lag(CLASS, 1),
lag(CLASS, 2),)]
# Dynamic scaling of some features
roll_scale <- function(x, n) {
xout <- frollapply(x, n, function(z) {
out <- last((z - mean(z, na.rm = T))/sd(z, na.rm = T))})
return(xout)
}
old_data[, scaled := roll_scale(FEAT_2, 50)]
# Train model
simple_model <- glm(CLASS ~ ., data = old_data[, -"Date"], family = "binomial")
# Then new data comes
Final <- rbindlist(list(old_data, new_data), fill = T)
# So I have to calculate new feat again, so because the features are time-dependent, I use the whole data-set so lagged values are accessible for the rolling-functions
Final[, DFEAT_1 := frollmean(FEAT_2, n = 10, fill = NA)]
Final[, DFEAT_2 := frollmean(FEAT_2, n = 20, fill = NA)]
Final[, DFEAT_3 := frollmean(FEAT_2, n = 50, fill = NA)]
Final[, scaled := roll_scale(FEAT_2, 50)]
Final[, c("LAG_1", "LAG_2") := .(lag(CLASS, 1),
lag(CLASS, 2),)]
# Predict class
Final[, PREDICTED := predict(simple_model, newdata = Final, type = "response")]
Ideally, what I am looking for is for a general framework to adapt for many functions so that I can minimise the feature-updating time and stream the predictions.