2017-08-01 28 views
0

我們有一個大小爲2 GB的GLM R模型。我們正在使用此模型來爲REST API提供服務。我們需要3秒鐘的響應時間。問題是使用傳統的saveRDS/readRDS函數太長了。我們最後的選擇是找到一種方法在會話之間將R模型保存在內存中。將R模型保留在內存中用於Rest API

在高層次上:

  1. 服務REST API。

  2. 在內存中保留多個千兆字節模型。

  3. 保持響應時間低於3秒。

的東西,我們已經嘗試並不起作用:

  1. 縮小模型的大小。我們的數據科學家表示,儘可能小,他可以得到它。

  2. 我已經在saveRDS上進行了壓縮和其他設置的實驗。我能做的最好的是從文件加載模型12秒。

  3. 我們嘗試過Microsoft R Server。所有的Web API請求都會被重定向到同一個會話。問題在於我們必須在保持會話活着的前提下包裝大量代碼。即使這樣它也會經常出現。

  4. Microsoft R Server Real Time已關閉,因爲它只接受由ScaleR生成的模型。我知道ScaleR具有GLM功能,但我被告知它不是一個選項。

  5. 更快的IO似乎沒有幫助。看來,瓶頸是rData文件的反序列​​化。 R是單線程不起作用。

編輯: 的問題是,什麼樣的R用REST API庫/服務將使我們能夠有狀態保存在內存中的模型中調用之間。

+1

什麼是你的問題? – user3640617

+0

2 GB GLM:想法:我會再仔細檢查一下,你肯定不會變小。 – Zach

+1

我認爲問題在於GLM模型保存了關於保存的培訓數據的副本。爲什麼不直接導出係數並手動計分(即讓API生成分數)?應該用簡單的線性模型足夠簡單,因爲它只是y = Beta1 * var1 + Beta2 * var2 ...等。 – BigTimeStats

回答

0

繼續我的評論以及@TenniStats的建議,最好的方法是減少GLM的大小。考慮以下幾點:

#generating some sample data that's fairly large 
sample.data <- data.frame('target' = sample(c(1:10), size = 5000000, replace = T), 
          'regressor1' = rnorm(5000000), 
          'regressor2' = rnorm(5000000), 
          'regressor3' = rnorm(5000000), 
          'regressor4' = rnorm(5000000), 
          'regressor5' = rnorm(5000000), 
          'regressor6' = rnorm(5000000), 
          'regressor7' = rnorm(5000000), 
          'regressor8' = rnorm(5000000), 
          'regressor9' = rnorm(5000000), 
          'regressor10' = rnorm(5000000)) 

#building a toy glm - this one is about 3.3 GB 
lm.mod <- glm(sample.data, formula = target ~ ., family = gaussian) 

#baseline predictions 
lm.default.preds <- predict(lm.mod, sample.data) 

#extracting coefficients 
lm.co <- coefficients(lm.mod) 

#applying coefficients to original data set by row and adding intercept 
lightweight.preds <- lm.co[1] + 
    apply(sample.data[,2:ncol(sample.data)], 
     1, 
     FUN = function(x) sum(x * lm.co[2:length(lm.co)])) 

#clearing names from vector for comparison 
names(lm.default.preds) <- NULL 

#taa daa 
all.equal(lm.default.preds, lightweight.preds) 

然後我們可以做到以下幾點:

#saving for our example and starting timing 
saveRDS(lm.co, file = 'myfile.RDS') 
start.time <- Sys.time() 

#reading from file 
coefs.from.file <- readRDS('myfile.RDS') 
#scoring function 
light.scoring <- function(coeff, new.data) { 
    prediction <- coeff[1] + sum(coeff[2:length(coeff)] * new.data) 
    names(prediction) <- NULL 
    return(prediction) 
} 

#same as before 
light.scoring(coefs.from.file, sample.data[1, 2:11]) 
#~.03 seconds on my machine 
Sys.time() - start.time 
+0

與我們的數據科學家聊天。最大的問題是我們需要計算置信度和概率區間以配合我們的預測。這給了我們一個走下坡路。 –