Как улучшить время обработки циклов в R, ручной прогноз xgboost - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть обученная модель xgboost в R, и мой сервер приложений может запустить R, но не может установить package:xgboost (не поддерживается renjin, который является интерпретатором на основе JVM для R).Поэтому для развертывания моей модели мне нужен был способ оценки новых данных без xgb.predict.Теперь я написал функцию оценки в R, используя фрейм данных, сделанный xgb.model.dt.tree, который работает нормально, но очень медленно.Требуется 7 секунд, чтобы забить одну запись.Мне интересно, как я могу заставить мой код работать быстрее, любая помощь будет оценена по достоинству.

Я использую 2 для и 1 в то время как циклы, что, очевидно, очень медленно в R. Очевидно, я должен попытаться векторизовать их, ноЯ не могу понять, как.

Rcpp, кажется, вариант, но я не знаю C ++.

Вот мой код.Его мультиклассовая классификация с 18 классом (0,500,1000 и т. Д.).Модель была построена с nrounds=50, так что в общей сложности 18*50=900 бустеров.Глубина дерева была установлена ​​на 8, а кадр данных дампа a имеет размер 238252 X 10.

fun_score <- function (testsample) {
  df <- data.frame('0'=NA,'500'=NA,'1000'=NA,'1500'=NA,'2000'=NA,'3000'=NA,'5000'=NA,'6000'=NA,'8000'=NA,
                   '10000'=NA,'15000'=NA,'20000'=NA,'25000'=NA,'40000'=NA,'50000'=NA,'70000'=NA,'77000'=NA,'120000'=NA)
for (i in 0:17) { 
    twght <- 0
    for(tree_num in seq(i,899,18)){
      tr=a[Tree==tree_num]
      rid <- which(tr[,2]==0)
      splitvar <- as.character(tr[rid,4])
      while (grepl("Leaf",tr[rid,4])==F) {
        next_split <- as.character(ifelse(is.null(testsample[splitvar]), tr[rid,7],
                                          ifelse( as.numeric(testsample[splitvar]) < tr[rid,5], tr[rid,6],tr[rid,7])))
        rid <- which(tr[,3] == next_split)
        splitvar <- as.character(tr[rid,4])
      }
      w=(tr[rid,9])
      twght=twght+w
    }
    twght=twght+0.5 # bias 0.5
    df[,i+1]=twght
}
  df = as.data.frame(t(apply(df, 1, function(x)(exp(x))/(sum(exp(x))))))
  df$class=substr(colnames(df)[apply(df,1,which.max)],2, nchar(colnames(df)[apply(df,1,which.max)]))
  return(df)
}

И дерево data.frame выглядит следующим образом

> head(a)
   Tree Node  ID Feature     Split  Yes   No Missing    Quality     Cover
1:    0    0 0-0     DBR 14.900000  0-1  0-2     0-1 31579.3008 28727.481
2:    0    1 0-1     DBR  8.815001  0-3  0-4     0-3  4707.3477 15235.673
3:    0    2 0-2     DBR 20.584999  0-5  0-6     0-5  3631.3484 13491.809
4:    0    3 0-3    DSLR 18.500000  0-7  0-8     0-7  1703.1209  6624.963
5:    0    4 0-4     RAD -0.500000  0-9 0-10     0-9  1390.2230  8610.710
6:    0    5 0-5    DSLR 27.500000 0-11 0-12    0-11   861.4305  4966.624

1 Ответ

0 голосов
/ 22 декабря 2018

Это похоже на отличный пример использования цикла компилятора Renjin Just-in-time.Однако в текущем выпуске он не включен по умолчанию.Вы можете включить его в командной строке с флагом --compile-loops или с помощью флага JVM -Drenjin.compile.loops=true

Если это не обеспечивает ускорение, откройте проблему на GitHub.

...