commit
96f221e0d0
@ -41,6 +41,9 @@ on going at master
|
|||||||
- Fixed possible problem of poisson regression for R.
|
- Fixed possible problem of poisson regression for R.
|
||||||
* Python module now throw exception instead of crash terminal when a parameter error happens.
|
* Python module now throw exception instead of crash terminal when a parameter error happens.
|
||||||
* Python module now has importance plot and tree plot functions.
|
* Python module now has importance plot and tree plot functions.
|
||||||
|
* Python module now accepts different learning rates for each boosting round.
|
||||||
|
* Python now allows model training continuation from previously saved model.
|
||||||
|
* Additional parameters added for sklearn wrapper
|
||||||
* Java api is ready for use
|
* Java api is ready for use
|
||||||
* Added more test cases and continuous integration to make each build more robust
|
* Added more test cases and continuous integration to make each build more robust
|
||||||
* Improvements in sklearn compatible module
|
* Improvements in sklearn compatible module
|
||||||
|
|||||||
@ -13,6 +13,8 @@ Committers are people who have made substantial contribution to the project and
|
|||||||
- Bing is the original creator of xgboost python package and currently the maintainer of [XGBoost.jl](https://github.com/antinucleon/XGBoost.jl).
|
- Bing is the original creator of xgboost python package and currently the maintainer of [XGBoost.jl](https://github.com/antinucleon/XGBoost.jl).
|
||||||
* [Michael Benesty](https://github.com/pommedeterresautee)
|
* [Michael Benesty](https://github.com/pommedeterresautee)
|
||||||
- Micheal is a lawyer, data scientist in France, he is the creator of xgboost interactive analysis module in R.
|
- Micheal is a lawyer, data scientist in France, he is the creator of xgboost interactive analysis module in R.
|
||||||
|
* [Yuan Tang](https://github.com/terrytangyuan)
|
||||||
|
- Yuan is a data scientist in Chicago, US. He contributed mostly in R and Python packages.
|
||||||
|
|
||||||
Become a Comitter
|
Become a Comitter
|
||||||
-----------------
|
-----------------
|
||||||
@ -34,7 +36,6 @@ List of Contributors
|
|||||||
* [Zygmunt Zając](https://github.com/zygmuntz)
|
* [Zygmunt Zając](https://github.com/zygmuntz)
|
||||||
- Zygmunt is the master behind the early stopping feature frequently used by kagglers.
|
- Zygmunt is the master behind the early stopping feature frequently used by kagglers.
|
||||||
* [Ajinkya Kale](https://github.com/ajkl)
|
* [Ajinkya Kale](https://github.com/ajkl)
|
||||||
* [Yuan Tang](https://github.com/terrytangyuan)
|
|
||||||
* [Boliang Chen](https://github.com/cblsjtu)
|
* [Boliang Chen](https://github.com/cblsjtu)
|
||||||
* [Vadim Khotilovich](https://github.com/khotilov)
|
* [Vadim Khotilovich](https://github.com/khotilov)
|
||||||
* [Yangqing Men](https://github.com/yanqingmen)
|
* [Yangqing Men](https://github.com/yanqingmen)
|
||||||
@ -49,5 +50,9 @@ List of Contributors
|
|||||||
- Masaaki is the initial creator of xgboost python plotting module.
|
- Masaaki is the initial creator of xgboost python plotting module.
|
||||||
* [Hongliang Liu](https://github.com/phunterlau)
|
* [Hongliang Liu](https://github.com/phunterlau)
|
||||||
- Hongliang is the maintainer of xgboost python PyPI package for pip installation.
|
- Hongliang is the maintainer of xgboost python PyPI package for pip installation.
|
||||||
|
* [daiyl0320](https://github.com/daiyl0320)
|
||||||
|
- daiyl0320 contributed patch to xgboost distributed version more robust, and scales stably on TB scale datasets.
|
||||||
* [Huayi Zhang](https://github.com/irachex)
|
* [Huayi Zhang](https://github.com/irachex)
|
||||||
* [Johan Manders](https://github.com/johanmanders)
|
* [Johan Manders](https://github.com/johanmanders)
|
||||||
|
* [yoori](https://github.com/yoori)
|
||||||
|
* [Mathias Müller](https://github.com/far0n)
|
||||||
|
|||||||
1
Makefile
1
Makefile
@ -189,7 +189,6 @@ pythonpack:
|
|||||||
cp -r multi-node xgboost-deploy/xgboost
|
cp -r multi-node xgboost-deploy/xgboost
|
||||||
cp -r windows xgboost-deploy/xgboost
|
cp -r windows xgboost-deploy/xgboost
|
||||||
cp -r src xgboost-deploy/xgboost
|
cp -r src xgboost-deploy/xgboost
|
||||||
|
|
||||||
#make python
|
#make python
|
||||||
|
|
||||||
pythonbuild:
|
pythonbuild:
|
||||||
|
|||||||
@ -54,4 +54,3 @@ setMethod("getinfo", signature = "xgb.DMatrix",
|
|||||||
}
|
}
|
||||||
return(ret)
|
return(ret)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -48,7 +48,7 @@ setMethod("predict", signature = "xgb.Booster",
|
|||||||
stop("predict: ntreelimit must be equal to or greater than 1")
|
stop("predict: ntreelimit must be equal to or greater than 1")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
option = 0
|
option <- 0
|
||||||
if (outputmargin) {
|
if (outputmargin) {
|
||||||
option <- option + 1
|
option <- option + 1
|
||||||
}
|
}
|
||||||
@ -68,4 +68,3 @@ setMethod("predict", signature = "xgb.Booster",
|
|||||||
}
|
}
|
||||||
return(ret)
|
return(ret)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,6 @@ setMethod("predict", signature = "xgb.Booster.handle",
|
|||||||
|
|
||||||
bst <- xgb.handleToBooster(object)
|
bst <- xgb.handleToBooster(object)
|
||||||
|
|
||||||
ret = predict(bst, ...)
|
ret <- predict(bst, ...)
|
||||||
return(ret)
|
return(ret)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -34,8 +34,8 @@ setMethod("slice", signature = "xgb.DMatrix",
|
|||||||
attr_list <- attributes(object)
|
attr_list <- attributes(object)
|
||||||
nr <- xgb.numrow(object)
|
nr <- xgb.numrow(object)
|
||||||
len <- sapply(attr_list,length)
|
len <- sapply(attr_list,length)
|
||||||
ind <- which(len==nr)
|
ind <- which(len == nr)
|
||||||
if (length(ind)>0) {
|
if (length(ind) > 0) {
|
||||||
nms <- names(attr_list)[ind]
|
nms <- names(attr_list)[ind]
|
||||||
for (i in 1:length(ind)) {
|
for (i in 1:length(ind)) {
|
||||||
attr(ret,nms[i]) <- attr(object,nms[i])[idxset]
|
attr(ret,nms[i]) <- attr(object,nms[i])[idxset]
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#' @importClassesFrom Matrix dgCMatrix dgeMatrix
|
#' @importClassesFrom Matrix dgCMatrix dgeMatrix
|
||||||
#' @import methods
|
#' @import methods
|
||||||
|
|
||||||
# depends on matrix
|
# depends on matrix
|
||||||
@ -15,14 +15,14 @@ xgb.setinfo <- function(dmat, name, info) {
|
|||||||
stop("xgb.setinfo: first argument dtrain must be xgb.DMatrix")
|
stop("xgb.setinfo: first argument dtrain must be xgb.DMatrix")
|
||||||
}
|
}
|
||||||
if (name == "label") {
|
if (name == "label") {
|
||||||
if (length(info)!=xgb.numrow(dmat))
|
if (length(info) != xgb.numrow(dmat))
|
||||||
stop("The length of labels must equal to the number of rows in the input data")
|
stop("The length of labels must equal to the number of rows in the input data")
|
||||||
.Call("XGDMatrixSetInfo_R", dmat, name, as.numeric(info),
|
.Call("XGDMatrixSetInfo_R", dmat, name, as.numeric(info),
|
||||||
PACKAGE = "xgboost")
|
PACKAGE = "xgboost")
|
||||||
return(TRUE)
|
return(TRUE)
|
||||||
}
|
}
|
||||||
if (name == "weight") {
|
if (name == "weight") {
|
||||||
if (length(info)!=xgb.numrow(dmat))
|
if (length(info) != xgb.numrow(dmat))
|
||||||
stop("The length of weights must equal to the number of rows in the input data")
|
stop("The length of weights must equal to the number of rows in the input data")
|
||||||
.Call("XGDMatrixSetInfo_R", dmat, name, as.numeric(info),
|
.Call("XGDMatrixSetInfo_R", dmat, name, as.numeric(info),
|
||||||
PACKAGE = "xgboost")
|
PACKAGE = "xgboost")
|
||||||
@ -36,7 +36,7 @@ xgb.setinfo <- function(dmat, name, info) {
|
|||||||
return(TRUE)
|
return(TRUE)
|
||||||
}
|
}
|
||||||
if (name == "group") {
|
if (name == "group") {
|
||||||
if (sum(info)!=xgb.numrow(dmat))
|
if (sum(info) != xgb.numrow(dmat))
|
||||||
stop("The sum of groups must equal to the number of rows in the input data")
|
stop("The sum of groups must equal to the number of rows in the input data")
|
||||||
.Call("XGDMatrixSetInfo_R", dmat, name, as.integer(info),
|
.Call("XGDMatrixSetInfo_R", dmat, name, as.integer(info),
|
||||||
PACKAGE = "xgboost")
|
PACKAGE = "xgboost")
|
||||||
@ -142,8 +142,7 @@ xgb.iter.boost <- function(booster, dtrain, gpair) {
|
|||||||
if (class(dtrain) != "xgb.DMatrix") {
|
if (class(dtrain) != "xgb.DMatrix") {
|
||||||
stop("xgb.iter.update: second argument must be type xgb.DMatrix")
|
stop("xgb.iter.update: second argument must be type xgb.DMatrix")
|
||||||
}
|
}
|
||||||
.Call("XGBoosterBoostOneIter_R", booster, dtrain, gpair$grad, gpair$hess,
|
.Call("XGBoosterBoostOneIter_R", booster, dtrain, gpair$grad, gpair$hess, PACKAGE = "xgboost")
|
||||||
PACKAGE = "xgboost")
|
|
||||||
return(TRUE)
|
return(TRUE)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +158,7 @@ xgb.iter.update <- function(booster, dtrain, iter, obj = NULL) {
|
|||||||
if (is.null(obj)) {
|
if (is.null(obj)) {
|
||||||
.Call("XGBoosterUpdateOneIter_R", booster, as.integer(iter), dtrain,
|
.Call("XGBoosterUpdateOneIter_R", booster, as.integer(iter), dtrain,
|
||||||
PACKAGE = "xgboost")
|
PACKAGE = "xgboost")
|
||||||
} else {
|
} else {
|
||||||
pred <- predict(booster, dtrain)
|
pred <- predict(booster, dtrain)
|
||||||
gpair <- obj(pred, dtrain)
|
gpair <- obj(pred, dtrain)
|
||||||
succ <- xgb.iter.boost(booster, dtrain, gpair)
|
succ <- xgb.iter.boost(booster, dtrain, gpair)
|
||||||
@ -252,17 +251,17 @@ xgb.cv.mknfold <- function(dall, nfold, param, stratified, folds) {
|
|||||||
# make simple non-stratified folds
|
# make simple non-stratified folds
|
||||||
kstep <- length(randidx) %/% nfold
|
kstep <- length(randidx) %/% nfold
|
||||||
folds <- list()
|
folds <- list()
|
||||||
for (i in 1:(nfold-1)) {
|
for (i in 1:(nfold - 1)) {
|
||||||
folds[[i]] = randidx[1:kstep]
|
folds[[i]] <- randidx[1:kstep]
|
||||||
randidx = setdiff(randidx, folds[[i]])
|
randidx <- setdiff(randidx, folds[[i]])
|
||||||
}
|
}
|
||||||
folds[[nfold]] = randidx
|
folds[[nfold]] <- randidx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret <- list()
|
ret <- list()
|
||||||
for (k in 1:nfold) {
|
for (k in 1:nfold) {
|
||||||
dtest <- slice(dall, folds[[k]])
|
dtest <- slice(dall, folds[[k]])
|
||||||
didx = c()
|
didx <- c()
|
||||||
for (i in 1:nfold) {
|
for (i in 1:nfold) {
|
||||||
if (i != k) {
|
if (i != k) {
|
||||||
didx <- append(didx, folds[[i]])
|
didx <- append(didx, folds[[i]])
|
||||||
@ -270,7 +269,7 @@ xgb.cv.mknfold <- function(dall, nfold, param, stratified, folds) {
|
|||||||
}
|
}
|
||||||
dtrain <- slice(dall, didx)
|
dtrain <- slice(dall, didx)
|
||||||
bst <- xgb.Booster(param, list(dtrain, dtest))
|
bst <- xgb.Booster(param, list(dtrain, dtest))
|
||||||
watchlist = list(train=dtrain, test=dtest)
|
watchlist <- list(train=dtrain, test=dtest)
|
||||||
ret[[k]] <- list(dtrain=dtrain, booster=bst, watchlist=watchlist, index=folds[[k]])
|
ret[[k]] <- list(dtrain=dtrain, booster=bst, watchlist=watchlist, index=folds[[k]])
|
||||||
}
|
}
|
||||||
return (ret)
|
return (ret)
|
||||||
@ -311,9 +310,9 @@ xgb.createFolds <- function(y, k = 10)
|
|||||||
## At most, we will use quantiles. If the sample
|
## At most, we will use quantiles. If the sample
|
||||||
## is too small, we just do regular unstratified
|
## is too small, we just do regular unstratified
|
||||||
## CV
|
## CV
|
||||||
cuts <- floor(length(y)/k)
|
cuts <- floor(length(y) / k)
|
||||||
if(cuts < 2) cuts <- 2
|
if (cuts < 2) cuts <- 2
|
||||||
if(cuts > 5) cuts <- 5
|
if (cuts > 5) cuts <- 5
|
||||||
y <- cut(y,
|
y <- cut(y,
|
||||||
unique(stats::quantile(y, probs = seq(0, 1, length = cuts))),
|
unique(stats::quantile(y, probs = seq(0, 1, length = cuts))),
|
||||||
include.lowest = TRUE)
|
include.lowest = TRUE)
|
||||||
|
|||||||
@ -99,7 +99,7 @@ xgb.cv <- function(params=list(), data, nrounds, nfold, label = NULL, missing =
|
|||||||
stop("xgb.cv: first argument params must be list")
|
stop("xgb.cv: first argument params must be list")
|
||||||
}
|
}
|
||||||
if(!is.null(folds)) {
|
if(!is.null(folds)) {
|
||||||
if(class(folds)!="list" | length(folds) < 2) {
|
if(class(folds) != "list" | length(folds) < 2) {
|
||||||
stop("folds must be a list with 2 or more elements that are vectors of indices for each CV-fold")
|
stop("folds must be a list with 2 or more elements that are vectors of indices for each CV-fold")
|
||||||
}
|
}
|
||||||
nfold <- length(folds)
|
nfold <- length(folds)
|
||||||
@ -108,10 +108,10 @@ xgb.cv <- function(params=list(), data, nrounds, nfold, label = NULL, missing =
|
|||||||
stop("nfold must be bigger than 1")
|
stop("nfold must be bigger than 1")
|
||||||
}
|
}
|
||||||
dtrain <- xgb.get.DMatrix(data, label, missing)
|
dtrain <- xgb.get.DMatrix(data, label, missing)
|
||||||
dot.params = list(...)
|
dot.params <- list(...)
|
||||||
nms.params = names(params)
|
nms.params <- names(params)
|
||||||
nms.dot.params = names(dot.params)
|
nms.dot.params <- names(dot.params)
|
||||||
if (length(intersect(nms.params,nms.dot.params))>0)
|
if (length(intersect(nms.params,nms.dot.params)) > 0)
|
||||||
stop("Duplicated defined term in parameters. Please check your list of params.")
|
stop("Duplicated defined term in parameters. Please check your list of params.")
|
||||||
params <- append(params, dot.params)
|
params <- append(params, dot.params)
|
||||||
params <- append(params, list(silent=1))
|
params <- append(params, list(silent=1))
|
||||||
@ -123,16 +123,16 @@ xgb.cv <- function(params=list(), data, nrounds, nfold, label = NULL, missing =
|
|||||||
if (!is.null(params$objective) && !is.null(obj))
|
if (!is.null(params$objective) && !is.null(obj))
|
||||||
stop("xgb.cv: cannot assign two different objectives")
|
stop("xgb.cv: cannot assign two different objectives")
|
||||||
if (!is.null(params$objective))
|
if (!is.null(params$objective))
|
||||||
if (class(params$objective)=='function') {
|
if (class(params$objective) == 'function') {
|
||||||
obj = params$objective
|
obj <- params$objective
|
||||||
params[['objective']] = NULL
|
params[['objective']] <- NULL
|
||||||
}
|
}
|
||||||
# if (!is.null(params$eval_metric) && !is.null(feval))
|
# if (!is.null(params$eval_metric) && !is.null(feval))
|
||||||
# stop("xgb.cv: cannot assign two different evaluation metrics")
|
# stop("xgb.cv: cannot assign two different evaluation metrics")
|
||||||
if (!is.null(params$eval_metric))
|
if (!is.null(params$eval_metric))
|
||||||
if (class(params$eval_metric)=='function') {
|
if (class(params$eval_metric) == 'function') {
|
||||||
feval = params$eval_metric
|
feval <- params$eval_metric
|
||||||
params[['eval_metric']] = NULL
|
params[['eval_metric']] <- NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
# Early Stopping
|
# Early Stopping
|
||||||
@ -144,39 +144,39 @@ xgb.cv <- function(params=list(), data, nrounds, nfold, label = NULL, missing =
|
|||||||
if (is.null(maximize))
|
if (is.null(maximize))
|
||||||
{
|
{
|
||||||
if (params$eval_metric %in% c('rmse','logloss','error','merror','mlogloss')) {
|
if (params$eval_metric %in% c('rmse','logloss','error','merror','mlogloss')) {
|
||||||
maximize = FALSE
|
maximize <- FALSE
|
||||||
} else {
|
} else {
|
||||||
maximize = TRUE
|
maximize <- TRUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maximize) {
|
if (maximize) {
|
||||||
bestScore = 0
|
bestScore <- 0
|
||||||
} else {
|
} else {
|
||||||
bestScore = Inf
|
bestScore <- Inf
|
||||||
}
|
}
|
||||||
bestInd = 0
|
bestInd <- 0
|
||||||
earlyStopflag = FALSE
|
earlyStopflag <- FALSE
|
||||||
|
|
||||||
if (length(metrics)>1)
|
if (length(metrics) > 1)
|
||||||
warning('Only the first metric is used for early stopping process.')
|
warning('Only the first metric is used for early stopping process.')
|
||||||
}
|
}
|
||||||
|
|
||||||
xgb_folds <- xgb.cv.mknfold(dtrain, nfold, params, stratified, folds)
|
xgb_folds <- xgb.cv.mknfold(dtrain, nfold, params, stratified, folds)
|
||||||
obj_type = params[['objective']]
|
obj_type <- params[['objective']]
|
||||||
mat_pred = FALSE
|
mat_pred <- FALSE
|
||||||
if (!is.null(obj_type) && obj_type=='multi:softprob')
|
if (!is.null(obj_type) && obj_type == 'multi:softprob')
|
||||||
{
|
{
|
||||||
num_class = params[['num_class']]
|
num_class <- params[['num_class']]
|
||||||
if (is.null(num_class))
|
if (is.null(num_class))
|
||||||
stop('must set num_class to use softmax')
|
stop('must set num_class to use softmax')
|
||||||
predictValues <- matrix(0,xgb.numrow(dtrain),num_class)
|
predictValues <- matrix(0,xgb.numrow(dtrain),num_class)
|
||||||
mat_pred = TRUE
|
mat_pred <- TRUE
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
predictValues <- rep(0,xgb.numrow(dtrain))
|
predictValues <- rep(0,xgb.numrow(dtrain))
|
||||||
history <- c()
|
history <- c()
|
||||||
print.every.n = max(as.integer(print.every.n), 1L)
|
print.every.n <- max(as.integer(print.every.n), 1L)
|
||||||
for (i in 1:nrounds) {
|
for (i in 1:nrounds) {
|
||||||
msg <- list()
|
msg <- list()
|
||||||
for (k in 1:nfold) {
|
for (k in 1:nfold) {
|
||||||
@ -187,46 +187,44 @@ xgb.cv <- function(params=list(), data, nrounds, nfold, label = NULL, missing =
|
|||||||
ret <- xgb.cv.aggcv(msg, showsd)
|
ret <- xgb.cv.aggcv(msg, showsd)
|
||||||
history <- c(history, ret)
|
history <- c(history, ret)
|
||||||
if(verbose)
|
if(verbose)
|
||||||
if (0==(i-1L)%%print.every.n)
|
if (0 == (i - 1L) %% print.every.n)
|
||||||
cat(ret, "\n", sep="")
|
cat(ret, "\n", sep="")
|
||||||
|
|
||||||
# early_Stopping
|
# early_Stopping
|
||||||
if (!is.null(early.stop.round)){
|
if (!is.null(early.stop.round)){
|
||||||
score = strsplit(ret,'\\s+')[[1]][1+length(metrics)+2]
|
score <- strsplit(ret,'\\s+')[[1]][1 + length(metrics) + 2]
|
||||||
score = strsplit(score,'\\+|:')[[1]][[2]]
|
score <- strsplit(score,'\\+|:')[[1]][[2]]
|
||||||
score = as.numeric(score)
|
score <- as.numeric(score)
|
||||||
if ((maximize && score>bestScore) || (!maximize && score<bestScore)) {
|
if ( (maximize && score > bestScore) || (!maximize && score < bestScore)) {
|
||||||
bestScore = score
|
bestScore <- score
|
||||||
bestInd = i
|
bestInd <- i
|
||||||
} else {
|
} else {
|
||||||
if (i-bestInd>=early.stop.round) {
|
if (i - bestInd >= early.stop.round) {
|
||||||
earlyStopflag = TRUE
|
earlyStopflag <- TRUE
|
||||||
cat('Stopping. Best iteration:',bestInd)
|
cat('Stopping. Best iteration:',bestInd)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prediction) {
|
if (prediction) {
|
||||||
for (k in 1:nfold) {
|
for (k in 1:nfold) {
|
||||||
fd = xgb_folds[[k]]
|
fd <- xgb_folds[[k]]
|
||||||
if (!is.null(early.stop.round) && earlyStopflag) {
|
if (!is.null(early.stop.round) && earlyStopflag) {
|
||||||
res = xgb.iter.eval(fd$booster, fd$watchlist, bestInd - 1, feval, prediction)
|
res <- xgb.iter.eval(fd$booster, fd$watchlist, bestInd - 1, feval, prediction)
|
||||||
} else {
|
} else {
|
||||||
res = xgb.iter.eval(fd$booster, fd$watchlist, nrounds - 1, feval, prediction)
|
res <- xgb.iter.eval(fd$booster, fd$watchlist, nrounds - 1, feval, prediction)
|
||||||
}
|
}
|
||||||
if (mat_pred) {
|
if (mat_pred) {
|
||||||
pred_mat = matrix(res[[2]],num_class,length(fd$index))
|
pred_mat <- matrix(res[[2]],num_class,length(fd$index))
|
||||||
predictValues[fd$index,] = t(pred_mat)
|
predictValues[fd$index,] <- t(pred_mat)
|
||||||
} else {
|
} else {
|
||||||
predictValues[fd$index] = res[[2]]
|
predictValues[fd$index] <- res[[2]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
colnames <- str_split(string = history[1], pattern = "\t")[[1]] %>% .[2:length(.)] %>% str_extract(".*:") %>% str_replace(":","") %>% str_replace("-", ".")
|
colnames <- str_split(string = history[1], pattern = "\t")[[1]] %>% .[2:length(.)] %>% str_extract(".*:") %>% str_replace(":","") %>% str_replace("-", ".")
|
||||||
colnamesMean <- paste(colnames, "mean")
|
colnamesMean <- paste(colnames, "mean")
|
||||||
if(showsd) colnamesStd <- paste(colnames, "std")
|
if(showsd) colnamesStd <- paste(colnames, "std")
|
||||||
@ -239,10 +237,10 @@ xgb.cv <- function(params=list(), data, nrounds, nfold, label = NULL, missing =
|
|||||||
dt <- utils::read.table(text = "", colClasses = type, col.names = colnames) %>% as.data.table
|
dt <- utils::read.table(text = "", colClasses = type, col.names = colnames) %>% as.data.table
|
||||||
split <- str_split(string = history, pattern = "\t")
|
split <- str_split(string = history, pattern = "\t")
|
||||||
|
|
||||||
for(line in split) dt <- line[2:length(line)] %>% str_extract_all(pattern = "\\d*\\.+\\d*") %>% unlist %>% as.numeric %>% as.list %>% {rbindlist(list(dt, .), use.names = F, fill = F)}
|
for(line in split) dt <- line[2:length(line)] %>% str_extract_all(pattern = "\\d*\\.+\\d*") %>% unlist %>% as.numeric %>% as.list %>% {rbindlist( list( dt, .), use.names = F, fill = F)}
|
||||||
|
|
||||||
if (prediction) {
|
if (prediction) {
|
||||||
return(list(dt = dt,pred = predictValues))
|
return( list( dt = dt,pred = predictValues))
|
||||||
}
|
}
|
||||||
return(dt)
|
return(dt)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,7 +66,7 @@
|
|||||||
#' xgb.importance(train$data@@Dimnames[[2]], model = bst, data = train$data, label = train$label)
|
#' xgb.importance(train$data@@Dimnames[[2]], model = bst, data = train$data, label = train$label)
|
||||||
#'
|
#'
|
||||||
#' @export
|
#' @export
|
||||||
xgb.importance <- function(feature_names = NULL, filename_dump = NULL, model = NULL, data = NULL, label = NULL, target = function(x) ((x + label) == 2)){
|
xgb.importance <- function(feature_names = NULL, filename_dump = NULL, model = NULL, data = NULL, label = NULL, target = function(x) ( (x + label) == 2)){
|
||||||
if (!class(feature_names) %in% c("character", "NULL")) {
|
if (!class(feature_names) %in% c("character", "NULL")) {
|
||||||
stop("feature_names: Has to be a vector of character or NULL if the model dump already contains feature name. Look at this function documentation to see where to get feature names.")
|
stop("feature_names: Has to be a vector of character or NULL if the model dump already contains feature name. Look at this function documentation to see where to get feature names.")
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ xgb.importance <- function(feature_names = NULL, filename_dump = NULL, model = N
|
|||||||
stop("model: Has to be an object of class xgb.Booster model generaged by the xgb.train function.")
|
stop("model: Has to be an object of class xgb.Booster model generaged by the xgb.train function.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if((is.null(data) & !is.null(label)) |(!is.null(data) & is.null(label))) {
|
if((is.null(data) & !is.null(label)) | (!is.null(data) & is.null(label))) {
|
||||||
stop("data/label: Provide the two arguments if you want co-occurence computation or none of them if you are not interested but not one of them only.")
|
stop("data/label: Provide the two arguments if you want co-occurence computation or none of them if you are not interested but not one of them only.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ xgb.importance <- function(feature_names = NULL, filename_dump = NULL, model = N
|
|||||||
d <- data[, result[,Feature], drop=FALSE] < as.numeric(result[,Split])
|
d <- data[, result[,Feature], drop=FALSE] < as.numeric(result[,Split])
|
||||||
apply(c & d, 2, . %>% target %>% sum) -> vec
|
apply(c & d, 2, . %>% target %>% sum) -> vec
|
||||||
|
|
||||||
result <- result[, "RealCover":= as.numeric(vec), with = F][, "RealCover %" := RealCover / sum(label)][,MissingNo:=NULL]
|
result <- result[, "RealCover" := as.numeric(vec), with = F][, "RealCover %" := RealCover / sum(label)][,MissingNo := NULL]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
@ -119,13 +119,13 @@ xgb.importance <- function(feature_names = NULL, filename_dump = NULL, model = N
|
|||||||
treeDump <- function(feature_names, text, keepDetail){
|
treeDump <- function(feature_names, text, keepDetail){
|
||||||
if(keepDetail) groupBy <- c("Feature", "Split", "MissingNo") else groupBy <- "Feature"
|
if(keepDetail) groupBy <- c("Feature", "Split", "MissingNo") else groupBy <- "Feature"
|
||||||
|
|
||||||
result <- xgb.model.dt.tree(feature_names = feature_names, text = text)[,"MissingNo":= Missing == No ][Feature!="Leaf",.(Gain = sum(Quality), Cover = sum(Cover), Frequence = .N), by = groupBy, with = T][,`:=`(Gain = Gain/sum(Gain), Cover = Cover/sum(Cover), Frequence = Frequence/sum(Frequence))][order(Gain, decreasing = T)]
|
result <- xgb.model.dt.tree(feature_names = feature_names, text = text)[,"MissingNo" := Missing == No ][Feature != "Leaf",.(Gain = sum(Quality), Cover = sum(Cover), Frequence = .N), by = groupBy, with = T][,`:=`(Gain = Gain / sum(Gain), Cover = Cover / sum(Cover), Frequence = Frequence / sum(Frequence))][order(Gain, decreasing = T)]
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
linearDump <- function(feature_names, text){
|
linearDump <- function(feature_names, text){
|
||||||
which(text == "weight:") %>% {a=.+1;text[a:length(text)]} %>% as.numeric %>% data.table(Feature = feature_names, Weight = .)
|
which(text == "weight:") %>% {a =. + 1; text[a:length(text)]} %>% as.numeric %>% data.table(Feature = feature_names, Weight = .)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Avoid error messages during CRAN check.
|
# Avoid error messages during CRAN check.
|
||||||
|
|||||||
@ -81,12 +81,12 @@ xgb.model.dt.tree <- function(feature_names = NULL, filename_dump = NULL, model
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!is.null(model)){
|
if(!is.null(model)){
|
||||||
text = xgb.dump(model = model, with.stats = T)
|
text <- xgb.dump(model = model, with.stats = T)
|
||||||
} else if(!is.null(filename_dump)){
|
} else if(!is.null(filename_dump)){
|
||||||
text <- readLines(filename_dump) %>% str_trim(side = "both")
|
text <- readLines(filename_dump) %>% str_trim(side = "both")
|
||||||
}
|
}
|
||||||
|
|
||||||
position <- str_match(text, "booster") %>% is.na %>% not %>% which %>% c(length(text)+1)
|
position <- str_match(text, "booster") %>% is.na %>% not %>% which %>% c(length(text) + 1)
|
||||||
|
|
||||||
extract <- function(x, pattern) str_extract(x, pattern) %>% str_split("=") %>% lapply(function(x) x[2] %>% as.numeric) %>% unlist
|
extract <- function(x, pattern) str_extract(x, pattern) %>% str_split("=") %>% lapply(function(x) x[2] %>% as.numeric) %>% unlist
|
||||||
|
|
||||||
@ -96,15 +96,15 @@ xgb.model.dt.tree <- function(feature_names = NULL, filename_dump = NULL, model
|
|||||||
|
|
||||||
allTrees <- data.table()
|
allTrees <- data.table()
|
||||||
|
|
||||||
anynumber_regex<-"[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?"
|
anynumber_regex <- "[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?"
|
||||||
for(i in 1:n_round){
|
for (i in 1:n_round){
|
||||||
|
|
||||||
tree <- text[(position[i]+1):(position[i+1]-1)]
|
tree <- text[(position[i] + 1):(position[i + 1] - 1)]
|
||||||
|
|
||||||
# avoid tree made of a leaf only (no split)
|
# avoid tree made of a leaf only (no split)
|
||||||
if(length(tree) <2) next
|
if(length(tree) < 2) next
|
||||||
|
|
||||||
treeID <- i-1
|
treeID <- i - 1
|
||||||
|
|
||||||
notLeaf <- str_match(tree, "leaf") %>% is.na
|
notLeaf <- str_match(tree, "leaf") %>% is.na
|
||||||
leaf <- notLeaf %>% not %>% tree[.]
|
leaf <- notLeaf %>% not %>% tree[.]
|
||||||
@ -128,7 +128,7 @@ xgb.model.dt.tree <- function(feature_names = NULL, filename_dump = NULL, model
|
|||||||
qualityLeaf <- extract(leaf, paste0("leaf=",anynumber_regex))
|
qualityLeaf <- extract(leaf, paste0("leaf=",anynumber_regex))
|
||||||
coverBranch <- extract(branch, "cover=\\d*\\.*\\d*")
|
coverBranch <- extract(branch, "cover=\\d*\\.*\\d*")
|
||||||
coverLeaf <- extract(leaf, "cover=\\d*\\.*\\d*")
|
coverLeaf <- extract(leaf, "cover=\\d*\\.*\\d*")
|
||||||
dt <- data.table(ID = c(idBranch, idLeaf), Feature = c(featureBranch, featureLeaf), Split = c(splitBranch, splitLeaf), Yes = c(yesBranch, yesLeaf), No = c(noBranch, noLeaf), Missing = c(missingBranch, missingLeaf), Quality = c(qualityBranch, qualityLeaf), Cover = c(coverBranch, coverLeaf))[order(ID)][,Tree:=treeID]
|
dt <- data.table(ID = c(idBranch, idLeaf), Feature = c(featureBranch, featureLeaf), Split = c(splitBranch, splitLeaf), Yes = c(yesBranch, yesLeaf), No = c(noBranch, noLeaf), Missing = c(missingBranch, missingLeaf), Quality = c(qualityBranch, qualityLeaf), Cover = c(coverBranch, coverLeaf))[order(ID)][,Tree := treeID]
|
||||||
|
|
||||||
allTrees <- rbindlist(list(allTrees, dt), use.names = T, fill = F)
|
allTrees <- rbindlist(list(allTrees, dt), use.names = T, fill = F)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,9 +44,9 @@ xgb.plot.importance <- function(importance_matrix = NULL, numberOfClusters = c(1
|
|||||||
importance_matrix <- importance_matrix[, .(Gain = sum(Gain)), by = Feature]
|
importance_matrix <- importance_matrix[, .(Gain = sum(Gain)), by = Feature]
|
||||||
|
|
||||||
clusters <- suppressWarnings(Ckmeans.1d.dp::Ckmeans.1d.dp(importance_matrix[,Gain], numberOfClusters))
|
clusters <- suppressWarnings(Ckmeans.1d.dp::Ckmeans.1d.dp(importance_matrix[,Gain], numberOfClusters))
|
||||||
importance_matrix[,"Cluster":=clusters$cluster %>% as.character]
|
importance_matrix[,"Cluster" := clusters$cluster %>% as.character]
|
||||||
|
|
||||||
plot <- ggplot2::ggplot(importance_matrix, ggplot2::aes(x=stats::reorder(Feature, Gain), y = Gain, width= 0.05), environment = environment())+ ggplot2::geom_bar(ggplot2::aes(fill=Cluster), stat="identity", position="identity") + ggplot2::coord_flip() + ggplot2::xlab("Features") + ggplot2::ylab("Gain") + ggplot2::ggtitle("Feature importance") + ggplot2::theme(plot.title = ggplot2::element_text(lineheight=.9, face="bold"), panel.grid.major.y = ggplot2::element_blank() )
|
plot <- ggplot2::ggplot(importance_matrix, ggplot2::aes(x=stats::reorder(Feature, Gain), y = Gain, width = 0.05), environment = environment()) + ggplot2::geom_bar(ggplot2::aes(fill=Cluster), stat="identity", position="identity") + ggplot2::coord_flip() + ggplot2::xlab("Features") + ggplot2::ylab("Gain") + ggplot2::ggtitle("Feature importance") + ggplot2::theme(plot.title = ggplot2::element_text(lineheight=.9, face="bold"), panel.grid.major.y = ggplot2::element_blank() )
|
||||||
|
|
||||||
return(plot)
|
return(plot)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,20 +74,19 @@ xgb.plot.tree <- function(feature_names = NULL, filename_dump = NULL, model = NU
|
|||||||
allTrees <- xgb.model.dt.tree(feature_names = feature_names, model = model, n_first_tree = n_first_tree)
|
allTrees <- xgb.model.dt.tree(feature_names = feature_names, model = model, n_first_tree = n_first_tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
allTrees[Feature!="Leaf" ,yesPath:= paste(ID,"(", Feature, "<br/>Cover: ", Cover, "<br/>Gain: ", Quality, ")-->|< ", Split, "|", Yes, ">", Yes.Feature, "]", sep = "")]
|
allTrees[Feature != "Leaf" ,yesPath := paste(ID,"(", Feature, "<br/>Cover: ", Cover, "<br/>Gain: ", Quality, ")-->|< ", Split, "|", Yes, ">", Yes.Feature, "]", sep = "")]
|
||||||
|
|
||||||
allTrees[Feature!="Leaf" ,noPath:= paste(ID,"(", Feature, ")-->|>= ", Split, "|", No, ">", No.Feature, "]", sep = "")]
|
|
||||||
|
|
||||||
|
allTrees[Feature != "Leaf" ,noPath := paste(ID,"(", Feature, ")-->|>= ", Split, "|", No, ">", No.Feature, "]", sep = "")]
|
||||||
|
|
||||||
if(is.null(CSSstyle)){
|
if(is.null(CSSstyle)){
|
||||||
CSSstyle <- "classDef greenNode fill:#A2EB86, stroke:#04C4AB, stroke-width:2px;classDef redNode fill:#FFA070, stroke:#FF5E5E, stroke-width:2px"
|
CSSstyle <- "classDef greenNode fill:#A2EB86, stroke:#04C4AB, stroke-width:2px;classDef redNode fill:#FFA070, stroke:#FF5E5E, stroke-width:2px"
|
||||||
}
|
}
|
||||||
|
|
||||||
yes <- allTrees[Feature!="Leaf", c(Yes)] %>% paste(collapse = ",") %>% paste("class ", ., " greenNode", sep = "")
|
yes <- allTrees[Feature != "Leaf", c(Yes)] %>% paste(collapse = ",") %>% paste("class ", ., " greenNode", sep = "")
|
||||||
|
|
||||||
no <- allTrees[Feature!="Leaf", c(No)] %>% paste(collapse = ",") %>% paste("class ", ., " redNode", sep = "")
|
no <- allTrees[Feature != "Leaf", c(No)] %>% paste(collapse = ",") %>% paste("class ", ., " redNode", sep = "")
|
||||||
|
|
||||||
path <- allTrees[Feature!="Leaf", c(yesPath, noPath)] %>% .[order(.)] %>% paste(sep = "", collapse = ";") %>% paste("graph LR", .,collapse = "", sep = ";") %>% paste(CSSstyle, yes, no, sep = ";")
|
path <- allTrees[Feature != "Leaf", c(yesPath, noPath)] %>% .[order(.)] %>% paste(sep = "", collapse = ";") %>% paste("graph LR", .,collapse = "", sep = ";") %>% paste(CSSstyle, yes, no, sep = ";")
|
||||||
DiagrammeR::mermaid(path, width, height)
|
DiagrammeR::mermaid(path, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -140,27 +140,27 @@ xgb.train <- function(params=list(), data, nrounds, watchlist = list(),
|
|||||||
warning('watchlist is provided but verbose=0, no evaluation information will be printed')
|
warning('watchlist is provided but verbose=0, no evaluation information will be printed')
|
||||||
}
|
}
|
||||||
|
|
||||||
dot.params = list(...)
|
dot.params <- list(...)
|
||||||
nms.params = names(params)
|
nms.params <- names(params)
|
||||||
nms.dot.params = names(dot.params)
|
nms.dot.params <- names(dot.params)
|
||||||
if (length(intersect(nms.params,nms.dot.params))>0)
|
if (length(intersect(nms.params,nms.dot.params)) > 0)
|
||||||
stop("Duplicated term in parameters. Please check your list of params.")
|
stop("Duplicated term in parameters. Please check your list of params.")
|
||||||
params = append(params, dot.params)
|
params <- append(params, dot.params)
|
||||||
|
|
||||||
# customized objective and evaluation metric interface
|
# customized objective and evaluation metric interface
|
||||||
if (!is.null(params$objective) && !is.null(obj))
|
if (!is.null(params$objective) && !is.null(obj))
|
||||||
stop("xgb.train: cannot assign two different objectives")
|
stop("xgb.train: cannot assign two different objectives")
|
||||||
if (!is.null(params$objective))
|
if (!is.null(params$objective))
|
||||||
if (class(params$objective)=='function') {
|
if (class(params$objective) == 'function') {
|
||||||
obj = params$objective
|
obj <- params$objective
|
||||||
params$objective = NULL
|
params$objective <- NULL
|
||||||
}
|
}
|
||||||
if (!is.null(params$eval_metric) && !is.null(feval))
|
if (!is.null(params$eval_metric) && !is.null(feval))
|
||||||
stop("xgb.train: cannot assign two different evaluation metrics")
|
stop("xgb.train: cannot assign two different evaluation metrics")
|
||||||
if (!is.null(params$eval_metric))
|
if (!is.null(params$eval_metric))
|
||||||
if (class(params$eval_metric)=='function') {
|
if (class(params$eval_metric) == 'function') {
|
||||||
feval = params$eval_metric
|
feval <- params$eval_metric
|
||||||
params$eval_metric = NULL
|
params$eval_metric <- NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
# Early stopping
|
# Early stopping
|
||||||
@ -174,44 +174,43 @@ xgb.train <- function(params=list(), data, nrounds, watchlist = list(),
|
|||||||
if (is.null(maximize))
|
if (is.null(maximize))
|
||||||
{
|
{
|
||||||
if (params$eval_metric %in% c('rmse','logloss','error','merror','mlogloss')) {
|
if (params$eval_metric %in% c('rmse','logloss','error','merror','mlogloss')) {
|
||||||
maximize = FALSE
|
maximize <- FALSE
|
||||||
} else {
|
} else {
|
||||||
maximize = TRUE
|
maximize <- TRUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maximize) {
|
if (maximize) {
|
||||||
bestScore = 0
|
bestScore <- 0
|
||||||
} else {
|
} else {
|
||||||
bestScore = Inf
|
bestScore <- Inf
|
||||||
}
|
}
|
||||||
bestInd = 0
|
bestInd <- 0
|
||||||
earlyStopflag = FALSE
|
earlyStopflag = FALSE
|
||||||
|
|
||||||
if (length(watchlist)>1)
|
if (length(watchlist) > 1)
|
||||||
warning('Only the first data set in watchlist is used for early stopping process.')
|
warning('Only the first data set in watchlist is used for early stopping process.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
handle <- xgb.Booster(params, append(watchlist, dtrain))
|
handle <- xgb.Booster(params, append(watchlist, dtrain))
|
||||||
bst <- xgb.handleToBooster(handle)
|
bst <- xgb.handleToBooster(handle)
|
||||||
print.every.n=max( as.integer(print.every.n), 1L)
|
print.every.n <- max( as.integer(print.every.n), 1L)
|
||||||
for (i in 1:nrounds) {
|
for (i in 1:nrounds) {
|
||||||
succ <- xgb.iter.update(bst$handle, dtrain, i - 1, obj)
|
succ <- xgb.iter.update(bst$handle, dtrain, i - 1, obj)
|
||||||
if (length(watchlist) != 0) {
|
if (length(watchlist) != 0) {
|
||||||
msg <- xgb.iter.eval(bst$handle, watchlist, i - 1, feval)
|
msg <- xgb.iter.eval(bst$handle, watchlist, i - 1, feval)
|
||||||
if (0== ( (i-1) %% print.every.n))
|
if (0 == ( (i - 1) %% print.every.n))
|
||||||
cat(paste(msg, "\n", sep=""))
|
cat(paste(msg, "\n", sep = ""))
|
||||||
if (!is.null(early.stop.round))
|
if (!is.null(early.stop.round))
|
||||||
{
|
{
|
||||||
score = strsplit(msg,':|\\s+')[[1]][3]
|
score <- strsplit(msg,':|\\s+')[[1]][3]
|
||||||
score = as.numeric(score)
|
score <- as.numeric(score)
|
||||||
if ((maximize && score>bestScore) || (!maximize && score<bestScore)) {
|
if ( (maximize && score > bestScore) || (!maximize && score < bestScore)) {
|
||||||
bestScore = score
|
bestScore <- score
|
||||||
bestInd = i
|
bestInd <- i
|
||||||
} else {
|
} else {
|
||||||
if (i-bestInd>=early.stop.round) {
|
earlyStopflag = TRUE
|
||||||
earlyStopflag = TRUE
|
if (i - bestInd >= early.stop.round) {
|
||||||
cat('Stopping. Best iteration:',bestInd)
|
cat('Stopping. Best iteration:',bestInd)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -226,8 +225,8 @@ xgb.train <- function(params=list(), data, nrounds, watchlist = list(),
|
|||||||
}
|
}
|
||||||
bst <- xgb.Booster.check(bst)
|
bst <- xgb.Booster.check(bst)
|
||||||
if (!is.null(early.stop.round)) {
|
if (!is.null(early.stop.round)) {
|
||||||
bst$bestScore = bestScore
|
bst$bestScore <- bestScore
|
||||||
bst$bestInd = bestInd
|
bst$bestInd <- bestInd
|
||||||
}
|
}
|
||||||
return(bst)
|
return(bst)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,8 +79,6 @@ xgboost <- function(data = NULL, label = NULL, missing = NA, weight = NULL,
|
|||||||
|
|
||||||
return(bst)
|
return(bst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#' Training part from Mushroom Data Set
|
#' Training part from Mushroom Data Set
|
||||||
#'
|
#'
|
||||||
#' This data set is originally from the Mushroom data set,
|
#' This data set is originally from the Mushroom data set,
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\alias{predict,xgb.Booster-method}
|
\alias{predict,xgb.Booster-method}
|
||||||
\title{Predict method for eXtreme Gradient Boosting model}
|
\title{Predict method for eXtreme Gradient Boosting model}
|
||||||
\usage{
|
\usage{
|
||||||
\S4method{predict}{xgb.Booster}(object, newdata, missing = NULL,
|
\S4method{predict}{xgb.Booster}(object, newdata, missing = NA,
|
||||||
outputmargin = FALSE, ntreelimit = NULL, predleaf = FALSE)
|
outputmargin = FALSE, ntreelimit = NULL, predleaf = FALSE)
|
||||||
}
|
}
|
||||||
\arguments{
|
\arguments{
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
\alias{xgb.DMatrix}
|
\alias{xgb.DMatrix}
|
||||||
\title{Contruct xgb.DMatrix object}
|
\title{Contruct xgb.DMatrix object}
|
||||||
\usage{
|
\usage{
|
||||||
xgb.DMatrix(data, info = list(), missing = 0, ...)
|
xgb.DMatrix(data, info = list(), missing = NA, ...)
|
||||||
}
|
}
|
||||||
\arguments{
|
\arguments{
|
||||||
\item{data}{a \code{matrix} object, a \code{dgCMatrix} object or a character
|
\item{data}{a \code{matrix} object, a \code{dgCMatrix} object or a character
|
||||||
|
|||||||
@ -4,11 +4,10 @@
|
|||||||
\alias{xgb.cv}
|
\alias{xgb.cv}
|
||||||
\title{Cross Validation}
|
\title{Cross Validation}
|
||||||
\usage{
|
\usage{
|
||||||
xgb.cv(params = list(), data, nrounds, nfold, label = NULL,
|
xgb.cv(params = list(), data, nrounds, nfold, label = NULL, missing = NA,
|
||||||
missing = NULL, prediction = FALSE, showsd = TRUE, metrics = list(),
|
prediction = FALSE, showsd = TRUE, metrics = list(), obj = NULL,
|
||||||
obj = NULL, feval = NULL, stratified = TRUE, folds = NULL,
|
feval = NULL, stratified = TRUE, folds = NULL, verbose = T,
|
||||||
verbose = T, print.every.n = 1L, early.stop.round = NULL,
|
print.every.n = 1L, early.stop.round = NULL, maximize = NULL, ...)
|
||||||
maximize = NULL, ...)
|
|
||||||
}
|
}
|
||||||
\arguments{
|
\arguments{
|
||||||
\item{params}{the list of parameters. Commonly used ones are:
|
\item{params}{the list of parameters. Commonly used ones are:
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
\alias{xgboost}
|
\alias{xgboost}
|
||||||
\title{eXtreme Gradient Boosting (Tree) library}
|
\title{eXtreme Gradient Boosting (Tree) library}
|
||||||
\usage{
|
\usage{
|
||||||
xgboost(data = NULL, label = NULL, missing = NULL, weight = NULL,
|
xgboost(data = NULL, label = NULL, missing = NA, weight = NULL,
|
||||||
params = list(), nrounds, verbose = 1, print.every.n = 1L,
|
params = list(), nrounds, verbose = 1, print.every.n = 1L,
|
||||||
early.stop.round = NULL, maximize = NULL, save_period = 0,
|
early.stop.round = NULL, maximize = NULL, save_period = 0,
|
||||||
save_name = "xgboost.model", ...)
|
save_name = "xgboost.model", ...)
|
||||||
|
|||||||
@ -4,30 +4,33 @@ context("basic functions")
|
|||||||
|
|
||||||
data(agaricus.train, package='xgboost')
|
data(agaricus.train, package='xgboost')
|
||||||
data(agaricus.test, package='xgboost')
|
data(agaricus.test, package='xgboost')
|
||||||
train = agaricus.train
|
train <- agaricus.train
|
||||||
test = agaricus.test
|
test <- agaricus.test
|
||||||
|
set.seed(1994)
|
||||||
|
|
||||||
test_that("train and predict", {
|
test_that("train and predict", {
|
||||||
bst = xgboost(data = train$data, label = train$label, max.depth = 2,
|
bst <- xgboost(data = train$data, label = train$label, max.depth = 2,
|
||||||
eta = 1, nthread = 2, nround = 2, objective = "binary:logistic")
|
eta = 1, nthread = 2, nround = 2, objective = "binary:logistic")
|
||||||
pred = predict(bst, test$data)
|
pred <- predict(bst, test$data)
|
||||||
|
expect_equal(length(pred), 1611)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
test_that("early stopping", {
|
test_that("early stopping", {
|
||||||
res = xgb.cv(data = train$data, label = train$label, max.depth = 2, nfold = 5,
|
res <- xgb.cv(data = train$data, label = train$label, max.depth = 2, nfold = 5,
|
||||||
eta = 0.3, nthread = 2, nround = 20, objective = "binary:logistic",
|
eta = 0.3, nthread = 2, nround = 20, objective = "binary:logistic",
|
||||||
early.stop.round = 3, maximize = FALSE)
|
early.stop.round = 3, maximize = FALSE)
|
||||||
expect_true(nrow(res)<20)
|
expect_true(nrow(res) < 20)
|
||||||
bst = xgboost(data = train$data, label = train$label, max.depth = 2,
|
bst <- xgboost(data = train$data, label = train$label, max.depth = 2,
|
||||||
eta = 0.3, nthread = 2, nround = 20, objective = "binary:logistic",
|
eta = 0.3, nthread = 2, nround = 20, objective = "binary:logistic",
|
||||||
early.stop.round = 3, maximize = FALSE)
|
early.stop.round = 3, maximize = FALSE)
|
||||||
pred = predict(bst, test$data)
|
pred <- predict(bst, test$data)
|
||||||
|
expect_equal(length(pred), 1611)
|
||||||
})
|
})
|
||||||
|
|
||||||
test_that("save_period", {
|
test_that("save_period", {
|
||||||
bst = xgboost(data = train$data, label = train$label, max.depth = 2,
|
bst <- xgboost(data = train$data, label = train$label, max.depth = 2,
|
||||||
eta = 0.3, nthread = 2, nround = 20, objective = "binary:logistic",
|
eta = 0.3, nthread = 2, nround = 20, objective = "binary:logistic",
|
||||||
save_period = 10, save_name = "xgb.model")
|
save_period = 10, save_name = "xgb.model")
|
||||||
pred = predict(bst, test$data)
|
pred <- predict(bst, test$data)
|
||||||
|
expect_equal(length(pred), 1611)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2,25 +2,26 @@ context('Test models with custom objective')
|
|||||||
|
|
||||||
require(xgboost)
|
require(xgboost)
|
||||||
|
|
||||||
|
data(agaricus.train, package='xgboost')
|
||||||
|
data(agaricus.test, package='xgboost')
|
||||||
|
dtrain <- xgb.DMatrix(agaricus.train$data, label = agaricus.train$label)
|
||||||
|
dtest <- xgb.DMatrix(agaricus.test$data, label = agaricus.test$label)
|
||||||
|
|
||||||
test_that("custom objective works", {
|
test_that("custom objective works", {
|
||||||
data(agaricus.train, package='xgboost')
|
|
||||||
data(agaricus.test, package='xgboost')
|
|
||||||
dtrain <- xgb.DMatrix(agaricus.train$data, label = agaricus.train$label)
|
|
||||||
dtest <- xgb.DMatrix(agaricus.test$data, label = agaricus.test$label)
|
|
||||||
|
|
||||||
watchlist <- list(eval = dtest, train = dtrain)
|
watchlist <- list(eval = dtest, train = dtrain)
|
||||||
num_round <- 2
|
num_round <- 2
|
||||||
|
|
||||||
logregobj <- function(preds, dtrain) {
|
logregobj <- function(preds, dtrain) {
|
||||||
labels <- getinfo(dtrain, "label")
|
labels <- getinfo(dtrain, "label")
|
||||||
preds <- 1/(1 + exp(-preds))
|
preds <- 1 / (1 + exp(-preds))
|
||||||
grad <- preds - labels
|
grad <- preds - labels
|
||||||
hess <- preds * (1 - preds)
|
hess <- preds * (1 - preds)
|
||||||
return(list(grad = grad, hess = hess))
|
return(list(grad = grad, hess = hess))
|
||||||
}
|
}
|
||||||
evalerror <- function(preds, dtrain) {
|
evalerror <- function(preds, dtrain) {
|
||||||
labels <- getinfo(dtrain, "label")
|
labels <- getinfo(dtrain, "label")
|
||||||
err <- as.numeric(sum(labels != (preds > 0)))/length(labels)
|
err <- as.numeric(sum(labels != (preds > 0))) / length(labels)
|
||||||
return(list(metric = "error", value = err))
|
return(list(metric = "error", value = err))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,13 +35,13 @@ test_that("custom objective works", {
|
|||||||
|
|
||||||
logregobjattr <- function(preds, dtrain) {
|
logregobjattr <- function(preds, dtrain) {
|
||||||
labels <- attr(dtrain, 'label')
|
labels <- attr(dtrain, 'label')
|
||||||
preds <- 1/(1 + exp(-preds))
|
preds <- 1 / (1 + exp(-preds))
|
||||||
grad <- preds - labels
|
grad <- preds - labels
|
||||||
hess <- preds * (1 - preds)
|
hess <- preds * (1 - preds)
|
||||||
return(list(grad = grad, hess = hess))
|
return(list(grad = grad, hess = hess))
|
||||||
}
|
}
|
||||||
param <- list(max.depth=2, eta=1, nthread = 2, silent=1,
|
param <- list(max.depth=2, eta=1, nthread = 2, silent = 1,
|
||||||
objective=logregobjattr, eval_metric=evalerror)
|
objective = logregobjattr, eval_metric = evalerror)
|
||||||
bst <- xgb.train(param, dtrain, num_round, watchlist)
|
bst <- xgb.train(param, dtrain, num_round, watchlist)
|
||||||
expect_equal(class(bst), "xgb.Booster")
|
expect_equal(class(bst), "xgb.Booster")
|
||||||
expect_equal(length(bst$raw), 1064)
|
expect_equal(length(bst$raw), 1064)
|
||||||
|
|||||||
@ -5,26 +5,27 @@ require(data.table)
|
|||||||
require(Matrix)
|
require(Matrix)
|
||||||
require(vcd)
|
require(vcd)
|
||||||
|
|
||||||
|
set.seed(1994)
|
||||||
data(Arthritis)
|
data(Arthritis)
|
||||||
data(agaricus.train, package='xgboost')
|
data(agaricus.train, package='xgboost')
|
||||||
df <- data.table(Arthritis, keep.rownames = F)
|
df <- data.table(Arthritis, keep.rownames = F)
|
||||||
df[,AgeDiscret:= as.factor(round(Age/10,0))]
|
df[,AgeDiscret := as.factor(round(Age / 10,0))]
|
||||||
df[,AgeCat:= as.factor(ifelse(Age > 30, "Old", "Young"))]
|
df[,AgeCat := as.factor(ifelse(Age > 30, "Old", "Young"))]
|
||||||
df[,ID:=NULL]
|
df[,ID := NULL]
|
||||||
sparse_matrix = sparse.model.matrix(Improved~.-1, data = df)
|
sparse_matrix <- sparse.model.matrix(Improved~.-1, data = df)
|
||||||
output_vector = df[,Y:=0][Improved == "Marked",Y:=1][,Y]
|
output_vector <- df[,Y := 0][Improved == "Marked",Y := 1][,Y]
|
||||||
bst <- xgboost(data = sparse_matrix, label = output_vector, max.depth = 9,
|
bst <- xgboost(data = sparse_matrix, label = output_vector, max.depth = 9,
|
||||||
eta = 1, nthread = 2, nround = 10,objective = "binary:logistic")
|
eta = 1, nthread = 2, nround = 10,objective = "binary:logistic")
|
||||||
|
|
||||||
|
|
||||||
test_that("xgb.dump works", {
|
test_that("xgb.dump works", {
|
||||||
capture.output(print(xgb.dump(bst)))
|
capture.output(print(xgb.dump(bst)))
|
||||||
})
|
})
|
||||||
|
|
||||||
test_that("xgb.importance works", {
|
test_that("xgb.importance works", {
|
||||||
xgb.dump(bst, 'xgb.model.dump', with.stats = T)
|
expect_true(xgb.dump(bst, 'xgb.model.dump', with.stats = T))
|
||||||
importance <- xgb.importance(sparse_matrix@Dimnames[[2]], 'xgb.model.dump')
|
importance <- xgb.importance(sparse_matrix@Dimnames[[2]], 'xgb.model.dump')
|
||||||
expect_equal(dim(importance), c(7, 4))
|
expect_equal(dim(importance), c(7, 4))
|
||||||
|
expect_equal(colnames(importance), c("Feature", "Gain", "Cover", "Frequence"))
|
||||||
})
|
})
|
||||||
|
|
||||||
test_that("xgb.plot.tree works", {
|
test_that("xgb.plot.tree works", {
|
||||||
|
|||||||
27
R-package/tests/testthat/test_lint.R
Normal file
27
R-package/tests/testthat/test_lint.R
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
context("Code is of high quality and lint free")
|
||||||
|
test_that("Code Lint", {
|
||||||
|
skip_on_cran()
|
||||||
|
skip_on_travis()
|
||||||
|
skip_if_not_installed("lintr")
|
||||||
|
my_linters <- list(
|
||||||
|
absolute_paths_linter=lintr::absolute_paths_linter,
|
||||||
|
assignment_linter=lintr::assignment_linter,
|
||||||
|
closed_curly_linter=lintr::closed_curly_linter,
|
||||||
|
commas_linter=lintr::commas_linter,
|
||||||
|
# commented_code_linter=lintr::commented_code_linter,
|
||||||
|
infix_spaces_linter=lintr::infix_spaces_linter,
|
||||||
|
line_length_linter=lintr::line_length_linter,
|
||||||
|
no_tab_linter=lintr::no_tab_linter,
|
||||||
|
object_usage_linter=lintr::object_usage_linter,
|
||||||
|
# snake_case_linter=lintr::snake_case_linter,
|
||||||
|
# multiple_dots_linter=lintr::multiple_dots_linter,
|
||||||
|
object_length_linter=lintr::object_length_linter,
|
||||||
|
open_curly_linter=lintr::open_curly_linter,
|
||||||
|
# single_quotes_linter=lintr::single_quotes_linter,
|
||||||
|
spaces_inside_linter=lintr::spaces_inside_linter,
|
||||||
|
spaces_left_parentheses_linter=lintr::spaces_left_parentheses_linter,
|
||||||
|
trailing_blank_lines_linter=lintr::trailing_blank_lines_linter,
|
||||||
|
trailing_whitespace_linter=lintr::trailing_whitespace_linter
|
||||||
|
)
|
||||||
|
# lintr::expect_lint_free(linters=my_linters) # uncomment this if you want to check code quality
|
||||||
|
})
|
||||||
@ -1,13 +1,14 @@
|
|||||||
context('Test poisson regression model')
|
context('Test poisson regression model')
|
||||||
|
|
||||||
require(xgboost)
|
require(xgboost)
|
||||||
|
set.seed(1994)
|
||||||
|
|
||||||
test_that("poisson regression works", {
|
test_that("poisson regression works", {
|
||||||
data(mtcars)
|
data(mtcars)
|
||||||
bst = xgboost(data=as.matrix(mtcars[,-11]),label=mtcars[,11],
|
bst <- xgboost(data = as.matrix(mtcars[,-11]),label = mtcars[,11],
|
||||||
objective='count:poisson',nrounds=5)
|
objective = 'count:poisson', nrounds=5)
|
||||||
expect_equal(class(bst), "xgb.Booster")
|
expect_equal(class(bst), "xgb.Booster")
|
||||||
pred = predict(bst,as.matrix(mtcars[,-11]))
|
pred <- predict(bst,as.matrix(mtcars[, -11]))
|
||||||
expect_equal(length(pred), 32)
|
expect_equal(length(pred), 32)
|
||||||
sqrt(mean((pred-mtcars[,11])^2))
|
expect_equal(sqrt(mean( (pred - mtcars[,11]) ^ 2)), 1.16, tolerance = 0.01)
|
||||||
})
|
})
|
||||||
12
doc/model.md
12
doc/model.md
@ -53,22 +53,22 @@ The tradeoff between the two is also referred as bias-variance tradeoff in machi
|
|||||||
|
|
||||||
|
|
||||||
### Why introduce the general principle
|
### Why introduce the general principle
|
||||||
The elements introduced in above forms the basic elements of supervised learning, and they are naturally the building blocks of machine learning toolkits.
|
The elements introduced above form the basic elements of supervised learning, and they are naturally the building blocks of machine learning toolkits.
|
||||||
For example, you should be able to answer what is the difference and common parts between boosted trees and random forest.
|
For example, you should be able to describe the differences and commonalities between boosted trees and random forests.
|
||||||
Understanding the process in a formalized way also helps us to understand the objective that we are learning and the reason behind the heurestics such as
|
Understanding the process in a formalized way also helps us to understand the objective that we are learning and the reason behind the heurestics such as
|
||||||
pruning and smoothing.
|
pruning and smoothing.
|
||||||
|
|
||||||
Tree Ensemble
|
Tree Ensemble
|
||||||
-------------
|
-------------
|
||||||
Now that we have introduced the elements of supervised learning, let us get started with real trees.
|
Now that we have introduced the elements of supervised learning, let us get started with real trees.
|
||||||
To begin with, let us first learn what is the ***model*** of xgboost: tree ensembles.
|
To begin with, let us first learn about the ***model*** of xgboost: tree ensembles.
|
||||||
The tree ensemble model is a set of classification and regression trees (CART). Here's a simple example of a CART
|
The tree ensemble model is a set of classification and regression trees (CART). Here's a simple example of a CART
|
||||||
that classifies is someone will like computer games.
|
that classifies whether someone will like computer games.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
We classify the members in thie family into different leaves, and assign them the score on corresponding leaf.
|
We classify the members of a family into different leaves, and assign them the score on corresponding leaf.
|
||||||
A CART is a bit different from decision trees, where the leaf only contain decision values. In CART, a real score
|
A CART is a bit different from decision trees, where the leaf only contains decision values. In CART, a real score
|
||||||
is associated with each of the leaves, which gives us richer interpretations that go beyond classification.
|
is associated with each of the leaves, which gives us richer interpretations that go beyond classification.
|
||||||
This also makes the unified optimization step easier, as we will see in later part of this tutorial.
|
This also makes the unified optimization step easier, as we will see in later part of this tutorial.
|
||||||
|
|
||||||
|
|||||||
@ -97,9 +97,9 @@ Command Line Parameters
|
|||||||
-----------------------
|
-----------------------
|
||||||
The following parameters are only used in the console version of xgboost
|
The following parameters are only used in the console version of xgboost
|
||||||
* use_buffer [ default=1 ]
|
* use_buffer [ default=1 ]
|
||||||
- whether create binary buffer for text input, this normally will speedup loading when do
|
- Whether to create a binary buffer from text input. Doing so normally will speed up loading times
|
||||||
* num_round
|
* num_round
|
||||||
- the number of round for boosting.
|
- The number of rounds for boosting
|
||||||
* data
|
* data
|
||||||
- The path of training data
|
- The path of training data
|
||||||
* test:data
|
* test:data
|
||||||
|
|||||||
@ -8,7 +8,7 @@ This document gives a basic walkthrough of xgboost python package.
|
|||||||
|
|
||||||
Install XGBoost
|
Install XGBoost
|
||||||
---------------
|
---------------
|
||||||
To install XGBoost, do the following steps.
|
To install XGBoost, do the following steps:
|
||||||
|
|
||||||
* You need to run `make` in the root directory of the project
|
* You need to run `make` in the root directory of the project
|
||||||
* In the `python-package` directory run
|
* In the `python-package` directory run
|
||||||
@ -22,34 +22,39 @@ import xgboost as xgb
|
|||||||
|
|
||||||
Data Interface
|
Data Interface
|
||||||
--------------
|
--------------
|
||||||
XGBoost python module is able to loading from libsvm txt format file, Numpy 2D array and xgboost binary buffer file. The data will be store in ```DMatrix``` object.
|
The XGBoost python module is able to load data from:
|
||||||
|
- libsvm txt format file
|
||||||
|
- Numpy 2D array, and
|
||||||
|
- xgboost binary buffer file.
|
||||||
|
|
||||||
* To load libsvm text format file and XGBoost binary file into ```DMatrix```, the usage is like
|
The data will be store in a ```DMatrix``` object.
|
||||||
|
|
||||||
|
* To load a libsvm text file or a XGBoost binary file into ```DMatrix```, the command is:
|
||||||
```python
|
```python
|
||||||
dtrain = xgb.DMatrix('train.svm.txt')
|
dtrain = xgb.DMatrix('train.svm.txt')
|
||||||
dtest = xgb.DMatrix('test.svm.buffer')
|
dtest = xgb.DMatrix('test.svm.buffer')
|
||||||
```
|
```
|
||||||
* To load numpy array into ```DMatrix```, the usage is like
|
* To load a numpy array into ```DMatrix```, the command is:
|
||||||
```python
|
```python
|
||||||
data = np.random.rand(5,10) # 5 entities, each contains 10 features
|
data = np.random.rand(5,10) # 5 entities, each contains 10 features
|
||||||
label = np.random.randint(2, size=5) # binary target
|
label = np.random.randint(2, size=5) # binary target
|
||||||
dtrain = xgb.DMatrix( data, label=label)
|
dtrain = xgb.DMatrix( data, label=label)
|
||||||
```
|
```
|
||||||
* Build ```DMatrix``` from ```scipy.sparse```
|
* To load a scpiy.sparse array into ```DMatrix```, the command is:
|
||||||
```python
|
```python
|
||||||
csr = scipy.sparse.csr_matrix((dat, (row, col)))
|
csr = scipy.sparse.csr_matrix((dat, (row, col)))
|
||||||
dtrain = xgb.DMatrix(csr)
|
dtrain = xgb.DMatrix(csr)
|
||||||
```
|
```
|
||||||
* Saving ```DMatrix``` into XGBoost binary file will make loading faster in next time. The usage is like:
|
* Saving ```DMatrix``` into XGBoost binary file will make loading faster in next time:
|
||||||
```python
|
```python
|
||||||
dtrain = xgb.DMatrix('train.svm.txt')
|
dtrain = xgb.DMatrix('train.svm.txt')
|
||||||
dtrain.save_binary("train.buffer")
|
dtrain.save_binary("train.buffer")
|
||||||
```
|
```
|
||||||
* To handle missing value in ```DMatrix```, you can initialize the ```DMatrix``` like:
|
* To handle missing value in ```DMatrix```, you can initialize the ```DMatrix``` by specifying missing values:
|
||||||
```python
|
```python
|
||||||
dtrain = xgb.DMatrix(data, label=label, missing = -999.0)
|
dtrain = xgb.DMatrix(data, label=label, missing = -999.0)
|
||||||
```
|
```
|
||||||
* Weight can be set when needed, like
|
* Weight can be set when needed:
|
||||||
```python
|
```python
|
||||||
w = np.random.rand(5, 1)
|
w = np.random.rand(5, 1)
|
||||||
dtrain = xgb.DMatrix(data, label=label, missing = -999.0, weight=w)
|
dtrain = xgb.DMatrix(data, label=label, missing = -999.0, weight=w)
|
||||||
|
|||||||
@ -5,3 +5,10 @@ recursive-include xgboost/windows *
|
|||||||
recursive-include xgboost/subtree *
|
recursive-include xgboost/subtree *
|
||||||
recursive-include xgboost/src *
|
recursive-include xgboost/src *
|
||||||
recursive-include xgboost/multi-node *
|
recursive-include xgboost/multi-node *
|
||||||
|
#exclude pre-compiled .o file for less confusions
|
||||||
|
#include the pre-compiled .so is needed as a placeholder
|
||||||
|
#since it will be copy after compiling on the fly
|
||||||
|
global-exclude xgboost/wrapper/*.so.gz
|
||||||
|
global-exclude xgboost/*.o
|
||||||
|
global-exclude *.pyo
|
||||||
|
global-exclude *.pyc
|
||||||
|
|||||||
48
python-package/build_trouble_shooting.md
Normal file
48
python-package/build_trouble_shooting.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
XGBoost Python Package Troubleshooting
|
||||||
|
======================
|
||||||
|
Windows platform
|
||||||
|
------------
|
||||||
|
The current best solution for installing xgboost on windows machine is building from github. Please go to [windows](/windows/), build with the Visual Studio project file, and install. Additional detailed instruction can be found at this [installation tutorial](https://www.kaggle.com/c/otto-group-product-classification-challenge/forums/t/13043/run-xgboost-from-windows-and-python) from Kaggle Otto Forum.
|
||||||
|
|
||||||
|
`pip install xgboost` is **not** tested nor supported in windows platform for now.
|
||||||
|
|
||||||
|
Linux platform (also Mac OS X in general)
|
||||||
|
------------
|
||||||
|
**Trouble 0**: I see error messages like this when install from github using `python setup.py install`.
|
||||||
|
|
||||||
|
XGBoostLibraryNotFound: Cannot find XGBoost Libarary in the candicate path, did you install compilers and run build.sh in root path?
|
||||||
|
List of candidates:
|
||||||
|
/home/dmlc/anaconda/lib/python2.7/site-packages/xgboost-0.4-py2.7.egg/xgboost/libxgboostwrapper.so
|
||||||
|
/home/dmlc/anaconda/lib/python2.7/site-packages/xgboost-0.4-py2.7.egg/xgboost/../../wrapper/libxgboostwrapper.so
|
||||||
|
/home/dmlc/anaconda/lib/python2.7/site-packages/xgboost-0.4-py2.7.egg/xgboost/./wrapper/libxgboostwrapper.so
|
||||||
|
|
||||||
|
**Solution 0**: Please check if you have:
|
||||||
|
|
||||||
|
* installed C++ compilers, for example `g++` and `gcc` (Linux) or `clang LLVM` (Mac OS X). Recommended compilers are `g++-5` or newer (Linux and Mac), or `clang` comes with Xcode in Mac OS X. For installting compilers, please refer to your system package management commands, e.g. `apt-get` `yum` or `brew`(Mac).
|
||||||
|
* compilers in your `$PATH`. Try typing `gcc` and see if your have it in your path.
|
||||||
|
|
||||||
|
**Trouble 1**: I see the same error message in **Trouble 0** when install from `pip install xgboost`.
|
||||||
|
|
||||||
|
**Solution 1**: the problem is the same as in **Trouble 0**, please see **Solution 0**.
|
||||||
|
|
||||||
|
**Trouble 2**: I see this error message when `pip install xgboost`. It says I have `libxgboostwrapper.so` but it is not valid.
|
||||||
|
|
||||||
|
OSError: /home/dmlc/anaconda/lib/python2.7/site-packages/xgboost/./wrapper/libxgboostwrapper.so: invalid ELF header
|
||||||
|
|
||||||
|
**Solution 2**: Solution is as in 0 and 1 by installing `g++` compiler. The reason for this rare error is that, `pip` ships with a pre-compiled `libxgboostwrapper.so` with Mac for placeholder for allowing `setup.py` to find the right lib path. If a system doesn't compile, it may refer to this placeholder lib and fail. This placeholder `libxgboostwrapper.so` will be automatically removed and correctly generated by the compiling on-the-fly for the system.
|
||||||
|
|
||||||
|
**Trouble 3**: My system's `pip` says it can't find a valid `xgboost` installation release on `PyPI`.
|
||||||
|
**Solution 3**: Some linux system comes with an old `pip` version. Please update to the latest `pip` by following the official installation document at <http://pip.readthedocs.org/en/stable/installing/>
|
||||||
|
|
||||||
|
**Trouble 4**: I tried `python setup.py install` but it says `setuptools` import fail.
|
||||||
|
**Solution 4**: Please make sure you have [setuptools](https://pypi.python.org/pypi/setuptools) before installing the python package.
|
||||||
|
|
||||||
|
Mac OS X (specific)
|
||||||
|
------------
|
||||||
|
Most of the troubles and solutions are the same with that in the Linux platform. Mac has the following specific problems.
|
||||||
|
|
||||||
|
**Trouble 0**: I successfully installed `xgboost` using github installation/using `pip install xgboost`. But it runs very slow with only single thread, what is going on?
|
||||||
|
**Solution 0**: `clang LLVM` compiler on Mac OS X from Xcode doesn't support OpenMP multi-thread. An alternative choice is installing `homebrew` <http://brew.sh/> and `brew install g++-5` which provides multi-thread OpenMP support.
|
||||||
|
|
||||||
|
**Trouble 1**: Can I install `clang-omp` for supporting OpenMP without using `gcc`?
|
||||||
|
**Solution 1**: it is not support and may have linking errors.
|
||||||
@ -2,21 +2,10 @@
|
|||||||
"""Setup xgboost package."""
|
"""Setup xgboost package."""
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
import sys
|
import sys
|
||||||
from setuptools import setup, find_packages
|
|
||||||
import subprocess
|
|
||||||
sys.path.insert(0, '.')
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
#build on the fly if install in pip
|
from setuptools import setup, find_packages
|
||||||
#otherwise, use build.sh in the parent directory
|
#import subprocess
|
||||||
|
sys.path.insert(0, '.')
|
||||||
if 'pip' in __file__:
|
|
||||||
if not os.name == 'nt': #if not windows
|
|
||||||
build_sh = subprocess.Popen(['sh', 'xgboost/build-python.sh'])
|
|
||||||
build_sh.wait()
|
|
||||||
output = build_sh.communicate()
|
|
||||||
print(output)
|
|
||||||
|
|
||||||
|
|
||||||
CURRENT_DIR = os.path.dirname(__file__)
|
CURRENT_DIR = os.path.dirname(__file__)
|
||||||
|
|
||||||
@ -28,15 +17,12 @@ libpath = {'__file__': libpath_py}
|
|||||||
exec(compile(open(libpath_py, "rb").read(), libpath_py, 'exec'), libpath, libpath)
|
exec(compile(open(libpath_py, "rb").read(), libpath_py, 'exec'), libpath, libpath)
|
||||||
|
|
||||||
LIB_PATH = libpath['find_lib_path']()
|
LIB_PATH = libpath['find_lib_path']()
|
||||||
#print LIB_PATH
|
|
||||||
|
|
||||||
#to deploy to pip, please use
|
#Please use setup_pip.py for generating and deploying pip installation
|
||||||
#make pythonpack
|
#detailed instruction in setup_pip.py
|
||||||
#python setup.py register sdist upload
|
|
||||||
#and be sure to test it firstly using "python setup.py register sdist upload -r pypitest"
|
|
||||||
setup(name='xgboost',
|
setup(name='xgboost',
|
||||||
version=open(os.path.join(CURRENT_DIR, 'xgboost/VERSION')).read().strip(),
|
version=open(os.path.join(CURRENT_DIR, 'xgboost/VERSION')).read().strip(),
|
||||||
#version='0.4a13',
|
#version='0.4a23',
|
||||||
description=open(os.path.join(CURRENT_DIR, 'README.md')).read(),
|
description=open(os.path.join(CURRENT_DIR, 'README.md')).read(),
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'numpy',
|
'numpy',
|
||||||
@ -46,10 +32,6 @@ setup(name='xgboost',
|
|||||||
maintainer_email='phunter.lau@gmail.com',
|
maintainer_email='phunter.lau@gmail.com',
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
#don't need this and don't use this, give everything to MANIFEST.in
|
|
||||||
#package_dir = {'':'xgboost'},
|
|
||||||
#package_data = {'': ['*.txt','*.md','*.sh'],
|
|
||||||
# }
|
|
||||||
#this will use MANIFEST.in during install where we specify additional files,
|
#this will use MANIFEST.in during install where we specify additional files,
|
||||||
#this is the golden line
|
#this is the golden line
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
|
|||||||
58
python-package/setup_pip.py
Normal file
58
python-package/setup_pip.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# pylint: disable=invalid-name, exec-used
|
||||||
|
"""Setup xgboost package."""
|
||||||
|
from __future__ import absolute_import
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
#import subprocess
|
||||||
|
sys.path.insert(0, '.')
|
||||||
|
|
||||||
|
#this script is for packing and shipping pip installation
|
||||||
|
#it builds xgboost code on the fly and packs for pip
|
||||||
|
#please don't use this file for installing from github
|
||||||
|
|
||||||
|
if not os.name == 'nt': #if not windows, compile and install
|
||||||
|
os.system('sh ./xgboost/build-python.sh')
|
||||||
|
else:
|
||||||
|
print('Windows users please use github installation.')
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
CURRENT_DIR = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
# We can not import `xgboost.libpath` in setup.py directly since xgboost/__init__.py
|
||||||
|
# import `xgboost.core` and finally will import `numpy` and `scipy` which are setup
|
||||||
|
# `install_requires`. That's why we're using `exec` here.
|
||||||
|
libpath_py = os.path.join(CURRENT_DIR, 'xgboost/libpath.py')
|
||||||
|
libpath = {'__file__': libpath_py}
|
||||||
|
exec(compile(open(libpath_py, "rb").read(), libpath_py, 'exec'), libpath, libpath)
|
||||||
|
|
||||||
|
LIB_PATH = libpath['find_lib_path']()
|
||||||
|
|
||||||
|
#to deploy to pip, please use
|
||||||
|
#make pythonpack
|
||||||
|
#python setup.py register sdist upload
|
||||||
|
#and be sure to test it firstly using "python setup.py register sdist upload -r pypitest"
|
||||||
|
setup(name='xgboost',
|
||||||
|
#version=open(os.path.join(CURRENT_DIR, 'xgboost/VERSION')).read().strip(),
|
||||||
|
version='0.4a24',
|
||||||
|
description=open(os.path.join(CURRENT_DIR, 'README.md')).read(),
|
||||||
|
install_requires=[
|
||||||
|
'numpy',
|
||||||
|
'scipy',
|
||||||
|
],
|
||||||
|
maintainer='Hongliang Liu',
|
||||||
|
maintainer_email='phunter.lau@gmail.com',
|
||||||
|
zip_safe=False,
|
||||||
|
packages=find_packages(),
|
||||||
|
#don't need this and don't use this, give everything to MANIFEST.in
|
||||||
|
#package_dir = {'':'xgboost'},
|
||||||
|
#package_data = {'': ['*.txt','*.md','*.sh'],
|
||||||
|
# }
|
||||||
|
#this will use MANIFEST.in during install where we specify additional files,
|
||||||
|
#this is the golden line
|
||||||
|
include_package_data=True,
|
||||||
|
#!!! don't use data_files for creating pip installation,
|
||||||
|
#otherwise install_data process will copy it to
|
||||||
|
#root directory for some machines, and cause confusions on building
|
||||||
|
#data_files=[('xgboost', LIB_PATH)],
|
||||||
|
url='https://github.com/dmlc/xgboost')
|
||||||
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
|
|
||||||
pushd xgboost
|
pushd xgboost
|
||||||
|
#remove the pre-compiled .so and trigger the system's on-the-fly compiling
|
||||||
|
make clean
|
||||||
if make python; then
|
if make python; then
|
||||||
echo "Successfully build multi-thread xgboost"
|
echo "Successfully build multi-thread xgboost"
|
||||||
else
|
else
|
||||||
|
|||||||
@ -249,7 +249,7 @@ class DMatrix(object):
|
|||||||
csr = scipy.sparse.csr_matrix(data)
|
csr = scipy.sparse.csr_matrix(data)
|
||||||
self._init_from_csr(csr)
|
self._init_from_csr(csr)
|
||||||
except:
|
except:
|
||||||
raise TypeError('can not intialize DMatrix from {}'.format(type(data).__name__))
|
raise TypeError('can not initialize DMatrix from {}'.format(type(data).__name__))
|
||||||
if label is not None:
|
if label is not None:
|
||||||
self.set_label(label)
|
self.set_label(label)
|
||||||
if weight is not None:
|
if weight is not None:
|
||||||
|
|||||||
@ -36,9 +36,10 @@ def find_lib_path():
|
|||||||
else:
|
else:
|
||||||
dll_path = [os.path.join(p, 'libxgboostwrapper.so') for p in dll_path]
|
dll_path = [os.path.join(p, 'libxgboostwrapper.so') for p in dll_path]
|
||||||
lib_path = [p for p in dll_path if os.path.exists(p) and os.path.isfile(p)]
|
lib_path = [p for p in dll_path if os.path.exists(p) and os.path.isfile(p)]
|
||||||
|
#From github issues, most of installation errors come from machines w/o compilers
|
||||||
if len(lib_path) == 0 and not os.environ.get('XGBOOST_BUILD_DOC', False):
|
if len(lib_path) == 0 and not os.environ.get('XGBOOST_BUILD_DOC', False):
|
||||||
raise XGBoostLibraryNotFound(
|
raise XGBoostLibraryNotFound(
|
||||||
'Cannot find XGBoost Libarary in the candicate path, ' +
|
'Cannot find XGBoost Libarary in the candicate path, ' +
|
||||||
'did you run build.sh in root path?\n'
|
'did you install compilers and run build.sh in root path?\n'
|
||||||
'List of candidates:\n' + ('\n'.join(dll_path)))
|
'List of candidates:\n' + ('\n'.join(dll_path)))
|
||||||
return lib_path
|
return lib_path
|
||||||
|
|||||||
@ -7,11 +7,12 @@ from __future__ import absolute_import
|
|||||||
import re
|
import re
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .core import Booster
|
from .core import Booster
|
||||||
|
from .sklearn import XGBModel
|
||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
def plot_importance(booster, ax=None, height=0.2,
|
def plot_importance(booster, ax=None, height=0.2,
|
||||||
xlim=None, title='Feature importance',
|
xlim=None, ylim=None, title='Feature importance',
|
||||||
xlabel='F score', ylabel='Features',
|
xlabel='F score', ylabel='Features',
|
||||||
grid=True, **kwargs):
|
grid=True, **kwargs):
|
||||||
|
|
||||||
@ -19,14 +20,16 @@ def plot_importance(booster, ax=None, height=0.2,
|
|||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
booster : Booster or dict
|
booster : Booster, XGBModel or dict
|
||||||
Booster instance, or dict taken by Booster.get_fscore()
|
Booster or XGBModel instance, or dict taken by Booster.get_fscore()
|
||||||
ax : matplotlib Axes, default None
|
ax : matplotlib Axes, default None
|
||||||
Target axes instance. If None, new figure and axes will be created.
|
Target axes instance. If None, new figure and axes will be created.
|
||||||
height : float, default 0.2
|
height : float, default 0.2
|
||||||
Bar height, passed to ax.barh()
|
Bar height, passed to ax.barh()
|
||||||
xlim : tuple, default None
|
xlim : tuple, default None
|
||||||
Tuple passed to axes.xlim()
|
Tuple passed to axes.xlim()
|
||||||
|
ylim : tuple, default None
|
||||||
|
Tuple passed to axes.ylim()
|
||||||
title : str, default "Feature importance"
|
title : str, default "Feature importance"
|
||||||
Axes title. To disable, pass None.
|
Axes title. To disable, pass None.
|
||||||
xlabel : str, default "F score"
|
xlabel : str, default "F score"
|
||||||
@ -46,12 +49,14 @@ def plot_importance(booster, ax=None, height=0.2,
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError('You must install matplotlib to plot importance')
|
raise ImportError('You must install matplotlib to plot importance')
|
||||||
|
|
||||||
if isinstance(booster, Booster):
|
if isinstance(booster, XGBModel):
|
||||||
|
importance = booster.booster().get_fscore()
|
||||||
|
elif isinstance(booster, Booster):
|
||||||
importance = booster.get_fscore()
|
importance = booster.get_fscore()
|
||||||
elif isinstance(booster, dict):
|
elif isinstance(booster, dict):
|
||||||
importance = booster
|
importance = booster
|
||||||
else:
|
else:
|
||||||
raise ValueError('tree must be Booster or dict instance')
|
raise ValueError('tree must be Booster, XGBModel or dict instance')
|
||||||
|
|
||||||
if len(importance) == 0:
|
if len(importance) == 0:
|
||||||
raise ValueError('Booster.get_fscore() results in empty')
|
raise ValueError('Booster.get_fscore() results in empty')
|
||||||
@ -73,12 +78,19 @@ def plot_importance(booster, ax=None, height=0.2,
|
|||||||
ax.set_yticklabels(labels)
|
ax.set_yticklabels(labels)
|
||||||
|
|
||||||
if xlim is not None:
|
if xlim is not None:
|
||||||
if not isinstance(xlim, tuple) or len(xlim, 2):
|
if not isinstance(xlim, tuple) or len(xlim) != 2:
|
||||||
raise ValueError('xlim must be a tuple of 2 elements')
|
raise ValueError('xlim must be a tuple of 2 elements')
|
||||||
else:
|
else:
|
||||||
xlim = (0, max(values) * 1.1)
|
xlim = (0, max(values) * 1.1)
|
||||||
ax.set_xlim(xlim)
|
ax.set_xlim(xlim)
|
||||||
|
|
||||||
|
if ylim is not None:
|
||||||
|
if not isinstance(ylim, tuple) or len(ylim) != 2:
|
||||||
|
raise ValueError('ylim must be a tuple of 2 elements')
|
||||||
|
else:
|
||||||
|
ylim = (-1, len(importance))
|
||||||
|
ax.set_ylim(ylim)
|
||||||
|
|
||||||
if title is not None:
|
if title is not None:
|
||||||
ax.set_title(title)
|
ax.set_title(title)
|
||||||
if xlabel is not None:
|
if xlabel is not None:
|
||||||
@ -142,8 +154,8 @@ def to_graphviz(booster, num_trees=0, rankdir='UT',
|
|||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
booster : Booster
|
booster : Booster, XGBModel
|
||||||
Booster instance
|
Booster or XGBModel instance
|
||||||
num_trees : int, default 0
|
num_trees : int, default 0
|
||||||
Specify the ordinal number of target tree
|
Specify the ordinal number of target tree
|
||||||
rankdir : str, default "UT"
|
rankdir : str, default "UT"
|
||||||
@ -165,8 +177,11 @@ def to_graphviz(booster, num_trees=0, rankdir='UT',
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError('You must install graphviz to plot tree')
|
raise ImportError('You must install graphviz to plot tree')
|
||||||
|
|
||||||
if not isinstance(booster, Booster):
|
if not isinstance(booster, (Booster, XGBModel)):
|
||||||
raise ValueError('booster must be Booster instance')
|
raise ValueError('booster must be Booster or XGBModel instance')
|
||||||
|
|
||||||
|
if isinstance(booster, XGBModel):
|
||||||
|
booster = booster.booster()
|
||||||
|
|
||||||
tree = booster.get_dump()[num_trees]
|
tree = booster.get_dump()[num_trees]
|
||||||
tree = tree.split()
|
tree = tree.split()
|
||||||
@ -193,8 +208,8 @@ def plot_tree(booster, num_trees=0, rankdir='UT', ax=None, **kwargs):
|
|||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
booster : Booster
|
booster : Booster, XGBModel
|
||||||
Booster instance
|
Booster or XGBModel instance
|
||||||
num_trees : int, default 0
|
num_trees : int, default 0
|
||||||
Specify the ordinal number of target tree
|
Specify the ordinal number of target tree
|
||||||
rankdir : str, default "UT"
|
rankdir : str, default "UT"
|
||||||
@ -216,7 +231,6 @@ def plot_tree(booster, num_trees=0, rankdir='UT', ax=None, **kwargs):
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError('You must install matplotlib to plot tree')
|
raise ImportError('You must install matplotlib to plot tree')
|
||||||
|
|
||||||
|
|
||||||
if ax is None:
|
if ax is None:
|
||||||
_, ax = plt.subplots(1, 1)
|
_, ax = plt.subplots(1, 1)
|
||||||
|
|
||||||
|
|||||||
@ -54,6 +54,14 @@ class XGBModel(XGBModelBase):
|
|||||||
Subsample ratio of the training instance.
|
Subsample ratio of the training instance.
|
||||||
colsample_bytree : float
|
colsample_bytree : float
|
||||||
Subsample ratio of columns when constructing each tree.
|
Subsample ratio of columns when constructing each tree.
|
||||||
|
colsample_bylevel : float
|
||||||
|
Subsample ratio of columns for each split, in each level.
|
||||||
|
reg_alpha : float (xgb's alpha)
|
||||||
|
L2 regularization term on weights
|
||||||
|
reg_lambda : float (xgb's lambda)
|
||||||
|
L1 regularization term on weights
|
||||||
|
scale_pos_weight : float
|
||||||
|
Balancing of positive and negative weights.
|
||||||
|
|
||||||
base_score:
|
base_score:
|
||||||
The initial prediction score of all instances, global bias.
|
The initial prediction score of all instances, global bias.
|
||||||
@ -66,7 +74,8 @@ class XGBModel(XGBModelBase):
|
|||||||
def __init__(self, max_depth=3, learning_rate=0.1, n_estimators=100,
|
def __init__(self, max_depth=3, learning_rate=0.1, n_estimators=100,
|
||||||
silent=True, objective="reg:linear",
|
silent=True, objective="reg:linear",
|
||||||
nthread=-1, gamma=0, min_child_weight=1, max_delta_step=0,
|
nthread=-1, gamma=0, min_child_weight=1, max_delta_step=0,
|
||||||
subsample=1, colsample_bytree=1,
|
subsample=1, colsample_bytree=1, colsample_bylevel=1,
|
||||||
|
reg_alpha=0, reg_lambda=1, scale_pos_weight=1,
|
||||||
base_score=0.5, seed=0, missing=None):
|
base_score=0.5, seed=0, missing=None):
|
||||||
if not SKLEARN_INSTALLED:
|
if not SKLEARN_INSTALLED:
|
||||||
raise XGBoostError('sklearn needs to be installed in order to use this module')
|
raise XGBoostError('sklearn needs to be installed in order to use this module')
|
||||||
@ -82,6 +91,10 @@ class XGBModel(XGBModelBase):
|
|||||||
self.max_delta_step = max_delta_step
|
self.max_delta_step = max_delta_step
|
||||||
self.subsample = subsample
|
self.subsample = subsample
|
||||||
self.colsample_bytree = colsample_bytree
|
self.colsample_bytree = colsample_bytree
|
||||||
|
self.colsample_bylevel = colsample_bylevel
|
||||||
|
self.reg_alpha = reg_alpha
|
||||||
|
self.reg_lambda = reg_lambda
|
||||||
|
self.scale_pos_weight = scale_pos_weight
|
||||||
|
|
||||||
self.base_score = base_score
|
self.base_score = base_score
|
||||||
self.seed = seed
|
self.seed = seed
|
||||||
@ -190,7 +203,7 @@ class XGBModel(XGBModelBase):
|
|||||||
|
|
||||||
if evals_result:
|
if evals_result:
|
||||||
for val in evals_result.items():
|
for val in evals_result.items():
|
||||||
evals_result_key = val[1].keys()[0]
|
evals_result_key = list(val[1].keys())[0]
|
||||||
evals_result[val[0]][evals_result_key] = val[1][evals_result_key]
|
evals_result[val[0]][evals_result_key] = val[1][evals_result_key]
|
||||||
self.evals_result_ = evals_result
|
self.evals_result_ = evals_result
|
||||||
|
|
||||||
@ -199,10 +212,12 @@ class XGBModel(XGBModelBase):
|
|||||||
self.best_iteration = self._Booster.best_iteration
|
self.best_iteration = self._Booster.best_iteration
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def predict(self, data):
|
def predict(self, data, output_margin=False, ntree_limit=0):
|
||||||
# pylint: disable=missing-docstring,invalid-name
|
# pylint: disable=missing-docstring,invalid-name
|
||||||
test_dmatrix = DMatrix(data, missing=self.missing)
|
test_dmatrix = DMatrix(data, missing=self.missing)
|
||||||
return self.booster().predict(test_dmatrix)
|
return self.booster().predict(test_dmatrix,
|
||||||
|
output_margin=output_margin,
|
||||||
|
ntree_limit=ntree_limit)
|
||||||
|
|
||||||
def evals_result(self):
|
def evals_result(self):
|
||||||
"""Return the evaluation results.
|
"""Return the evaluation results.
|
||||||
@ -251,14 +266,16 @@ class XGBClassifier(XGBModel, XGBClassifierBase):
|
|||||||
n_estimators=100, silent=True,
|
n_estimators=100, silent=True,
|
||||||
objective="binary:logistic",
|
objective="binary:logistic",
|
||||||
nthread=-1, gamma=0, min_child_weight=1,
|
nthread=-1, gamma=0, min_child_weight=1,
|
||||||
max_delta_step=0, subsample=1, colsample_bytree=1,
|
max_delta_step=0, subsample=1, colsample_bytree=1, colsample_bylevel=1,
|
||||||
|
reg_alpha=0, reg_lambda=1, scale_pos_weight=1,
|
||||||
base_score=0.5, seed=0, missing=None):
|
base_score=0.5, seed=0, missing=None):
|
||||||
super(XGBClassifier, self).__init__(max_depth, learning_rate,
|
super(XGBClassifier, self).__init__(max_depth, learning_rate,
|
||||||
n_estimators, silent, objective,
|
n_estimators, silent, objective,
|
||||||
nthread, gamma, min_child_weight,
|
nthread, gamma, min_child_weight,
|
||||||
max_delta_step, subsample,
|
max_delta_step, subsample,
|
||||||
colsample_bytree,
|
colsample_bytree, colsample_bylevel,
|
||||||
base_score, seed, missing)
|
reg_alpha, reg_lambda,
|
||||||
|
scale_pos_weight, base_score, seed, missing)
|
||||||
|
|
||||||
def fit(self, X, y, sample_weight=None, eval_set=None, eval_metric=None,
|
def fit(self, X, y, sample_weight=None, eval_set=None, eval_metric=None,
|
||||||
early_stopping_rounds=None, verbose=True):
|
early_stopping_rounds=None, verbose=True):
|
||||||
@ -341,7 +358,7 @@ class XGBClassifier(XGBModel, XGBClassifierBase):
|
|||||||
|
|
||||||
if evals_result:
|
if evals_result:
|
||||||
for val in evals_result.items():
|
for val in evals_result.items():
|
||||||
evals_result_key = val[1].keys()[0]
|
evals_result_key = list(val[1].keys())[0]
|
||||||
evals_result[val[0]][evals_result_key] = val[1][evals_result_key]
|
evals_result[val[0]][evals_result_key] = val[1][evals_result_key]
|
||||||
self.evals_result_ = evals_result
|
self.evals_result_ = evals_result
|
||||||
|
|
||||||
@ -351,9 +368,11 @@ class XGBClassifier(XGBModel, XGBClassifierBase):
|
|||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def predict(self, data):
|
def predict(self, data, output_margin=False, ntree_limit=0):
|
||||||
test_dmatrix = DMatrix(data, missing=self.missing)
|
test_dmatrix = DMatrix(data, missing=self.missing)
|
||||||
class_probs = self.booster().predict(test_dmatrix)
|
class_probs = self.booster().predict(test_dmatrix,
|
||||||
|
output_margin=output_margin,
|
||||||
|
ntree_limit=ntree_limit)
|
||||||
if len(class_probs.shape) > 1:
|
if len(class_probs.shape) > 1:
|
||||||
column_indexes = np.argmax(class_probs, axis=1)
|
column_indexes = np.argmax(class_probs, axis=1)
|
||||||
else:
|
else:
|
||||||
@ -361,9 +380,11 @@ class XGBClassifier(XGBModel, XGBClassifierBase):
|
|||||||
column_indexes[class_probs > 0.5] = 1
|
column_indexes[class_probs > 0.5] = 1
|
||||||
return self._le.inverse_transform(column_indexes)
|
return self._le.inverse_transform(column_indexes)
|
||||||
|
|
||||||
def predict_proba(self, data):
|
def predict_proba(self, data, output_margin=False, ntree_limit=0):
|
||||||
test_dmatrix = DMatrix(data, missing=self.missing)
|
test_dmatrix = DMatrix(data, missing=self.missing)
|
||||||
class_probs = self.booster().predict(test_dmatrix)
|
class_probs = self.booster().predict(test_dmatrix,
|
||||||
|
output_margin=output_margin,
|
||||||
|
ntree_limit=ntree_limit)
|
||||||
if self.objective == "multi:softprob":
|
if self.objective == "multi:softprob":
|
||||||
return class_probs
|
return class_probs
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -10,7 +10,8 @@ import numpy as np
|
|||||||
from .core import Booster, STRING_TYPES
|
from .core import Booster, STRING_TYPES
|
||||||
|
|
||||||
def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
||||||
early_stopping_rounds=None, evals_result=None, verbose_eval=True):
|
maximize=False, early_stopping_rounds=None, evals_result=None,
|
||||||
|
verbose_eval=True, learning_rates=None, xgb_model=None):
|
||||||
# pylint: disable=too-many-statements,too-many-branches, attribute-defined-outside-init
|
# pylint: disable=too-many-statements,too-many-branches, attribute-defined-outside-init
|
||||||
"""Train a booster with given parameters.
|
"""Train a booster with given parameters.
|
||||||
|
|
||||||
@ -29,6 +30,8 @@ def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
|||||||
Customized objective function.
|
Customized objective function.
|
||||||
feval : function
|
feval : function
|
||||||
Customized evaluation function.
|
Customized evaluation function.
|
||||||
|
maximize : bool
|
||||||
|
Whether to maximize feval.
|
||||||
early_stopping_rounds: int
|
early_stopping_rounds: int
|
||||||
Activates early stopping. Validation error needs to decrease at least
|
Activates early stopping. Validation error needs to decrease at least
|
||||||
every <early_stopping_rounds> round(s) to continue training.
|
every <early_stopping_rounds> round(s) to continue training.
|
||||||
@ -46,13 +49,27 @@ def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
|||||||
verbose_eval : bool
|
verbose_eval : bool
|
||||||
If `verbose_eval` then the evaluation metric on the validation set, if
|
If `verbose_eval` then the evaluation metric on the validation set, if
|
||||||
given, is printed at each boosting stage.
|
given, is printed at each boosting stage.
|
||||||
|
learning_rates: list or function
|
||||||
|
Learning rate for each boosting round (yields learning rate decay).
|
||||||
|
- list l: eta = l[boosting round]
|
||||||
|
- function f: eta = f(boosting round, num_boost_round)
|
||||||
|
xgb_model : file name of stored xgb model or 'Booster' instance
|
||||||
|
Xgb model to be loaded before training (allows training continuation).
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
booster : a trained booster model
|
booster : a trained booster model
|
||||||
"""
|
"""
|
||||||
evals = list(evals)
|
evals = list(evals)
|
||||||
bst = Booster(params, [dtrain] + [d[0] for d in evals])
|
ntrees = 0
|
||||||
|
if xgb_model is not None:
|
||||||
|
if not isinstance(xgb_model, STRING_TYPES):
|
||||||
|
xgb_model = xgb_model.save_raw()
|
||||||
|
bst = Booster(params, [dtrain] + [d[0] for d in evals], model_file=xgb_model)
|
||||||
|
ntrees = len(bst.get_dump())
|
||||||
|
else:
|
||||||
|
bst = Booster(params, [dtrain] + [d[0] for d in evals])
|
||||||
|
|
||||||
|
|
||||||
if evals_result is not None:
|
if evals_result is not None:
|
||||||
if not isinstance(evals_result, dict):
|
if not isinstance(evals_result, dict):
|
||||||
@ -65,6 +82,7 @@ def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
|||||||
if not early_stopping_rounds:
|
if not early_stopping_rounds:
|
||||||
for i in range(num_boost_round):
|
for i in range(num_boost_round):
|
||||||
bst.update(dtrain, i, obj)
|
bst.update(dtrain, i, obj)
|
||||||
|
ntrees += 1
|
||||||
if len(evals) != 0:
|
if len(evals) != 0:
|
||||||
bst_eval_set = bst.eval_set(evals, i, feval)
|
bst_eval_set = bst.eval_set(evals, i, feval)
|
||||||
if isinstance(bst_eval_set, STRING_TYPES):
|
if isinstance(bst_eval_set, STRING_TYPES):
|
||||||
@ -78,7 +96,7 @@ def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
|||||||
res = re.findall("([0-9a-zA-Z@]+[-]*):-?([0-9.]+).", msg)
|
res = re.findall("([0-9a-zA-Z@]+[-]*):-?([0-9.]+).", msg)
|
||||||
for key in evals_name:
|
for key in evals_name:
|
||||||
evals_idx = evals_name.index(key)
|
evals_idx = evals_name.index(key)
|
||||||
res_per_eval = len(res) / len(evals_name)
|
res_per_eval = len(res) // len(evals_name)
|
||||||
for r in range(res_per_eval):
|
for r in range(res_per_eval):
|
||||||
res_item = res[(evals_idx*res_per_eval) + r]
|
res_item = res[(evals_idx*res_per_eval) + r]
|
||||||
res_key = res_item[0]
|
res_key = res_item[0]
|
||||||
@ -87,6 +105,7 @@ def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
|||||||
evals_result[key][res_key].append(res_val)
|
evals_result[key][res_key].append(res_val)
|
||||||
else:
|
else:
|
||||||
evals_result[key][res_key] = [res_val]
|
evals_result[key][res_key] = [res_val]
|
||||||
|
bst.best_iteration = (ntrees - 1)
|
||||||
return bst
|
return bst
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -94,7 +113,8 @@ def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
|||||||
if len(evals) < 1:
|
if len(evals) < 1:
|
||||||
raise ValueError('For early stopping you need at least one set in evals.')
|
raise ValueError('For early stopping you need at least one set in evals.')
|
||||||
|
|
||||||
sys.stderr.write("Will train until {} error hasn't decreased in {} rounds.\n".format(\
|
if verbose_eval:
|
||||||
|
sys.stderr.write("Will train until {} error hasn't decreased in {} rounds.\n".format(\
|
||||||
evals[-1][1], early_stopping_rounds))
|
evals[-1][1], early_stopping_rounds))
|
||||||
|
|
||||||
# is params a list of tuples? are we using multiple eval metrics?
|
# is params a list of tuples? are we using multiple eval metrics?
|
||||||
@ -110,6 +130,8 @@ def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
|||||||
maximize_metrics = ('auc', 'map', 'ndcg')
|
maximize_metrics = ('auc', 'map', 'ndcg')
|
||||||
if any(params['eval_metric'].startswith(x) for x in maximize_metrics):
|
if any(params['eval_metric'].startswith(x) for x in maximize_metrics):
|
||||||
maximize_score = True
|
maximize_score = True
|
||||||
|
if feval is not None:
|
||||||
|
maximize_score = maximize
|
||||||
|
|
||||||
if maximize_score:
|
if maximize_score:
|
||||||
best_score = 0.0
|
best_score = 0.0
|
||||||
@ -117,10 +139,19 @@ def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
|||||||
best_score = float('inf')
|
best_score = float('inf')
|
||||||
|
|
||||||
best_msg = ''
|
best_msg = ''
|
||||||
best_score_i = 0
|
best_score_i = ntrees
|
||||||
|
|
||||||
|
if isinstance(learning_rates, list) and len(learning_rates) != num_boost_round:
|
||||||
|
raise ValueError("Length of list 'learning_rates' has to equal 'num_boost_round'.")
|
||||||
|
|
||||||
for i in range(num_boost_round):
|
for i in range(num_boost_round):
|
||||||
|
if learning_rates is not None:
|
||||||
|
if isinstance(learning_rates, list):
|
||||||
|
bst.set_param({'eta': learning_rates[i]})
|
||||||
|
else:
|
||||||
|
bst.set_param({'eta': learning_rates(i, num_boost_round)})
|
||||||
bst.update(dtrain, i, obj)
|
bst.update(dtrain, i, obj)
|
||||||
|
ntrees += 1
|
||||||
bst_eval_set = bst.eval_set(evals, i, feval)
|
bst_eval_set = bst.eval_set(evals, i, feval)
|
||||||
|
|
||||||
if isinstance(bst_eval_set, STRING_TYPES):
|
if isinstance(bst_eval_set, STRING_TYPES):
|
||||||
@ -135,7 +166,7 @@ def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
|||||||
res = re.findall("([0-9a-zA-Z@]+[-]*):-?([0-9.]+).", msg)
|
res = re.findall("([0-9a-zA-Z@]+[-]*):-?([0-9.]+).", msg)
|
||||||
for key in evals_name:
|
for key in evals_name:
|
||||||
evals_idx = evals_name.index(key)
|
evals_idx = evals_name.index(key)
|
||||||
res_per_eval = len(res) / len(evals_name)
|
res_per_eval = len(res) // len(evals_name)
|
||||||
for r in range(res_per_eval):
|
for r in range(res_per_eval):
|
||||||
res_item = res[(evals_idx*res_per_eval) + r]
|
res_item = res[(evals_idx*res_per_eval) + r]
|
||||||
res_key = res_item[0]
|
res_key = res_item[0]
|
||||||
@ -149,7 +180,7 @@ def train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None,
|
|||||||
if (maximize_score and score > best_score) or \
|
if (maximize_score and score > best_score) or \
|
||||||
(not maximize_score and score < best_score):
|
(not maximize_score and score < best_score):
|
||||||
best_score = score
|
best_score = score
|
||||||
best_score_i = i
|
best_score_i = (ntrees - 1)
|
||||||
best_msg = msg
|
best_msg = msg
|
||||||
elif i - best_score_i >= early_stopping_rounds:
|
elif i - best_score_i >= early_stopping_rounds:
|
||||||
sys.stderr.write("Stopping. Best iteration:\n{}\n\n".format(best_msg))
|
sys.stderr.write("Stopping. Best iteration:\n{}\n\n".format(best_msg))
|
||||||
|
|||||||
@ -64,7 +64,7 @@ if [ ${TASK} == "python-package" -o ${TASK} == "python-package3" ]; then
|
|||||||
conda create -n myenv python=2.7
|
conda create -n myenv python=2.7
|
||||||
fi
|
fi
|
||||||
source activate myenv
|
source activate myenv
|
||||||
conda install numpy scipy pandas matplotlib nose
|
conda install numpy scipy pandas matplotlib nose scikit-learn
|
||||||
python -m pip install graphviz
|
python -m pip install graphviz
|
||||||
|
|
||||||
make all CXX=${CXX} || exit -1
|
make all CXX=${CXX} || exit -1
|
||||||
|
|||||||
@ -138,10 +138,7 @@ class GBTree : public IGradBooster {
|
|||||||
{
|
{
|
||||||
nthread = omp_get_num_threads();
|
nthread = omp_get_num_threads();
|
||||||
}
|
}
|
||||||
thread_temp.resize(nthread, tree::RegTree::FVec());
|
InitThreadTemp(nthread);
|
||||||
for (int i = 0; i < nthread; ++i) {
|
|
||||||
thread_temp[i].Init(mparam.num_feature);
|
|
||||||
}
|
|
||||||
std::vector<float> &preds = *out_preds;
|
std::vector<float> &preds = *out_preds;
|
||||||
const size_t stride = info.num_row * mparam.num_output_group;
|
const size_t stride = info.num_row * mparam.num_output_group;
|
||||||
preds.resize(stride * (mparam.size_leaf_vector+1));
|
preds.resize(stride * (mparam.size_leaf_vector+1));
|
||||||
@ -194,10 +191,7 @@ class GBTree : public IGradBooster {
|
|||||||
{
|
{
|
||||||
nthread = omp_get_num_threads();
|
nthread = omp_get_num_threads();
|
||||||
}
|
}
|
||||||
thread_temp.resize(nthread, tree::RegTree::FVec());
|
InitThreadTemp(nthread);
|
||||||
for (int i = 0; i < nthread; ++i) {
|
|
||||||
thread_temp[i].Init(mparam.num_feature);
|
|
||||||
}
|
|
||||||
this->PredPath(p_fmat, info, out_preds, ntree_limit);
|
this->PredPath(p_fmat, info, out_preds, ntree_limit);
|
||||||
}
|
}
|
||||||
virtual std::vector<std::string> DumpModel(const utils::FeatMap& fmap, int option) {
|
virtual std::vector<std::string> DumpModel(const utils::FeatMap& fmap, int option) {
|
||||||
@ -391,6 +385,16 @@ class GBTree : public IGradBooster {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// init thread buffers
|
||||||
|
inline void InitThreadTemp(int nthread) {
|
||||||
|
int prev_thread_temp_size = thread_temp.size();
|
||||||
|
if (prev_thread_temp_size < nthread) {
|
||||||
|
thread_temp.resize(nthread, tree::RegTree::FVec());
|
||||||
|
for (int i = prev_thread_temp_size; i < nthread; ++i) {
|
||||||
|
thread_temp[i].Init(mparam.num_feature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- data structure ---
|
// --- data structure ---
|
||||||
/*! \brief training parameters */
|
/*! \brief training parameters */
|
||||||
|
|||||||
@ -72,7 +72,8 @@ struct TrainParam{
|
|||||||
opt_dense_col = 1.0f;
|
opt_dense_col = 1.0f;
|
||||||
nthread = 0;
|
nthread = 0;
|
||||||
size_leaf_vector = 0;
|
size_leaf_vector = 0;
|
||||||
parallel_option = 2;
|
// enforce parallel option to 0 for now, investigate the other strategy
|
||||||
|
parallel_option = 0;
|
||||||
sketch_eps = 0.1f;
|
sketch_eps = 0.1f;
|
||||||
sketch_ratio = 2.0f;
|
sketch_ratio = 2.0f;
|
||||||
cache_opt = 1;
|
cache_opt = 1;
|
||||||
|
|||||||
3
subtree/rabit/.gitignore
vendored
3
subtree/rabit/.gitignore
vendored
@ -34,3 +34,6 @@
|
|||||||
*tmp*
|
*tmp*
|
||||||
*.rabit
|
*.rabit
|
||||||
*.mock
|
*.mock
|
||||||
|
dmlc-core
|
||||||
|
recommonmark
|
||||||
|
recom
|
||||||
|
|||||||
51
subtree/rabit/.travis.yml
Normal file
51
subtree/rabit/.travis.yml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# disable sudo to use container based build
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
# Use Build Matrix to do lint and build seperately
|
||||||
|
env:
|
||||||
|
matrix:
|
||||||
|
- TASK=lint LINT_LANG=cpp
|
||||||
|
- TASK=lint LINT_LANG=python
|
||||||
|
- TASK=doc
|
||||||
|
- TASK=build CXX=g++
|
||||||
|
- TASK=test CXX=g++
|
||||||
|
|
||||||
|
# dependent apt packages
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- doxygen
|
||||||
|
- libopenmpi-dev
|
||||||
|
- wget
|
||||||
|
- git
|
||||||
|
- libcurl4-openssl-dev
|
||||||
|
- unzip
|
||||||
|
- python-numpy
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- git clone https://github.com/dmlc/dmlc-core
|
||||||
|
- export TRAVIS=dmlc-core/scripts/travis/
|
||||||
|
- source ${TRAVIS}/travis_setup_env.sh
|
||||||
|
|
||||||
|
install:
|
||||||
|
- pip install cpplint pylint --user `whoami`
|
||||||
|
|
||||||
|
script: scripts/travis_script.sh
|
||||||
|
|
||||||
|
|
||||||
|
before_cache:
|
||||||
|
- ${TRAVIS}/travis_before_cache.sh
|
||||||
|
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- ${HOME}/.cache/usr
|
||||||
|
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
# Emails are sent to the committer's git-configured email address by default,
|
||||||
|
email:
|
||||||
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
|
|
||||||
|
|
||||||
@ -3,8 +3,19 @@ export CXX = g++
|
|||||||
endif
|
endif
|
||||||
export MPICXX = mpicxx
|
export MPICXX = mpicxx
|
||||||
export LDFLAGS= -Llib -lrt
|
export LDFLAGS= -Llib -lrt
|
||||||
export WARNFLAGS= -Wall -Wextra -Wno-unused-parameter -Wno-unknown-pragmas -pedantic
|
export WARNFLAGS= -Wall -Wextra -Wno-unused-parameter -Wno-unknown-pragmas -std=c++0x
|
||||||
export CFLAGS = -O3 -msse2 -fPIC $(WARNFLAGS)
|
export CFLAGS = -O3 -msse2 $(WARNFLAGS)
|
||||||
|
|
||||||
|
ifndef WITH_FPIC
|
||||||
|
WITH_FPIC = 1
|
||||||
|
endif
|
||||||
|
ifeq ($(WITH_FPIC), 1)
|
||||||
|
CFLAGS += -fPIC
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef LINT_LANG
|
||||||
|
LINT_LANG="all"
|
||||||
|
endif
|
||||||
|
|
||||||
# build path
|
# build path
|
||||||
BPATH=.
|
BPATH=.
|
||||||
@ -15,7 +26,9 @@ OBJ= $(BPATH)/allreduce_base.o $(BPATH)/allreduce_robust.o $(BPATH)/engine.o $(B
|
|||||||
SLIB= wrapper/librabit_wrapper.so wrapper/librabit_wrapper_mock.so wrapper/librabit_wrapper_mpi.so
|
SLIB= wrapper/librabit_wrapper.so wrapper/librabit_wrapper_mock.so wrapper/librabit_wrapper_mpi.so
|
||||||
ALIB= lib/librabit.a lib/librabit_mpi.a lib/librabit_empty.a lib/librabit_mock.a lib/librabit_base.a
|
ALIB= lib/librabit.a lib/librabit_mpi.a lib/librabit_empty.a lib/librabit_mock.a lib/librabit_base.a
|
||||||
HEADERS=src/*.h include/*.h include/rabit/*.h
|
HEADERS=src/*.h include/*.h include/rabit/*.h
|
||||||
.PHONY: clean all install mpi python
|
DMLC=dmlc-core
|
||||||
|
|
||||||
|
.PHONY: clean all install mpi python lint doc doxygen
|
||||||
|
|
||||||
all: lib/librabit.a lib/librabit_mock.a wrapper/librabit_wrapper.so wrapper/librabit_wrapper_mock.so lib/librabit_base.a
|
all: lib/librabit.a lib/librabit_mock.a wrapper/librabit_wrapper.so wrapper/librabit_wrapper_mock.so lib/librabit_base.a
|
||||||
mpi: lib/librabit_mpi.a wrapper/librabit_wrapper_mpi.so
|
mpi: lib/librabit_mpi.a wrapper/librabit_wrapper_mpi.so
|
||||||
@ -52,6 +65,12 @@ $(ALIB):
|
|||||||
$(SLIB) :
|
$(SLIB) :
|
||||||
$(CXX) $(CFLAGS) -shared -o $@ $(filter %.cpp %.o %.c %.cc %.a, $^) $(LDFLAGS)
|
$(CXX) $(CFLAGS) -shared -o $@ $(filter %.cpp %.o %.c %.cc %.a, $^) $(LDFLAGS)
|
||||||
|
|
||||||
clean:
|
lint:
|
||||||
$(RM) $(OBJ) $(MPIOBJ) $(ALIB) $(MPIALIB) *~ src/*~ include/*~ include/*/*~ wrapper/*~
|
$(DMLC)/scripts/lint.py rabit $(LINT_LANG) src include wrapper
|
||||||
|
|
||||||
|
doc doxygen:
|
||||||
|
cd include; doxygen ../doc/Doxyfile; cd -
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(OBJ) $(MPIOBJ) $(ALIB) $(MPIALIB) $(SLIB) *~ src/*~ include/*~ include/*/*~ wrapper/*~
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
## rabit: Reliable Allreduce and Broadcast Interface
|
## rabit: Reliable Allreduce and Broadcast Interface
|
||||||
|
[](https://travis-ci.org/dmlc/rabit)
|
||||||
|
[](http://rabit.readthedocs.org/)
|
||||||
|
|
||||||
rabit is a light weight library that provides a fault tolerant interface of Allreduce and Broadcast. It is designed to support easy implementations of distributed machine learning programs, many of which fall naturally under the Allreduce abstraction. The goal of rabit is to support ***portable*** , ***scalable*** and ***reliable*** distributed machine learning programs.
|
rabit is a light weight library that provides a fault tolerant interface of Allreduce and Broadcast. It is designed to support easy implementations of distributed machine learning programs, many of which fall naturally under the Allreduce abstraction. The goal of rabit is to support ***portable*** , ***scalable*** and ***reliable*** distributed machine learning programs.
|
||||||
|
|
||||||
|
|||||||
2
subtree/rabit/doc/.gitignore
vendored
2
subtree/rabit/doc/.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
html
|
html
|
||||||
latex
|
latex
|
||||||
*.sh
|
*.sh
|
||||||
|
_*
|
||||||
|
doxygen
|
||||||
|
|||||||
@ -8,7 +8,7 @@ PROJECT_NAME = "rabit"
|
|||||||
PROJECT_NUMBER =
|
PROJECT_NUMBER =
|
||||||
PROJECT_BRIEF =
|
PROJECT_BRIEF =
|
||||||
PROJECT_LOGO =
|
PROJECT_LOGO =
|
||||||
OUTPUT_DIRECTORY = ../doc
|
OUTPUT_DIRECTORY = ../doc/doxygen
|
||||||
CREATE_SUBDIRS = NO
|
CREATE_SUBDIRS = NO
|
||||||
OUTPUT_LANGUAGE = English
|
OUTPUT_LANGUAGE = English
|
||||||
BRIEF_MEMBER_DESC = YES
|
BRIEF_MEMBER_DESC = YES
|
||||||
@ -216,7 +216,7 @@ MAN_LINKS = NO
|
|||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# configuration options related to the XML output
|
# configuration options related to the XML output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
GENERATE_XML = NO
|
GENERATE_XML = YES
|
||||||
XML_OUTPUT = xml
|
XML_OUTPUT = xml
|
||||||
XML_SCHEMA =
|
XML_SCHEMA =
|
||||||
XML_DTD =
|
XML_DTD =
|
||||||
|
|||||||
192
subtree/rabit/doc/Makefile
Normal file
192
subtree/rabit/doc/Makefile
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
# Makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line.
|
||||||
|
SPHINXOPTS =
|
||||||
|
SPHINXBUILD = sphinx-build
|
||||||
|
PAPER =
|
||||||
|
BUILDDIR = _build
|
||||||
|
|
||||||
|
# User-friendly check for sphinx-build
|
||||||
|
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||||
|
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Internal variables.
|
||||||
|
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||||
|
PAPEROPT_letter = -D latex_paper_size=letter
|
||||||
|
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||||
|
# the i18n builder cannot share the environment and doctrees with the others
|
||||||
|
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||||
|
|
||||||
|
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Please use \`make <target>' where <target> is one of"
|
||||||
|
@echo " html to make standalone HTML files"
|
||||||
|
@echo " dirhtml to make HTML files named index.html in directories"
|
||||||
|
@echo " singlehtml to make a single large HTML file"
|
||||||
|
@echo " pickle to make pickle files"
|
||||||
|
@echo " json to make JSON files"
|
||||||
|
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||||
|
@echo " qthelp to make HTML files and a qthelp project"
|
||||||
|
@echo " applehelp to make an Apple Help Book"
|
||||||
|
@echo " devhelp to make HTML files and a Devhelp project"
|
||||||
|
@echo " epub to make an epub"
|
||||||
|
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||||
|
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||||
|
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||||
|
@echo " text to make text files"
|
||||||
|
@echo " man to make manual pages"
|
||||||
|
@echo " texinfo to make Texinfo files"
|
||||||
|
@echo " info to make Texinfo files and run them through makeinfo"
|
||||||
|
@echo " gettext to make PO message catalogs"
|
||||||
|
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||||
|
@echo " xml to make Docutils-native XML files"
|
||||||
|
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||||
|
@echo " linkcheck to check all external links for integrity"
|
||||||
|
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||||
|
@echo " coverage to run coverage check of the documentation (if enabled)"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILDDIR)/*
|
||||||
|
|
||||||
|
html:
|
||||||
|
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||||
|
|
||||||
|
dirhtml:
|
||||||
|
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||||
|
|
||||||
|
singlehtml:
|
||||||
|
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||||
|
|
||||||
|
pickle:
|
||||||
|
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the pickle files."
|
||||||
|
|
||||||
|
json:
|
||||||
|
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the JSON files."
|
||||||
|
|
||||||
|
htmlhelp:
|
||||||
|
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||||
|
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||||
|
|
||||||
|
qthelp:
|
||||||
|
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||||
|
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||||
|
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/rabit.qhcp"
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/rabit.qhc"
|
||||||
|
|
||||||
|
applehelp:
|
||||||
|
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
|
||||||
|
@echo "N.B. You won't be able to view it unless you put it in" \
|
||||||
|
"~/Library/Documentation/Help or install it in your application" \
|
||||||
|
"bundle."
|
||||||
|
|
||||||
|
devhelp:
|
||||||
|
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished."
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# mkdir -p $$HOME/.local/share/devhelp/rabit"
|
||||||
|
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/rabit"
|
||||||
|
@echo "# devhelp"
|
||||||
|
|
||||||
|
epub:
|
||||||
|
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||||
|
|
||||||
|
latex:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||||
|
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||||
|
"(use \`make latexpdf' here to do that automatically)."
|
||||||
|
|
||||||
|
latexpdf:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo "Running LaTeX files through pdflatex..."
|
||||||
|
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||||
|
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
|
latexpdfja:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||||
|
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||||
|
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
|
text:
|
||||||
|
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||||
|
|
||||||
|
man:
|
||||||
|
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||||
|
|
||||||
|
texinfo:
|
||||||
|
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||||
|
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||||
|
"(use \`make info' here to do that automatically)."
|
||||||
|
|
||||||
|
info:
|
||||||
|
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||||
|
@echo "Running Texinfo files through makeinfo..."
|
||||||
|
make -C $(BUILDDIR)/texinfo info
|
||||||
|
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||||
|
|
||||||
|
gettext:
|
||||||
|
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||||
|
|
||||||
|
changes:
|
||||||
|
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||||
|
@echo
|
||||||
|
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||||
|
|
||||||
|
linkcheck:
|
||||||
|
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||||
|
@echo
|
||||||
|
@echo "Link check complete; look for any errors in the above output " \
|
||||||
|
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||||
|
|
||||||
|
doctest:
|
||||||
|
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||||
|
@echo "Testing of doctests in the sources finished, look at the " \
|
||||||
|
"results in $(BUILDDIR)/doctest/output.txt."
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
|
||||||
|
@echo "Testing of coverage in the sources finished, look at the " \
|
||||||
|
"results in $(BUILDDIR)/coverage/python.txt."
|
||||||
|
|
||||||
|
xml:
|
||||||
|
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||||
|
|
||||||
|
pseudoxml:
|
||||||
|
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
||||||
184
subtree/rabit/doc/conf.py
Normal file
184
subtree/rabit/doc/conf.py
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# documentation build configuration file, created by
|
||||||
|
# sphinx-quickstart on Thu Jul 23 19:40:08 2015.
|
||||||
|
#
|
||||||
|
# This file is execfile()d with the current directory set to its
|
||||||
|
# containing dir.
|
||||||
|
#
|
||||||
|
# Note that not all possible configuration values are present in this
|
||||||
|
# autogenerated file.
|
||||||
|
#
|
||||||
|
# All configuration values have a default; values that are commented out
|
||||||
|
# serve to show the default.
|
||||||
|
import sys
|
||||||
|
import os, subprocess
|
||||||
|
import shlex
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
|
||||||
|
libpath = os.path.join(curr_path, '../wrapper/')
|
||||||
|
sys.path.insert(0, os.path.join(curr_path, '../wrapper/'))
|
||||||
|
sys.path.insert(0, curr_path)
|
||||||
|
from sphinx_util import MarkdownParser, AutoStructify
|
||||||
|
|
||||||
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = u'rabit'
|
||||||
|
copyright = u'2015, rabit developers'
|
||||||
|
author = u'rabit developers'
|
||||||
|
github_doc_root = 'https://github.com/dmlc/rabit/tree/master/doc/'
|
||||||
|
|
||||||
|
# add markdown parser
|
||||||
|
MarkdownParser.github_doc_root = github_doc_root
|
||||||
|
source_parsers = {
|
||||||
|
'.md': MarkdownParser,
|
||||||
|
}
|
||||||
|
# Version information.
|
||||||
|
import rabit
|
||||||
|
|
||||||
|
version = rabit.__version__
|
||||||
|
release = rabit.__version__
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.autodoc',
|
||||||
|
'sphinx.ext.napoleon',
|
||||||
|
'sphinx.ext.mathjax',
|
||||||
|
'breathe',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Use breathe to include doxygen documents
|
||||||
|
breathe_projects = {'rabit' : 'doxygen/xml/'}
|
||||||
|
breathe_default_project = 'rabit'
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The suffix(es) of source filenames.
|
||||||
|
# You can specify multiple suffix as a list of string:
|
||||||
|
# source_suffix = ['.rst', '.md']
|
||||||
|
source_suffix = ['.rst', '.md']
|
||||||
|
|
||||||
|
# The encoding of source files.
|
||||||
|
#source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#
|
||||||
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
|
# Usually you set "language" from the command line for these cases.
|
||||||
|
language = None
|
||||||
|
|
||||||
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
|
# non-false value, then it is used:
|
||||||
|
#today = ''
|
||||||
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
|
#today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
exclude_patterns = ['_build']
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
|
# documents.
|
||||||
|
#default_role = None
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
#add_function_parentheses = True
|
||||||
|
|
||||||
|
# If true, the current module name will be prepended to all description
|
||||||
|
# unit titles (such as .. function::).
|
||||||
|
#add_module_names = True
|
||||||
|
|
||||||
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
|
# output. They are ignored by default.
|
||||||
|
#show_authors = False
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
|
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||||
|
#keep_warnings = False
|
||||||
|
|
||||||
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
|
todo_include_todos = False
|
||||||
|
|
||||||
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
# html_theme = 'alabaster'
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = project + 'doc'
|
||||||
|
|
||||||
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
|
latex_elements = {
|
||||||
|
}
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title,
|
||||||
|
# author, documentclass [howto, manual, or own class]).
|
||||||
|
latex_documents = [
|
||||||
|
(master_doc, 'rabit.tex', project,
|
||||||
|
author, 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# hook for doxygen
|
||||||
|
def run_doxygen(folder):
|
||||||
|
"""Run the doxygen make command in the designated folder."""
|
||||||
|
try:
|
||||||
|
retcode = subprocess.call("cd %s; make doxygen" % folder, shell=True)
|
||||||
|
if retcode < 0:
|
||||||
|
sys.stderr.write("doxygen terminated by signal %s" % (-retcode))
|
||||||
|
except OSError as e:
|
||||||
|
sys.stderr.write("doxygen execution failed: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
def run_build_lib(folder):
|
||||||
|
"""Run the doxygen make command in the designated folder."""
|
||||||
|
try:
|
||||||
|
retcode = subprocess.call("cd %s; make" % folder, shell=True)
|
||||||
|
retcode = subprocess.call("rm -rf _build/html/doxygen", shell=True)
|
||||||
|
retcode = subprocess.call("mkdir _build", shell=True)
|
||||||
|
retcode = subprocess.call("mkdir _build/html", shell=True)
|
||||||
|
retcode = subprocess.call("cp -rf doxygen/html _build/html/doxygen", shell=True)
|
||||||
|
if retcode < 0:
|
||||||
|
sys.stderr.write("build terminated by signal %s" % (-retcode))
|
||||||
|
except OSError as e:
|
||||||
|
sys.stderr.write("build execution failed: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_doxygen_xml(app):
|
||||||
|
"""Run the doxygen make commands if we're on the ReadTheDocs server"""
|
||||||
|
read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True'
|
||||||
|
if read_the_docs_build:
|
||||||
|
run_doxygen('..')
|
||||||
|
sys.stderr.write('Check if shared lib exists\n')
|
||||||
|
run_build_lib('..')
|
||||||
|
sys.stderr.write('The wrapper path: %s\n' % str(os.listdir('../wrapper')))
|
||||||
|
rabit._loadlib()
|
||||||
|
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
# Add hook for building doxygen xml when needed
|
||||||
|
app.connect("builder-inited", generate_doxygen_xml)
|
||||||
|
app.add_config_value('recommonmark_config', {
|
||||||
|
'url_resolver': lambda url: github_doc_root + url,
|
||||||
|
}, True)
|
||||||
|
app.add_transform(AutoStructify)
|
||||||
9
subtree/rabit/doc/cpp_api.md
Normal file
9
subtree/rabit/doc/cpp_api.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
C++ Library API of Rabit
|
||||||
|
========================
|
||||||
|
This page contains document of Library API of rabit.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
.. toctree::
|
||||||
|
|
||||||
|
.. doxygennamespace:: rabit
|
||||||
|
```
|
||||||
@ -1,10 +1,9 @@
|
|||||||
Tutorial
|
Tutorial
|
||||||
=====
|
========
|
||||||
This is rabit's tutorial, a ***Reliable Allreduce and Broadcast Interface***.
|
This is rabit's tutorial, a ***Reliable Allreduce and Broadcast Interface***.
|
||||||
|
All the example codes are in the [guide](https://github.com/dmlc/rabit/blob/master/guide/) folder of the project.
|
||||||
To run the examples locally, you will need to build them with ```make```.
|
To run the examples locally, you will need to build them with ```make```.
|
||||||
|
|
||||||
Please also refer to the [API Documentation](http://homes.cs.washington.edu/~tqchen/rabit/doc) for further details.
|
|
||||||
|
|
||||||
**List of Topics**
|
**List of Topics**
|
||||||
* [What is Allreduce](#what-is-allreduce)
|
* [What is Allreduce](#what-is-allreduce)
|
||||||
* [Common Use Case](#common-use-case)
|
* [Common Use Case](#common-use-case)
|
||||||
@ -20,9 +19,9 @@ Please also refer to the [API Documentation](http://homes.cs.washington.edu/~tqc
|
|||||||
* [Fault Tolerance](#fault-tolerance)
|
* [Fault Tolerance](#fault-tolerance)
|
||||||
|
|
||||||
What is Allreduce
|
What is Allreduce
|
||||||
=====
|
-----------------
|
||||||
The main methods provided by rabit are Allreduce and Broadcast. Allreduce performs reduction across different computation nodes,
|
The main methods provided by rabit are Allreduce and Broadcast. Allreduce performs reduction across different computation nodes,
|
||||||
and returns the result to every node. To understand the behavior of the function, consider the following example in [basic.cc](basic.cc) (there is a python example right after this if you are more familiar with python).
|
and returns the result to every node. To understand the behavior of the function, consider the following example in [basic.cc](../guide/basic.cc) (there is a python example right after this if you are more familiar with python).
|
||||||
```c++
|
```c++
|
||||||
#include <rabit.h>
|
#include <rabit.h>
|
||||||
using namespace rabit;
|
using namespace rabit;
|
||||||
@ -63,7 +62,7 @@ Rabit provides different reduction operators, for example, if you change ```op:
|
|||||||
the reduction operation will be a summation, and the result will become ```a = {1, 3, 5}```.
|
the reduction operation will be a summation, and the result will become ```a = {1, 3, 5}```.
|
||||||
You can also run the example with different processes by setting -n to different values.
|
You can also run the example with different processes by setting -n to different values.
|
||||||
|
|
||||||
If you are more familiar with python, you can also use rabit in python. The same example as before can be found in [basic.py](basic.py):
|
If you are more familiar with python, you can also use rabit in python. The same example as before can be found in [basic.py](../guide/basic.py):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -89,7 +88,7 @@ You can run the program using the following command
|
|||||||
```
|
```
|
||||||
|
|
||||||
Broadcast is another method provided by rabit besides Allreduce. This function allows one node to broadcast its
|
Broadcast is another method provided by rabit besides Allreduce. This function allows one node to broadcast its
|
||||||
local data to all other nodes. The following code in [broadcast.cc](broadcast.cc) broadcasts a string from
|
local data to all other nodes. The following code in [broadcast.cc](../guide/broadcast.cc) broadcasts a string from
|
||||||
node 0 to all other nodes.
|
node 0 to all other nodes.
|
||||||
```c++
|
```c++
|
||||||
#include <rabit.h>
|
#include <rabit.h>
|
||||||
@ -115,7 +114,7 @@ The following command starts the program with three worker processes.
|
|||||||
```
|
```
|
||||||
Besides strings, rabit also allows to broadcast constant size array and vectors.
|
Besides strings, rabit also allows to broadcast constant size array and vectors.
|
||||||
|
|
||||||
The counterpart in python can be found in [broadcast.py](broadcast.py). Here is a snippet so that you can get a better sense of how simple is to use the python library:
|
The counterpart in python can be found in [broadcast.py](../guide/broadcast.py). Here is a snippet so that you can get a better sense of how simple is to use the python library:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import rabit
|
import rabit
|
||||||
@ -132,7 +131,7 @@ rabit.finalize()
|
|||||||
```
|
```
|
||||||
|
|
||||||
Common Use Case
|
Common Use Case
|
||||||
=====
|
---------------
|
||||||
Many distributed machine learning algorithms involve splitting the data into different nodes,
|
Many distributed machine learning algorithms involve splitting the data into different nodes,
|
||||||
computing statistics locally, and finally aggregating them. Such workflow is usually done repetitively through many iterations before the algorithm converges. Allreduce naturally meets the structure of such programs,
|
computing statistics locally, and finally aggregating them. Such workflow is usually done repetitively through many iterations before the algorithm converges. Allreduce naturally meets the structure of such programs,
|
||||||
common use cases include:
|
common use cases include:
|
||||||
@ -144,7 +143,7 @@ common use cases include:
|
|||||||
Rabit is a reliable and portable library for distributed machine learning programs, that allow programs to run reliably on different platforms.
|
Rabit is a reliable and portable library for distributed machine learning programs, that allow programs to run reliably on different platforms.
|
||||||
|
|
||||||
Use Rabit API
|
Use Rabit API
|
||||||
====
|
-------------
|
||||||
This section introduces topics about how to use rabit API.
|
This section introduces topics about how to use rabit API.
|
||||||
You can always refer to [API Documentation](http://homes.cs.washington.edu/~tqchen/rabit/doc) for definition of each functions.
|
You can always refer to [API Documentation](http://homes.cs.washington.edu/~tqchen/rabit/doc) for definition of each functions.
|
||||||
This section trys to gives examples of different aspectes of rabit API.
|
This section trys to gives examples of different aspectes of rabit API.
|
||||||
@ -202,8 +201,8 @@ into the data buffer, pass the data to Allreduce function, and get the reduced r
|
|||||||
from failure, we can directly recover the result from other nodes(see also [Fault Tolerance](#fault-tolerance)) and
|
from failure, we can directly recover the result from other nodes(see also [Fault Tolerance](#fault-tolerance)) and
|
||||||
the data preparation procedure no longer necessary. Rabit Allreduce add an optional parameter preparation function
|
the data preparation procedure no longer necessary. Rabit Allreduce add an optional parameter preparation function
|
||||||
to support such scenario. User can pass in a function that corresponds to the data preparation procedure to Allreduce
|
to support such scenario. User can pass in a function that corresponds to the data preparation procedure to Allreduce
|
||||||
calls, and the data preparation function will only be called when necessary. We use [lazy_allreduce.cc](lazy_allreduce.cc)
|
calls, and the data preparation function will only be called when necessary. We use [lazy_allreduce.cc](../guide/lazy_allreduce.cc)
|
||||||
as an example to demonstrate this feature. It is modified from [basic.cc](basic.cc), and you can compare the two codes.
|
as an example to demonstrate this feature. It is modified from [basic.cc](../guide/basic.cc), and you can compare the two codes.
|
||||||
```c++
|
```c++
|
||||||
#include <rabit.h>
|
#include <rabit.h>
|
||||||
using namespace rabit;
|
using namespace rabit;
|
||||||
@ -242,7 +241,7 @@ the effect when a process goes down. You can run the program using the following
|
|||||||
The additional arguments ```mock=0,0,1,0``` will cause node 0 to kill itself before second call of Allreduce (see also [mock test](#link-against-mock-test-rabit-library)).
|
The additional arguments ```mock=0,0,1,0``` will cause node 0 to kill itself before second call of Allreduce (see also [mock test](#link-against-mock-test-rabit-library)).
|
||||||
You will find that the prepare function's print is only executed once and node 0 will no longer execute the preparation function when it restarts from failure.
|
You will find that the prepare function's print is only executed once and node 0 will no longer execute the preparation function when it restarts from failure.
|
||||||
|
|
||||||
You can also find python version of the example in [lazy_allreduce.py](lazy_allreduce.py), and run it using the followin command
|
You can also find python version of the example in [lazy_allreduce.py](../guide/lazy_allreduce.py), and run it using the followin command
|
||||||
```bash
|
```bash
|
||||||
../tracker/rabit_demo.py -n 2 lazy_allreduce.py mock=0,0,1,0
|
../tracker/rabit_demo.py -n 2 lazy_allreduce.py mock=0,0,1,0
|
||||||
|
|
||||||
@ -250,7 +249,7 @@ You can also find python version of the example in [lazy_allreduce.py](lazy_allr
|
|||||||
|
|
||||||
Since lazy preparation function may not be called during execution. User should be careful when using this feature. For example, a possible mistake
|
Since lazy preparation function may not be called during execution. User should be careful when using this feature. For example, a possible mistake
|
||||||
could be putting some memory allocation code in the lazy preparation function, and the computing memory was not allocated when lazy preparation function is not called.
|
could be putting some memory allocation code in the lazy preparation function, and the computing memory was not allocated when lazy preparation function is not called.
|
||||||
The example in [lazy_allreduce.cc](lazy_allreduce.cc) provides a simple way to migrate normal prepration code([basic.cc](basic.cc)) to lazy version: wrap the preparation
|
The example in [lazy_allreduce.cc](../guide/lazy_allreduce.cc) provides a simple way to migrate normal prepration code([basic.cc](../guide/basic.cc)) to lazy version: wrap the preparation
|
||||||
code with a lambda function, and pass it to allreduce.
|
code with a lambda function, and pass it to allreduce.
|
||||||
|
|
||||||
#### Checkpoint and LazyCheckpoint
|
#### Checkpoint and LazyCheckpoint
|
||||||
@ -287,7 +286,7 @@ improve the efficiency of the program.
|
|||||||
|
|
||||||
|
|
||||||
Compile Programs with Rabit
|
Compile Programs with Rabit
|
||||||
====
|
---------------------------
|
||||||
Rabit is a portable library, to use it, you only need to include the rabit header file.
|
Rabit is a portable library, to use it, you only need to include the rabit header file.
|
||||||
* You will need to add the path to [../include](../include) to the header search path of the compiler
|
* You will need to add the path to [../include](../include) to the header search path of the compiler
|
||||||
- Solution 1: add ```-I/path/to/rabit/include``` to the compiler flag in gcc or clang
|
- Solution 1: add ```-I/path/to/rabit/include``` to the compiler flag in gcc or clang
|
||||||
@ -333,27 +332,27 @@ For example, consider the following script in the test case
|
|||||||
- Note that ndeath = 1 means this will happen only if node 1 died once, which is our case
|
- Note that ndeath = 1 means this will happen only if node 1 died once, which is our case
|
||||||
|
|
||||||
Running Rabit Jobs
|
Running Rabit Jobs
|
||||||
====
|
------------------
|
||||||
Rabit is a portable library that can run on multiple platforms.
|
Rabit is a portable library that can run on multiple platforms.
|
||||||
|
|
||||||
#### Running Rabit Locally
|
#### Running Rabit Locally
|
||||||
* You can use [../tracker/rabit_demo.py](../tracker/rabit_demo.py) to start n processes locally
|
* You can use [../tracker/rabit_demo.py](https://github.com/dmlc/rabit/blob/master/tracker/rabit_demo.py) to start n processes locally
|
||||||
* This script will restart the program when it exits with -2, so it can be used for [mock test](#link-against-mock-test-library)
|
* This script will restart the program when it exits with -2, so it can be used for [mock test](#link-against-mock-test-library)
|
||||||
|
|
||||||
#### Running Rabit on Hadoop
|
#### Running Rabit on Hadoop
|
||||||
* You can use [../tracker/rabit_yarn.py](../tracker/rabit_yarn.py) to run rabit programs as Yarn application
|
* You can use [../tracker/rabit_yarn.py](https://github.com/dmlc/rabit/blob/master/tracker/rabit_yarn.py) to run rabit programs as Yarn application
|
||||||
* This will start rabit programs as yarn applications
|
* This will start rabit programs as yarn applications
|
||||||
- This allows multi-threading programs in each node, which can be more efficient
|
- This allows multi-threading programs in each node, which can be more efficient
|
||||||
- An easy multi-threading solution could be to use OpenMP with rabit code
|
- An easy multi-threading solution could be to use OpenMP with rabit code
|
||||||
* It is also possible to run rabit program via hadoop streaming, however, YARN is highly recommended.
|
* It is also possible to run rabit program via hadoop streaming, however, YARN is highly recommended.
|
||||||
|
|
||||||
#### Running Rabit using MPI
|
#### Running Rabit using MPI
|
||||||
* You can submit rabit programs to an MPI cluster using [../tracker/rabit_mpi.py](../tracker/rabit_mpi.py).
|
* You can submit rabit programs to an MPI cluster using [../tracker/rabit_mpi.py](https://github.com/dmlc/rabit/blob/master/tracker/rabit_mpi.py).
|
||||||
* If you linked your code against librabit_mpi.a, then you can directly use mpirun to submit the job
|
* If you linked your code against librabit_mpi.a, then you can directly use mpirun to submit the job
|
||||||
|
|
||||||
#### Customize Tracker Script
|
#### Customize Tracker Script
|
||||||
You can also modify the tracker script to allow rabit to run on other platforms. To do so, refer to existing
|
You can also modify the tracker script to allow rabit to run on other platforms. To do so, refer to existing
|
||||||
tracker scripts, such as [../tracker/rabit_hadoop.py](../tracker/rabit_hadoop.py) and [../tracker/rabit_mpi.py](../tracker/rabit_mpi.py) to get a sense of how it is done.
|
tracker scripts, such as [../tracker/rabit_yarn.py](../tracker/rabit_yarn.py) and [../tracker/rabit_mpi.py](https://github.com/dmlc/rabit/blob/master/tracker/rabit_mpi.py) to get a sense of how it is done.
|
||||||
|
|
||||||
You will need to implement a platform dependent submission function with the following definition
|
You will need to implement a platform dependent submission function with the following definition
|
||||||
```python
|
```python
|
||||||
@ -376,7 +375,7 @@ Note that the current rabit tracker does not restart a worker when it dies, the
|
|||||||
- rabit-yarn provides such functionality in YARN
|
- rabit-yarn provides such functionality in YARN
|
||||||
|
|
||||||
Fault Tolerance
|
Fault Tolerance
|
||||||
=====
|
---------------
|
||||||
This section introduces how fault tolerance works in rabit.
|
This section introduces how fault tolerance works in rabit.
|
||||||
The following figure shows how rabit deals with failures.
|
The following figure shows how rabit deals with failures.
|
||||||
|
|
||||||
24
subtree/rabit/doc/index.md
Normal file
24
subtree/rabit/doc/index.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
Rabit Documentation
|
||||||
|
=====================
|
||||||
|
rabit is a light weight library that provides a fault tolerant interface of Allreduce and Broadcast. It is designed to support easy implementations of distributed machine learning programs, many of which fall naturally under the Allreduce abstraction. The goal of rabit is to support **portable** , **scalable** and **reliable** distributed machine learning programs.
|
||||||
|
|
||||||
|
API Documents
|
||||||
|
-------------
|
||||||
|
```eval_rst
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
python_api.md
|
||||||
|
cpp_api.md
|
||||||
|
parameters.md
|
||||||
|
guide.md
|
||||||
|
```
|
||||||
|
Indices and tables
|
||||||
|
------------------
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`modindex`
|
||||||
|
* :ref:`search`
|
||||||
|
```
|
||||||
@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
cd ../include
|
|
||||||
doxygen ../doc/Doxyfile
|
|
||||||
cd ../doc
|
|
||||||
@ -1,14 +1,7 @@
|
|||||||
Rabit Documentation
|
|
||||||
====
|
|
||||||
* [Tutorial](../guide)
|
|
||||||
* [API Documentation](http://homes.cs.washington.edu/~tqchen/rabit/doc)
|
|
||||||
- You can also run ```./mkdoc.sh``` to make the document locally
|
|
||||||
* [Parameters](#parameters)
|
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
====
|
==========
|
||||||
This section list all the parameters that can be passed to rabit::Init function as argv.
|
This section list all the parameters that can be passed to rabit::Init function as argv.
|
||||||
All the parameters are passed in as string in format of ```parameter-name=parameter-value```.
|
All the parameters are passed in as string in format of ``parameter-name=parameter-value``.
|
||||||
In most setting these parameters have default value or will be automatically detected,
|
In most setting these parameters have default value or will be automatically detected,
|
||||||
and do not need to be manually configured.
|
and do not need to be manually configured.
|
||||||
|
|
||||||
4
subtree/rabit/doc/python-requirements.txt
Normal file
4
subtree/rabit/doc/python-requirements.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
numpy
|
||||||
|
breathe
|
||||||
|
commonmark
|
||||||
|
|
||||||
11
subtree/rabit/doc/python_api.md
Normal file
11
subtree/rabit/doc/python_api.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Python API of Rabit
|
||||||
|
===================
|
||||||
|
This page contains document of python API of rabit.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
|
.. toctree::
|
||||||
|
|
||||||
|
.. automodule:: rabit
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
||||||
|
```
|
||||||
16
subtree/rabit/doc/sphinx_util.py
Normal file
16
subtree/rabit/doc/sphinx_util.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Helper utilty function for customization."""
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import docutils
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
if os.environ.get('READTHEDOCS', None) == 'True':
|
||||||
|
subprocess.call('cd ..; rm -rf recommonmark;' +
|
||||||
|
'git clone https://github.com/tqchen/recommonmark', shell=True)
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.abspath('../recommonmark/'))
|
||||||
|
from recommonmark import parser, transform
|
||||||
|
|
||||||
|
MarkdownParser = parser.CommonMarkParser
|
||||||
|
AutoStructify = transform.AutoStructify
|
||||||
1
subtree/rabit/guide/README
Normal file
1
subtree/rabit/guide/README
Normal file
@ -0,0 +1 @@
|
|||||||
|
See tutorial at ../doc/guide.md
|
||||||
@ -5,11 +5,17 @@
|
|||||||
*
|
*
|
||||||
* \author Tianqi Chen
|
* \author Tianqi Chen
|
||||||
*/
|
*/
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#define _CRT_SECURE_NO_DEPRECATE
|
||||||
|
#include <vector>
|
||||||
#include <rabit.h>
|
#include <rabit.h>
|
||||||
using namespace rabit;
|
using namespace rabit;
|
||||||
const int N = 3;
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int a[N];
|
int N = 3;
|
||||||
|
if (argc > 1) {
|
||||||
|
N = atoi(argv[1]);
|
||||||
|
}
|
||||||
|
std::vector<int> a(N);
|
||||||
rabit::Init(argc, argv);
|
rabit::Init(argc, argv);
|
||||||
for (int i = 0; i < N; ++i) {
|
for (int i = 0; i < N; ++i) {
|
||||||
a[i] = rabit::GetRank() + i;
|
a[i] = rabit::GetRank() + i;
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
// include uint64_t only to make io standalone
|
// include uint64_t only to make io standalone
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
/*! \brief uint64 */
|
||||||
typedef unsigned __int64 uint64_t;
|
typedef unsigned __int64 uint64_t;
|
||||||
#else
|
#else
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@ -24,7 +25,7 @@ namespace dmlc {
|
|||||||
/*!
|
/*!
|
||||||
* \brief interface of stream I/O for serialization
|
* \brief interface of stream I/O for serialization
|
||||||
*/
|
*/
|
||||||
class Stream {
|
class Stream { // NOLINT(*)
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
* \brief reads data from a stream
|
* \brief reads data from a stream
|
||||||
@ -192,9 +193,10 @@ class InputSplit {
|
|||||||
* List of possible types: "text", "recordio"
|
* List of possible types: "text", "recordio"
|
||||||
* - "text":
|
* - "text":
|
||||||
* text file, each line is treated as a record
|
* text file, each line is treated as a record
|
||||||
* input split will split on \n or \r
|
* input split will split on '\\n' or '\\r'
|
||||||
* - "recordio":
|
* - "recordio":
|
||||||
* binary recordio file, see recordio.h
|
* binary recordio file, see recordio.h
|
||||||
|
* \return a new input split
|
||||||
* \sa InputSplit::Type
|
* \sa InputSplit::Type
|
||||||
*/
|
*/
|
||||||
static InputSplit* Create(const char *uri,
|
static InputSplit* Create(const char *uri,
|
||||||
@ -224,7 +226,7 @@ class ostream : public std::basic_ostream<char> {
|
|||||||
* \param buffer_size internal streambuf size
|
* \param buffer_size internal streambuf size
|
||||||
*/
|
*/
|
||||||
explicit ostream(Stream *stream,
|
explicit ostream(Stream *stream,
|
||||||
size_t buffer_size = 1 << 10)
|
size_t buffer_size = (1 << 10))
|
||||||
: std::basic_ostream<char>(NULL), buf_(buffer_size) {
|
: std::basic_ostream<char>(NULL), buf_(buffer_size) {
|
||||||
this->set_stream(stream);
|
this->set_stream(stream);
|
||||||
}
|
}
|
||||||
@ -287,7 +289,7 @@ class istream : public std::basic_istream<char> {
|
|||||||
* \param buffer_size internal buffer size
|
* \param buffer_size internal buffer size
|
||||||
*/
|
*/
|
||||||
explicit istream(Stream *stream,
|
explicit istream(Stream *stream,
|
||||||
size_t buffer_size = 1 << 10)
|
size_t buffer_size = (1 << 10))
|
||||||
: std::basic_istream<char>(NULL), buf_(buffer_size) {
|
: std::basic_istream<char>(NULL), buf_(buffer_size) {
|
||||||
this->set_stream(stream);
|
this->set_stream(stream);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,12 +8,18 @@
|
|||||||
* rabit.h and serializable.h is all what the user needs to use the rabit interface
|
* rabit.h and serializable.h is all what the user needs to use the rabit interface
|
||||||
* \author Tianqi Chen, Ignacio Cano, Tianyi Zhou
|
* \author Tianqi Chen, Ignacio Cano, Tianyi Zhou
|
||||||
*/
|
*/
|
||||||
#ifndef RABIT_RABIT_H_
|
#ifndef RABIT_RABIT_H_ // NOLINT(*)
|
||||||
#define RABIT_RABIT_H_
|
#define RABIT_RABIT_H_ // NOLINT(*)
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
// whether or not use c++11 support
|
||||||
|
#ifndef DMLC_USE_CXX11
|
||||||
|
#define DMLC_USE_CXX11 (defined(__GXX_EXPERIMENTAL_CXX0X__) ||\
|
||||||
|
__cplusplus >= 201103L || defined(_MSC_VER))
|
||||||
|
#endif
|
||||||
// optionally support of lambda functions in C++11, if available
|
// optionally support of lambda functions in C++11, if available
|
||||||
#if __cplusplus >= 201103L
|
#if DMLC_USE_CXX11
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#endif // C++11
|
#endif // C++11
|
||||||
// contains definition of Serializable
|
// contains definition of Serializable
|
||||||
@ -117,10 +123,13 @@ inline void Broadcast(std::string *sendrecv_data, int root);
|
|||||||
* this function is NOT thread-safe
|
* this function is NOT thread-safe
|
||||||
*
|
*
|
||||||
* Example Usage: the following code does an Allreduce and outputs the sum as the result
|
* Example Usage: the following code does an Allreduce and outputs the sum as the result
|
||||||
* vector<int> data(10);
|
* \code{.cpp}
|
||||||
* ...
|
* vector<int> data(10);
|
||||||
* Allreduce<op::Sum>(&data[0], data.size());
|
* ...
|
||||||
* ...
|
* Allreduce<op::Sum>(&data[0], data.size());
|
||||||
|
* ...
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
* \param sendrecvbuf buffer for both sending and receiving data
|
* \param sendrecvbuf buffer for both sending and receiving data
|
||||||
* \param count number of elements to be reduced
|
* \param count number of elements to be reduced
|
||||||
* \param prepare_fun Lazy preprocessing function, if it is not NULL, prepare_fun(prepare_arg)
|
* \param prepare_fun Lazy preprocessing function, if it is not NULL, prepare_fun(prepare_arg)
|
||||||
@ -132,23 +141,26 @@ inline void Broadcast(std::string *sendrecv_data, int root);
|
|||||||
*/
|
*/
|
||||||
template<typename OP, typename DType>
|
template<typename OP, typename DType>
|
||||||
inline void Allreduce(DType *sendrecvbuf, size_t count,
|
inline void Allreduce(DType *sendrecvbuf, size_t count,
|
||||||
void (*prepare_fun)(void *arg) = NULL,
|
void (*prepare_fun)(void *) = NULL,
|
||||||
void *prepare_arg = NULL);
|
void *prepare_arg = NULL);
|
||||||
// C++11 support for lambda prepare function
|
// C++11 support for lambda prepare function
|
||||||
#if __cplusplus >= 201103L
|
#if DMLC_USE_CXX11
|
||||||
/*!
|
/*!
|
||||||
* \brief performs in-place Allreduce, on sendrecvbuf
|
* \brief performs in-place Allreduce, on sendrecvbuf
|
||||||
* with a prepare function specified by a lambda function
|
* with a prepare function specified by a lambda function
|
||||||
*
|
*
|
||||||
* Example Usage: the following code does an Allreduce and outputs the sum as the result
|
* Example Usage:
|
||||||
* vector<int> data(10);
|
* \code{.cpp}
|
||||||
* ...
|
* // the following code does an Allreduce and outputs the sum as the result
|
||||||
* Allreduce<op::Sum>(&data[0], data.size(), [&]() {
|
* vector<int> data(10);
|
||||||
* for (int i = 0; i < 10; ++i) {
|
* ...
|
||||||
* data[i] = i;
|
* Allreduce<op::Sum>(&data[0], data.size(), [&]() {
|
||||||
* }
|
* for (int i = 0; i < 10; ++i) {
|
||||||
* });
|
* data[i] = i;
|
||||||
|
* }
|
||||||
|
* });
|
||||||
* ...
|
* ...
|
||||||
|
* \endcode
|
||||||
* \param sendrecvbuf buffer for both sending and receiving data
|
* \param sendrecvbuf buffer for both sending and receiving data
|
||||||
* \param count number of elements to be reduced
|
* \param count number of elements to be reduced
|
||||||
* \param prepare_fun Lazy lambda preprocessing function, prepare_fun() will be invoked
|
* \param prepare_fun Lazy lambda preprocessing function, prepare_fun() will be invoked
|
||||||
@ -173,14 +185,15 @@ inline void Allreduce(DType *sendrecvbuf, size_t count,
|
|||||||
* if returned version == 0, this means no model has been CheckPointed
|
* if returned version == 0, this means no model has been CheckPointed
|
||||||
* the p_model is not touched, users should do the necessary initialization by themselves
|
* the p_model is not touched, users should do the necessary initialization by themselves
|
||||||
*
|
*
|
||||||
* Common usage example:
|
* \code{.cpp}
|
||||||
* int iter = rabit::LoadCheckPoint(&model);
|
* // Example usage code of LoadCheckPoint
|
||||||
* if (iter == 0) model.InitParameters();
|
* int iter = rabit::LoadCheckPoint(&model);
|
||||||
* for (i = iter; i < max_iter; ++i) {
|
* if (iter == 0) model.InitParameters();
|
||||||
* do many things, include allreduce
|
* for (i = iter; i < max_iter; ++i) {
|
||||||
* rabit::CheckPoint(model);
|
* // do many things, include allreduce
|
||||||
* }
|
* rabit::CheckPoint(model);
|
||||||
*
|
* }
|
||||||
|
* \endcode
|
||||||
* \sa CheckPoint, VersionNumber
|
* \sa CheckPoint, VersionNumber
|
||||||
*/
|
*/
|
||||||
inline int LoadCheckPoint(Serializable *global_model,
|
inline int LoadCheckPoint(Serializable *global_model,
|
||||||
@ -242,7 +255,7 @@ class ReduceHandle;
|
|||||||
* \tparam freduce the customized reduction function
|
* \tparam freduce the customized reduction function
|
||||||
* DType must be a struct, with no pointer
|
* DType must be a struct, with no pointer
|
||||||
*/
|
*/
|
||||||
template<typename DType, void (*freduce)(DType &dst, const DType &src)>
|
template<typename DType, void (*freduce)(DType &dst, const DType &src)> // NOLINT(*)
|
||||||
class Reducer {
|
class Reducer {
|
||||||
public:
|
public:
|
||||||
Reducer(void);
|
Reducer(void);
|
||||||
@ -256,9 +269,9 @@ class Reducer {
|
|||||||
* \param prepare_arg argument used to pass into the lazy preprocessing function
|
* \param prepare_arg argument used to pass into the lazy preprocessing function
|
||||||
*/
|
*/
|
||||||
inline void Allreduce(DType *sendrecvbuf, size_t count,
|
inline void Allreduce(DType *sendrecvbuf, size_t count,
|
||||||
void (*prepare_fun)(void *arg) = NULL,
|
void (*prepare_fun)(void *) = NULL,
|
||||||
void *prepare_arg = NULL);
|
void *prepare_arg = NULL);
|
||||||
#if __cplusplus >= 201103L
|
#if DMLC_USE_CXX11
|
||||||
/*!
|
/*!
|
||||||
* \brief customized in-place all reduce operation, with lambda function as preprocessor
|
* \brief customized in-place all reduce operation, with lambda function as preprocessor
|
||||||
* \param sendrecvbuf pointer to the array of objects to be reduced
|
* \param sendrecvbuf pointer to the array of objects to be reduced
|
||||||
@ -300,10 +313,10 @@ class SerializeReducer {
|
|||||||
*/
|
*/
|
||||||
inline void Allreduce(DType *sendrecvobj,
|
inline void Allreduce(DType *sendrecvobj,
|
||||||
size_t max_nbyte, size_t count,
|
size_t max_nbyte, size_t count,
|
||||||
void (*prepare_fun)(void *arg) = NULL,
|
void (*prepare_fun)(void *) = NULL,
|
||||||
void *prepare_arg = NULL);
|
void *prepare_arg = NULL);
|
||||||
// C++11 support for lambda prepare function
|
// C++11 support for lambda prepare function
|
||||||
#if __cplusplus >= 201103L
|
#if DMLC_USE_CXX11
|
||||||
/*!
|
/*!
|
||||||
* \brief customized in-place all reduce operation, with lambda function as preprocessor
|
* \brief customized in-place all reduce operation, with lambda function as preprocessor
|
||||||
* \param sendrecvobj pointer to the array of objects to be reduced
|
* \param sendrecvobj pointer to the array of objects to be reduced
|
||||||
@ -326,4 +339,4 @@ class SerializeReducer {
|
|||||||
} // namespace rabit
|
} // namespace rabit
|
||||||
// implementation of template functions
|
// implementation of template functions
|
||||||
#include "./rabit/rabit-inl.h"
|
#include "./rabit/rabit-inl.h"
|
||||||
#endif // RABIT_RABIT_H_
|
#endif // RABIT_RABIT_H_ // NOLINT(*)
|
||||||
|
|||||||
@ -183,7 +183,9 @@ enum DataType {
|
|||||||
kLong = 4,
|
kLong = 4,
|
||||||
kULong = 5,
|
kULong = 5,
|
||||||
kFloat = 6,
|
kFloat = 6,
|
||||||
kDouble = 7
|
kDouble = 7,
|
||||||
|
kLongLong = 8,
|
||||||
|
kULongLong = 9
|
||||||
};
|
};
|
||||||
} // namespace mpi
|
} // namespace mpi
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
* \brief utilities with different serializable implementations
|
* \brief utilities with different serializable implementations
|
||||||
* \author Tianqi Chen
|
* \author Tianqi Chen
|
||||||
*/
|
*/
|
||||||
#ifndef RABIT_UTILS_IO_H_
|
#ifndef RABIT_IO_H_
|
||||||
#define RABIT_UTILS_IO_H_
|
#define RABIT_IO_H_
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -51,6 +51,7 @@ struct MemoryFixSizeBuffer : public SeekStream {
|
|||||||
virtual bool AtEnd(void) const {
|
virtual bool AtEnd(void) const {
|
||||||
return curr_ptr_ == buffer_size_;
|
return curr_ptr_ == buffer_size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*! \brief in memory buffer */
|
/*! \brief in memory buffer */
|
||||||
char *p_buffer_;
|
char *p_buffer_;
|
||||||
@ -93,6 +94,7 @@ struct MemoryBufferStream : public SeekStream {
|
|||||||
virtual bool AtEnd(void) const {
|
virtual bool AtEnd(void) const {
|
||||||
return curr_ptr_ == p_buffer_->length();
|
return curr_ptr_ == p_buffer_->length();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*! \brief in memory buffer */
|
/*! \brief in memory buffer */
|
||||||
std::string *p_buffer_;
|
std::string *p_buffer_;
|
||||||
@ -101,4 +103,4 @@ struct MemoryBufferStream : public SeekStream {
|
|||||||
}; // class MemoryBufferStream
|
}; // class MemoryBufferStream
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
} // namespace rabit
|
} // namespace rabit
|
||||||
#endif // RABIT_UTILS_IO_H_
|
#endif // RABIT_IO_H_
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
/*!
|
/*!
|
||||||
|
* Copyright by Contributors
|
||||||
* \file rabit-inl.h
|
* \file rabit-inl.h
|
||||||
* \brief implementation of inline template function for rabit interface
|
* \brief implementation of inline template function for rabit interface
|
||||||
*
|
*
|
||||||
* \author Tianqi Chen
|
* \author Tianqi Chen
|
||||||
*/
|
*/
|
||||||
#ifndef RABIT_RABIT_INL_H
|
#ifndef RABIT_RABIT_INL_H_
|
||||||
#define RABIT_RABIT_INL_H
|
#define RABIT_RABIT_INL_H_
|
||||||
// use engine for implementation
|
// use engine for implementation
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
#include "./io.h"
|
#include "./io.h"
|
||||||
#include "./utils.h"
|
#include "./utils.h"
|
||||||
#include "../rabit.h"
|
#include "../rabit.h"
|
||||||
@ -30,15 +33,15 @@ inline DataType GetType<int>(void) {
|
|||||||
return kInt;
|
return kInt;
|
||||||
}
|
}
|
||||||
template<>
|
template<>
|
||||||
inline DataType GetType<unsigned>(void) {
|
inline DataType GetType<unsigned int>(void) { // NOLINT(*)
|
||||||
return kUInt;
|
return kUInt;
|
||||||
}
|
}
|
||||||
template<>
|
template<>
|
||||||
inline DataType GetType<long>(void) {
|
inline DataType GetType<long>(void) { // NOLINT(*)
|
||||||
return kLong;
|
return kLong;
|
||||||
}
|
}
|
||||||
template<>
|
template<>
|
||||||
inline DataType GetType<unsigned long>(void) {
|
inline DataType GetType<unsigned long>(void) { // NOLINT(*)
|
||||||
return kULong;
|
return kULong;
|
||||||
}
|
}
|
||||||
template<>
|
template<>
|
||||||
@ -49,47 +52,55 @@ template<>
|
|||||||
inline DataType GetType<double>(void) {
|
inline DataType GetType<double>(void) {
|
||||||
return kDouble;
|
return kDouble;
|
||||||
}
|
}
|
||||||
|
template<>
|
||||||
|
inline DataType GetType<long long>(void) { // NOLINT(*)
|
||||||
|
return kLongLong;
|
||||||
|
}
|
||||||
|
template<>
|
||||||
|
inline DataType GetType<unsigned long long>(void) { // NOLINT(*)
|
||||||
|
return kULongLong;
|
||||||
|
}
|
||||||
} // namespace mpi
|
} // namespace mpi
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
|
||||||
namespace op {
|
namespace op {
|
||||||
struct Max {
|
struct Max {
|
||||||
const static engine::mpi::OpType kType = engine::mpi::kMax;
|
static const engine::mpi::OpType kType = engine::mpi::kMax;
|
||||||
template<typename DType>
|
template<typename DType>
|
||||||
inline static void Reduce(DType &dst, const DType &src) {
|
inline static void Reduce(DType &dst, const DType &src) { // NOLINT(*)
|
||||||
if (dst < src) dst = src;
|
if (dst < src) dst = src;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct Min {
|
struct Min {
|
||||||
const static engine::mpi::OpType kType = engine::mpi::kMin;
|
static const engine::mpi::OpType kType = engine::mpi::kMin;
|
||||||
template<typename DType>
|
template<typename DType>
|
||||||
inline static void Reduce(DType &dst, const DType &src) {
|
inline static void Reduce(DType &dst, const DType &src) { // NOLINT(*)
|
||||||
if (dst > src) dst = src;
|
if (dst > src) dst = src;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct Sum {
|
struct Sum {
|
||||||
const static engine::mpi::OpType kType = engine::mpi::kSum;
|
static const engine::mpi::OpType kType = engine::mpi::kSum;
|
||||||
template<typename DType>
|
template<typename DType>
|
||||||
inline static void Reduce(DType &dst, const DType &src) {
|
inline static void Reduce(DType &dst, const DType &src) { // NOLINT(*)
|
||||||
dst += src;
|
dst += src;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct BitOR {
|
struct BitOR {
|
||||||
const static engine::mpi::OpType kType = engine::mpi::kBitwiseOR;
|
static const engine::mpi::OpType kType = engine::mpi::kBitwiseOR;
|
||||||
template<typename DType>
|
template<typename DType>
|
||||||
inline static void Reduce(DType &dst, const DType &src) {
|
inline static void Reduce(DType &dst, const DType &src) { // NOLINT(*)
|
||||||
dst |= src;
|
dst |= src;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<typename OP, typename DType>
|
template<typename OP, typename DType>
|
||||||
inline void Reducer(const void *src_, void *dst_, int len, const MPI::Datatype &dtype) {
|
inline void Reducer(const void *src_, void *dst_, int len, const MPI::Datatype &dtype) {
|
||||||
const DType *src = (const DType*)src_;
|
const DType *src = (const DType*)src_;
|
||||||
DType *dst = (DType*)dst_;
|
DType *dst = (DType*)dst_; // NOLINT(*)
|
||||||
for (int i = 0; i < len; ++i) {
|
for (int i = 0; i < len; ++i) {
|
||||||
OP::Reduce(dst[i], src[i]);
|
OP::Reduce(dst[i], src[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace op
|
} // namespace op
|
||||||
|
|
||||||
// intialize the rabit engine
|
// intialize the rabit engine
|
||||||
inline void Init(int argc, char *argv[]) {
|
inline void Init(int argc, char *argv[]) {
|
||||||
@ -146,21 +157,21 @@ template<typename OP, typename DType>
|
|||||||
inline void Allreduce(DType *sendrecvbuf, size_t count,
|
inline void Allreduce(DType *sendrecvbuf, size_t count,
|
||||||
void (*prepare_fun)(void *arg),
|
void (*prepare_fun)(void *arg),
|
||||||
void *prepare_arg) {
|
void *prepare_arg) {
|
||||||
engine::Allreduce_(sendrecvbuf, sizeof(DType), count, op::Reducer<OP,DType>,
|
engine::Allreduce_(sendrecvbuf, sizeof(DType), count, op::Reducer<OP, DType>,
|
||||||
engine::mpi::GetType<DType>(), OP::kType, prepare_fun, prepare_arg);
|
engine::mpi::GetType<DType>(), OP::kType, prepare_fun, prepare_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// C++11 support for lambda prepare function
|
// C++11 support for lambda prepare function
|
||||||
#if __cplusplus >= 201103L
|
#if DMLC_USE_CXX11
|
||||||
inline void InvokeLambda_(void *fun) {
|
inline void InvokeLambda_(void *fun) {
|
||||||
(*static_cast<std::function<void()>*>(fun))();
|
(*static_cast<std::function<void()>*>(fun))();
|
||||||
}
|
}
|
||||||
template<typename OP, typename DType>
|
template<typename OP, typename DType>
|
||||||
inline void Allreduce(DType *sendrecvbuf, size_t count, std::function<void()> prepare_fun) {
|
inline void Allreduce(DType *sendrecvbuf, size_t count, std::function<void()> prepare_fun) {
|
||||||
engine::Allreduce_(sendrecvbuf, sizeof(DType), count, op::Reducer<OP,DType>,
|
engine::Allreduce_(sendrecvbuf, sizeof(DType), count, op::Reducer<OP, DType>,
|
||||||
engine::mpi::GetType<DType>(), OP::kType, InvokeLambda_, &prepare_fun);
|
engine::mpi::GetType<DType>(), OP::kType, InvokeLambda_, &prepare_fun);
|
||||||
}
|
}
|
||||||
#endif // C++11
|
#endif // C++11
|
||||||
|
|
||||||
// print message to the tracker
|
// print message to the tracker
|
||||||
inline void TrackerPrint(const std::string &msg) {
|
inline void TrackerPrint(const std::string &msg) {
|
||||||
@ -215,15 +226,16 @@ inline void ReducerSafe_(const void *src_, void *dst_, int len_, const MPI::Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// function to perform reduction for Reducer
|
// function to perform reduction for Reducer
|
||||||
template<typename DType, void (*freduce)(DType &dst, const DType &src)>
|
template<typename DType, void (*freduce)(DType &dst, const DType &src)> // NOLINT(*)
|
||||||
inline void ReducerAlign_(const void *src_, void *dst_, int len_, const MPI::Datatype &dtype) {
|
inline void ReducerAlign_(const void *src_, void *dst_,
|
||||||
|
int len_, const MPI::Datatype &dtype) {
|
||||||
const DType *psrc = reinterpret_cast<const DType*>(src_);
|
const DType *psrc = reinterpret_cast<const DType*>(src_);
|
||||||
DType *pdst = reinterpret_cast<DType*>(dst_);
|
DType *pdst = reinterpret_cast<DType*>(dst_);
|
||||||
for (int i = 0; i < len_; ++i) {
|
for (int i = 0; i < len_; ++i) {
|
||||||
freduce(pdst[i], psrc[i]);
|
freduce(pdst[i], psrc[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename DType, void (*freduce)(DType &dst, const DType &src)>
|
template<typename DType, void (*freduce)(DType &dst, const DType &src)> // NOLINT(*)
|
||||||
inline Reducer<DType, freduce>::Reducer(void) {
|
inline Reducer<DType, freduce>::Reducer(void) {
|
||||||
// it is safe to directly use handle for aligned data types
|
// it is safe to directly use handle for aligned data types
|
||||||
if (sizeof(DType) == 8 || sizeof(DType) == 4 || sizeof(DType) == 1) {
|
if (sizeof(DType) == 8 || sizeof(DType) == 4 || sizeof(DType) == 1) {
|
||||||
@ -232,7 +244,7 @@ inline Reducer<DType, freduce>::Reducer(void) {
|
|||||||
this->handle_.Init(ReducerSafe_<DType, freduce>, sizeof(DType));
|
this->handle_.Init(ReducerSafe_<DType, freduce>, sizeof(DType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename DType, void (*freduce)(DType &dst, const DType &src)>
|
template<typename DType, void (*freduce)(DType &dst, const DType &src)> // NOLINT(*)
|
||||||
inline void Reducer<DType, freduce>::Allreduce(DType *sendrecvbuf, size_t count,
|
inline void Reducer<DType, freduce>::Allreduce(DType *sendrecvbuf, size_t count,
|
||||||
void (*prepare_fun)(void *arg),
|
void (*prepare_fun)(void *arg),
|
||||||
void *prepare_arg) {
|
void *prepare_arg) {
|
||||||
@ -240,13 +252,14 @@ inline void Reducer<DType, freduce>::Allreduce(DType *sendrecvbuf, size_t count,
|
|||||||
}
|
}
|
||||||
// function to perform reduction for SerializeReducer
|
// function to perform reduction for SerializeReducer
|
||||||
template<typename DType>
|
template<typename DType>
|
||||||
inline void SerializeReducerFunc_(const void *src_, void *dst_, int len_, const MPI::Datatype &dtype) {
|
inline void SerializeReducerFunc_(const void *src_, void *dst_,
|
||||||
|
int len_, const MPI::Datatype &dtype) {
|
||||||
int nbytes = engine::ReduceHandle::TypeSize(dtype);
|
int nbytes = engine::ReduceHandle::TypeSize(dtype);
|
||||||
// temp space
|
// temp space
|
||||||
DType tsrc, tdst;
|
DType tsrc, tdst;
|
||||||
for (int i = 0; i < len_; ++i) {
|
for (int i = 0; i < len_; ++i) {
|
||||||
utils::MemoryFixSizeBuffer fsrc((char*)(src_) + i * nbytes, nbytes);
|
utils::MemoryFixSizeBuffer fsrc((char*)(src_) + i * nbytes, nbytes); // NOLINT(*)
|
||||||
utils::MemoryFixSizeBuffer fdst((char*)(dst_) + i * nbytes, nbytes);
|
utils::MemoryFixSizeBuffer fdst((char*)(dst_) + i * nbytes, nbytes); // NOLINT(*)
|
||||||
tsrc.Load(fsrc);
|
tsrc.Load(fsrc);
|
||||||
tdst.Load(fdst);
|
tdst.Load(fdst);
|
||||||
// govern const check
|
// govern const check
|
||||||
@ -298,8 +311,8 @@ inline void SerializeReducer<DType>::Allreduce(DType *sendrecvobj,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
#if DMLC_USE_CXX11
|
||||||
template<typename DType, void (*freduce)(DType &dst, const DType &src)>
|
template<typename DType, void (*freduce)(DType &dst, const DType &src)> // NOLINT(*)g
|
||||||
inline void Reducer<DType, freduce>::Allreduce(DType *sendrecvbuf, size_t count,
|
inline void Reducer<DType, freduce>::Allreduce(DType *sendrecvbuf, size_t count,
|
||||||
std::function<void()> prepare_fun) {
|
std::function<void()> prepare_fun) {
|
||||||
this->Allreduce(sendrecvbuf, count, InvokeLambda_, &prepare_fun);
|
this->Allreduce(sendrecvbuf, count, InvokeLambda_, &prepare_fun);
|
||||||
@ -312,4 +325,4 @@ inline void SerializeReducer<DType>::Allreduce(DType *sendrecvobj,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} // namespace rabit
|
} // namespace rabit
|
||||||
#endif
|
#endif // RABIT_RABIT_INL_H_
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
/*!
|
/*!
|
||||||
|
* Copyright by Contributors
|
||||||
* \file timer.h
|
* \file timer.h
|
||||||
* \brief This file defines the utils for timing
|
* \brief This file defines the utils for timing
|
||||||
* \author Tianqi Chen, Nacho, Tianyi
|
* \author Tianqi Chen, Nacho, Tianyi
|
||||||
@ -18,7 +19,6 @@ namespace utils {
|
|||||||
* \brief return time in seconds, not cross platform, avoid to use this in most places
|
* \brief return time in seconds, not cross platform, avoid to use this in most places
|
||||||
*/
|
*/
|
||||||
inline double GetTime(void) {
|
inline double GetTime(void) {
|
||||||
// TODO: use c++11 chrono when c++11 was available
|
|
||||||
#ifdef __MACH__
|
#ifdef __MACH__
|
||||||
clock_serv_t cclock;
|
clock_serv_t cclock;
|
||||||
mach_timespec_t mts;
|
mach_timespec_t mts;
|
||||||
@ -32,7 +32,6 @@ inline double GetTime(void) {
|
|||||||
utils::Check(clock_gettime(CLOCK_REALTIME, &ts) == 0, "failed to get time");
|
utils::Check(clock_gettime(CLOCK_REALTIME, &ts) == 0, "failed to get time");
|
||||||
return static_cast<double>(ts.tv_sec) + static_cast<double>(ts.tv_nsec) * 1e-9;
|
return static_cast<double>(ts.tv_sec) + static_cast<double>(ts.tv_nsec) * 1e-9;
|
||||||
#else
|
#else
|
||||||
// TODO: add MSVC macro, and MSVC timer
|
|
||||||
return static_cast<double>(time(NULL));
|
return static_cast<double>(time(NULL));
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
#else
|
#else
|
||||||
#ifdef _FILE_OFFSET_BITS
|
#ifdef _FILE_OFFSET_BITS
|
||||||
#if _FILE_OFFSET_BITS == 32
|
#if _FILE_OFFSET_BITS == 32
|
||||||
#pragma message ("Warning: FILE OFFSET BITS defined to be 32 bit")
|
#pragma message("Warning: FILE OFFSET BITS defined to be 32 bit")
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ inline std::FILE *FopenCheck(const char *fname, const char *flag) {
|
|||||||
// easy utils that can be directly accessed in xgboost
|
// easy utils that can be directly accessed in xgboost
|
||||||
/*! \brief get the beginning address of a vector */
|
/*! \brief get the beginning address of a vector */
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T *BeginPtr(std::vector<T> &vec) {
|
inline T *BeginPtr(std::vector<T> &vec) { // NOLINT(*)
|
||||||
if (vec.size() == 0) {
|
if (vec.size() == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
@ -172,14 +172,14 @@ inline T *BeginPtr(std::vector<T> &vec) {
|
|||||||
}
|
}
|
||||||
/*! \brief get the beginning address of a vector */
|
/*! \brief get the beginning address of a vector */
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline const T *BeginPtr(const std::vector<T> &vec) {
|
inline const T *BeginPtr(const std::vector<T> &vec) { // NOLINT(*)
|
||||||
if (vec.size() == 0) {
|
if (vec.size() == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
return &vec[0];
|
return &vec[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline char* BeginPtr(std::string &str) {
|
inline char* BeginPtr(std::string &str) { // NOLINT(*)
|
||||||
if (str.length() == 0) return NULL;
|
if (str.length() == 0) return NULL;
|
||||||
return &str[0];
|
return &str[0];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
* \brief defines serializable interface of rabit
|
* \brief defines serializable interface of rabit
|
||||||
* \author Tianqi Chen
|
* \author Tianqi Chen
|
||||||
*/
|
*/
|
||||||
#ifndef RABIT_RABIT_SERIALIZABLE_H_
|
#ifndef RABIT_SERIALIZABLE_H_
|
||||||
#define RABIT_RABIT_SERIALIZABLE_H_
|
#define RABIT_SERIALIZABLE_H_
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "./rabit/utils.h"
|
#include "./rabit/utils.h"
|
||||||
@ -24,4 +24,4 @@ typedef dmlc::Stream Stream;
|
|||||||
typedef dmlc::Serializable Serializable;
|
typedef dmlc::Serializable Serializable;
|
||||||
|
|
||||||
} // namespace rabit
|
} // namespace rabit
|
||||||
#endif // RABIT_RABIT_SERIALIZABLE_H_
|
#endif // RABIT_SERIALIZABLE_H_
|
||||||
|
|||||||
8
subtree/rabit/scripts/travis_runtest.sh
Executable file
8
subtree/rabit/scripts/travis_runtest.sh
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
make -f test.mk model_recover_10_10k || exit -1
|
||||||
|
make -f test.mk model_recover_10_10k_die_same || exit -1
|
||||||
|
make -f test.mk local_recover_10_10k || exit -1
|
||||||
|
make -f test.mk pylocal_recover_10_10k || exit -1
|
||||||
|
make -f test.mk lazy_recover_10_10k_die_hard || exit -1
|
||||||
|
make -f test.mk lazy_recover_10_10k_die_same || exit -1
|
||||||
|
make -f test.mk ringallreduce_10_10k || exit -1
|
||||||
22
subtree/rabit/scripts/travis_script.sh
Executable file
22
subtree/rabit/scripts/travis_script.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# main script of travis
|
||||||
|
if [ ${TASK} == "lint" ]; then
|
||||||
|
make lint || exit -1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${TASK} == "doc" ]; then
|
||||||
|
make doc 2>log.txt
|
||||||
|
(cat log.txt| grep -v ENABLE_PREPROCESSING |grep -v "unsupported tag" |grep warning) && exit -1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${TASK} == "build" ]; then
|
||||||
|
make all || exit -1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${TASK} == "test" ]; then
|
||||||
|
cd test
|
||||||
|
make all || exit -1
|
||||||
|
../scripts/travis_runtest.sh || exit -1
|
||||||
|
fi
|
||||||
|
|
||||||
@ -24,6 +24,7 @@ AllreduceBase::AllreduceBase(void) {
|
|||||||
nport_trial = 1000;
|
nport_trial = 1000;
|
||||||
rank = 0;
|
rank = 0;
|
||||||
world_size = -1;
|
world_size = -1;
|
||||||
|
connect_retry = 5;
|
||||||
hadoop_mode = 0;
|
hadoop_mode = 0;
|
||||||
version_number = 0;
|
version_number = 0;
|
||||||
// 32 K items
|
// 32 K items
|
||||||
@ -46,6 +47,7 @@ AllreduceBase::AllreduceBase(void) {
|
|||||||
env_vars.push_back("DMLC_NUM_ATTEMPT");
|
env_vars.push_back("DMLC_NUM_ATTEMPT");
|
||||||
env_vars.push_back("DMLC_TRACKER_URI");
|
env_vars.push_back("DMLC_TRACKER_URI");
|
||||||
env_vars.push_back("DMLC_TRACKER_PORT");
|
env_vars.push_back("DMLC_TRACKER_PORT");
|
||||||
|
env_vars.push_back("DMLC_WORKER_CONNECT_RETRY");
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialization function
|
// initialization function
|
||||||
@ -94,7 +96,8 @@ void AllreduceBase::Init(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dmlc_role != "worker") {
|
if (dmlc_role != "worker") {
|
||||||
fprintf(stderr, "Rabit Module currently only work with dmlc worker, quit this program by exit 0\n");
|
fprintf(stderr, "Rabit Module currently only work with dmlc worker"\
|
||||||
|
", quit this program by exit 0\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
// clear the setting before start reconnection
|
// clear the setting before start reconnection
|
||||||
@ -134,7 +137,7 @@ void AllreduceBase::TrackerPrint(const std::string &msg) {
|
|||||||
// util to parse data with unit suffix
|
// util to parse data with unit suffix
|
||||||
inline size_t ParseUnit(const char *name, const char *val) {
|
inline size_t ParseUnit(const char *name, const char *val) {
|
||||||
char unit;
|
char unit;
|
||||||
unsigned long amt;
|
unsigned long amt; // NOLINT(*)
|
||||||
int n = sscanf(val, "%lu%c", &amt, &unit);
|
int n = sscanf(val, "%lu%c", &amt, &unit);
|
||||||
size_t amount = amt;
|
size_t amount = amt;
|
||||||
if (n == 2) {
|
if (n == 2) {
|
||||||
@ -174,6 +177,9 @@ void AllreduceBase::SetParam(const char *name, const char *val) {
|
|||||||
if (!strcmp(name, "rabit_reduce_buffer")) {
|
if (!strcmp(name, "rabit_reduce_buffer")) {
|
||||||
reduce_buffer_size = (ParseUnit(name, val) + 7) >> 3;
|
reduce_buffer_size = (ParseUnit(name, val) + 7) >> 3;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(name, "DMLC_WORKER_CONNECT_RETRY")) {
|
||||||
|
connect_retry = atoi(val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*!
|
/*!
|
||||||
* \brief initialize connection to the tracker
|
* \brief initialize connection to the tracker
|
||||||
@ -184,9 +190,23 @@ utils::TCPSocket AllreduceBase::ConnectTracker(void) const {
|
|||||||
// get information from tracker
|
// get information from tracker
|
||||||
utils::TCPSocket tracker;
|
utils::TCPSocket tracker;
|
||||||
tracker.Create();
|
tracker.Create();
|
||||||
if (!tracker.Connect(utils::SockAddr(tracker_uri.c_str(), tracker_port))) {
|
|
||||||
utils::Socket::Error("Connect");
|
int retry = 0;
|
||||||
}
|
do {
|
||||||
|
fprintf(stderr, "connect to ip: [%s]\n", tracker_uri.c_str());
|
||||||
|
if (!tracker.Connect(utils::SockAddr(tracker_uri.c_str(), tracker_port))) {
|
||||||
|
if (++retry >= connect_retry) {
|
||||||
|
fprintf(stderr, "connect to (failed): [%s]\n", tracker_uri.c_str());
|
||||||
|
utils::Socket::Error("Connect");
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "retry connect to ip(retry time %d): [%s]\n", retry, tracker_uri.c_str());
|
||||||
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} while (1);
|
||||||
|
|
||||||
using utils::Assert;
|
using utils::Assert;
|
||||||
Assert(tracker.SendAll(&magic, sizeof(magic)) == sizeof(magic),
|
Assert(tracker.SendAll(&magic, sizeof(magic)) == sizeof(magic),
|
||||||
"ReConnectLink failure 1");
|
"ReConnectLink failure 1");
|
||||||
@ -440,7 +460,7 @@ AllreduceBase::TryAllreduceTree(void *sendrecvbuf_,
|
|||||||
selecter.WatchRead(links[i].sock);
|
selecter.WatchRead(links[i].sock);
|
||||||
}
|
}
|
||||||
// size_write <= size_read
|
// size_write <= size_read
|
||||||
if (links[i].size_write != total_size){
|
if (links[i].size_write != total_size) {
|
||||||
if (links[i].size_write < size_down_in) {
|
if (links[i].size_write < size_down_in) {
|
||||||
selecter.WatchWrite(links[i].sock);
|
selecter.WatchWrite(links[i].sock);
|
||||||
}
|
}
|
||||||
@ -477,7 +497,7 @@ AllreduceBase::TryAllreduceTree(void *sendrecvbuf_,
|
|||||||
size_t max_reduce = total_size;
|
size_t max_reduce = total_size;
|
||||||
for (int i = 0; i < nlink; ++i) {
|
for (int i = 0; i < nlink; ++i) {
|
||||||
if (i != parent_index) {
|
if (i != parent_index) {
|
||||||
max_reduce= std::min(max_reduce, links[i].size_read);
|
max_reduce = std::min(max_reduce, links[i].size_read);
|
||||||
utils::Assert(buffer_size == 0 || buffer_size == links[i].buffer_size,
|
utils::Assert(buffer_size == 0 || buffer_size == links[i].buffer_size,
|
||||||
"buffer size inconsistent");
|
"buffer size inconsistent");
|
||||||
buffer_size = links[i].buffer_size;
|
buffer_size = links[i].buffer_size;
|
||||||
@ -513,7 +533,7 @@ AllreduceBase::TryAllreduceTree(void *sendrecvbuf_,
|
|||||||
if (len != -1) {
|
if (len != -1) {
|
||||||
size_up_out += static_cast<size_t>(len);
|
size_up_out += static_cast<size_t>(len);
|
||||||
} else {
|
} else {
|
||||||
ReturnType ret = Errno2Return(errno);
|
ReturnType ret = Errno2Return();
|
||||||
if (ret != kSuccess) {
|
if (ret != kSuccess) {
|
||||||
return ReportError(&links[parent_index], ret);
|
return ReportError(&links[parent_index], ret);
|
||||||
}
|
}
|
||||||
@ -533,7 +553,7 @@ AllreduceBase::TryAllreduceTree(void *sendrecvbuf_,
|
|||||||
utils::Assert(size_down_in <= size_up_out,
|
utils::Assert(size_down_in <= size_up_out,
|
||||||
"Allreduce: boundary error");
|
"Allreduce: boundary error");
|
||||||
} else {
|
} else {
|
||||||
ReturnType ret = Errno2Return(errno);
|
ReturnType ret = Errno2Return();
|
||||||
if (ret != kSuccess) {
|
if (ret != kSuccess) {
|
||||||
return ReportError(&links[parent_index], ret);
|
return ReportError(&links[parent_index], ret);
|
||||||
}
|
}
|
||||||
@ -709,7 +729,7 @@ AllreduceBase::TryAllgatherRing(void *sendrecvbuf_, size_t total_size,
|
|||||||
if (len != -1) {
|
if (len != -1) {
|
||||||
read_ptr += static_cast<size_t>(len);
|
read_ptr += static_cast<size_t>(len);
|
||||||
} else {
|
} else {
|
||||||
ReturnType ret = Errno2Return(errno);
|
ReturnType ret = Errno2Return();
|
||||||
if (ret != kSuccess) return ReportError(&next, ret);
|
if (ret != kSuccess) return ReportError(&next, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -723,7 +743,7 @@ AllreduceBase::TryAllgatherRing(void *sendrecvbuf_, size_t total_size,
|
|||||||
if (len != -1) {
|
if (len != -1) {
|
||||||
write_ptr += static_cast<size_t>(len);
|
write_ptr += static_cast<size_t>(len);
|
||||||
} else {
|
} else {
|
||||||
ReturnType ret = Errno2Return(errno);
|
ReturnType ret = Errno2Return();
|
||||||
if (ret != kSuccess) return ReportError(&prev, ret);
|
if (ret != kSuccess) return ReportError(&prev, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -826,7 +846,7 @@ AllreduceBase::TryReduceScatterRing(void *sendrecvbuf_,
|
|||||||
if (len != -1) {
|
if (len != -1) {
|
||||||
write_ptr += static_cast<size_t>(len);
|
write_ptr += static_cast<size_t>(len);
|
||||||
} else {
|
} else {
|
||||||
ReturnType ret = Errno2Return(errno);
|
ReturnType ret = Errno2Return();
|
||||||
if (ret != kSuccess) return ReportError(&prev, ret);
|
if (ret != kSuccess) return ReportError(&prev, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,6 +90,7 @@ class AllreduceBase : public IEngine {
|
|||||||
PreprocFunction prepare_fun = NULL,
|
PreprocFunction prepare_fun = NULL,
|
||||||
void *prepare_arg = NULL) {
|
void *prepare_arg = NULL) {
|
||||||
if (prepare_fun != NULL) prepare_fun(prepare_arg);
|
if (prepare_fun != NULL) prepare_fun(prepare_arg);
|
||||||
|
if (world_size == 1) return;
|
||||||
utils::Assert(TryAllreduce(sendrecvbuf_,
|
utils::Assert(TryAllreduce(sendrecvbuf_,
|
||||||
type_nbytes, count, reducer) == kSuccess,
|
type_nbytes, count, reducer) == kSuccess,
|
||||||
"Allreduce failed");
|
"Allreduce failed");
|
||||||
@ -101,6 +102,7 @@ class AllreduceBase : public IEngine {
|
|||||||
* \param root the root worker id to broadcast the data
|
* \param root the root worker id to broadcast the data
|
||||||
*/
|
*/
|
||||||
virtual void Broadcast(void *sendrecvbuf_, size_t total_size, int root) {
|
virtual void Broadcast(void *sendrecvbuf_, size_t total_size, int root) {
|
||||||
|
if (world_size == 1) return;
|
||||||
utils::Assert(TryBroadcast(sendrecvbuf_, total_size, root) == kSuccess,
|
utils::Assert(TryBroadcast(sendrecvbuf_, total_size, root) == kSuccess,
|
||||||
"Broadcast failed");
|
"Broadcast failed");
|
||||||
}
|
}
|
||||||
@ -223,7 +225,7 @@ class AllreduceBase : public IEngine {
|
|||||||
ReturnTypeEnum value;
|
ReturnTypeEnum value;
|
||||||
// constructor
|
// constructor
|
||||||
ReturnType() {}
|
ReturnType() {}
|
||||||
ReturnType(ReturnTypeEnum value) : value(value){}
|
ReturnType(ReturnTypeEnum value) : value(value) {} // NOLINT(*)
|
||||||
inline bool operator==(const ReturnTypeEnum &v) const {
|
inline bool operator==(const ReturnTypeEnum &v) const {
|
||||||
return value == v;
|
return value == v;
|
||||||
}
|
}
|
||||||
@ -232,8 +234,13 @@ class AllreduceBase : public IEngine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
/*! \brief translate errno to return type */
|
/*! \brief translate errno to return type */
|
||||||
inline static ReturnType Errno2Return(int errsv) {
|
inline static ReturnType Errno2Return() {
|
||||||
if (errsv == EAGAIN || errsv == EWOULDBLOCK) return kSuccess;
|
int errsv = utils::Socket::GetLastError();
|
||||||
|
if (errsv == EAGAIN || errsv == EWOULDBLOCK || errsv == 0) return kSuccess;
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (errsv == WSAEWOULDBLOCK) return kSuccess;
|
||||||
|
if (errsv == WSAECONNRESET) return kConnReset;
|
||||||
|
#endif
|
||||||
if (errsv == ECONNRESET) return kConnReset;
|
if (errsv == ECONNRESET) return kConnReset;
|
||||||
return kSockError;
|
return kSockError;
|
||||||
}
|
}
|
||||||
@ -297,7 +304,7 @@ class AllreduceBase : public IEngine {
|
|||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
sock.Close(); return kRecvZeroLen;
|
sock.Close(); return kRecvZeroLen;
|
||||||
}
|
}
|
||||||
if (len == -1) return Errno2Return(errno);
|
if (len == -1) return Errno2Return();
|
||||||
size_read += static_cast<size_t>(len);
|
size_read += static_cast<size_t>(len);
|
||||||
return kSuccess;
|
return kSuccess;
|
||||||
}
|
}
|
||||||
@ -316,7 +323,7 @@ class AllreduceBase : public IEngine {
|
|||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
sock.Close(); return kRecvZeroLen;
|
sock.Close(); return kRecvZeroLen;
|
||||||
}
|
}
|
||||||
if (len == -1) return Errno2Return(errno);
|
if (len == -1) return Errno2Return();
|
||||||
size_read += static_cast<size_t>(len);
|
size_read += static_cast<size_t>(len);
|
||||||
return kSuccess;
|
return kSuccess;
|
||||||
}
|
}
|
||||||
@ -329,7 +336,7 @@ class AllreduceBase : public IEngine {
|
|||||||
inline ReturnType WriteFromArray(const void *sendbuf_, size_t max_size) {
|
inline ReturnType WriteFromArray(const void *sendbuf_, size_t max_size) {
|
||||||
const char *p = static_cast<const char*>(sendbuf_);
|
const char *p = static_cast<const char*>(sendbuf_);
|
||||||
ssize_t len = sock.Send(p + size_write, max_size - size_write);
|
ssize_t len = sock.Send(p + size_write, max_size - size_write);
|
||||||
if (len == -1) return Errno2Return(errno);
|
if (len == -1) return Errno2Return();
|
||||||
size_write += static_cast<size_t>(len);
|
size_write += static_cast<size_t>(len);
|
||||||
return kSuccess;
|
return kSuccess;
|
||||||
}
|
}
|
||||||
@ -512,7 +519,9 @@ class AllreduceBase : public IEngine {
|
|||||||
int rank;
|
int rank;
|
||||||
// world size
|
// world size
|
||||||
int world_size;
|
int world_size;
|
||||||
|
// connect retry time
|
||||||
|
int connect_retry;
|
||||||
};
|
};
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace rabit
|
} // namespace rabit
|
||||||
#endif // RABIT_ALLREDUCE_BASE_H
|
#endif // RABIT_ALLREDUCE_BASE_H_
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
/*!
|
/*!
|
||||||
|
* Copyright by Contributors
|
||||||
* \file allreduce_mock.h
|
* \file allreduce_mock.h
|
||||||
* \brief Mock test module of AllReduce engine,
|
* \brief Mock test module of AllReduce engine,
|
||||||
* insert failures in certain call point, to test if the engine is robust to failure
|
* insert failures in certain call point, to test if the engine is robust to failure
|
||||||
@ -100,6 +101,7 @@ class AllreduceMock : public AllreduceRobust {
|
|||||||
this->Verify(MockKey(rank, version_number, seq_counter, num_trial), "LazyCheckPoint");
|
this->Verify(MockKey(rank, version_number, seq_counter, num_trial), "LazyCheckPoint");
|
||||||
AllreduceRobust::LazyCheckPoint(global_model);
|
AllreduceRobust::LazyCheckPoint(global_model);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// force checkpoint to local
|
// force checkpoint to local
|
||||||
int force_local;
|
int force_local;
|
||||||
@ -173,4 +175,4 @@ class AllreduceMock : public AllreduceRobust {
|
|||||||
};
|
};
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace rabit
|
} // namespace rabit
|
||||||
#endif // RABIT_ALLREDUCE_MOCK_H_
|
#endif // RABIT_ALLREDUCE_MOCK_H_
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
*
|
*
|
||||||
* \author Tianqi Chen
|
* \author Tianqi Chen
|
||||||
*/
|
*/
|
||||||
#ifndef RABIT_ENGINE_ROBUST_INL_H_
|
#ifndef RABIT_ALLREDUCE_ROBUST_INL_H_
|
||||||
#define RABIT_ENGINE_ROBUST_INL_H_
|
#define RABIT_ALLREDUCE_ROBUST_INL_H_
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace rabit {
|
namespace rabit {
|
||||||
@ -35,7 +35,7 @@ inline AllreduceRobust::ReturnType
|
|||||||
AllreduceRobust::MsgPassing(const NodeType &node_value,
|
AllreduceRobust::MsgPassing(const NodeType &node_value,
|
||||||
std::vector<EdgeType> *p_edge_in,
|
std::vector<EdgeType> *p_edge_in,
|
||||||
std::vector<EdgeType> *p_edge_out,
|
std::vector<EdgeType> *p_edge_out,
|
||||||
EdgeType (*func)
|
EdgeType(*func)
|
||||||
(const NodeType &node_value,
|
(const NodeType &node_value,
|
||||||
const std::vector<EdgeType> &edge_in,
|
const std::vector<EdgeType> &edge_in,
|
||||||
size_t out_index)) {
|
size_t out_index)) {
|
||||||
@ -80,8 +80,16 @@ AllreduceRobust::MsgPassing(const NodeType &node_value,
|
|||||||
selecter.WatchRead(links[i].sock);
|
selecter.WatchRead(links[i].sock);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: if (i == parent_index) selecter.WatchWrite(links[i].sock); break;
|
case 1:
|
||||||
case 2: if (i == parent_index) selecter.WatchRead(links[i].sock); break;
|
if (i == parent_index) {
|
||||||
|
selecter.WatchWrite(links[i].sock);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (i == parent_index) {
|
||||||
|
selecter.WatchRead(links[i].sock);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (i != parent_index && links[i].size_write != sizeof(EdgeType)) {
|
if (i != parent_index && links[i].size_write != sizeof(EdgeType)) {
|
||||||
selecter.WatchWrite(links[i].sock);
|
selecter.WatchWrite(links[i].sock);
|
||||||
@ -158,4 +166,4 @@ AllreduceRobust::MsgPassing(const NodeType &node_value,
|
|||||||
}
|
}
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace rabit
|
} // namespace rabit
|
||||||
#endif // RABIT_ENGINE_ROBUST_INL_H_
|
#endif // RABIT_ALLREDUCE_ROBUST_INL_H_
|
||||||
|
|||||||
@ -224,7 +224,7 @@ void AllreduceRobust::LocalModelCheck(bool with_local) {
|
|||||||
num_local_replica = 0;
|
num_local_replica = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
utils::Check(use_local_model == int(with_local),
|
utils::Check(use_local_model == static_cast<int>(with_local),
|
||||||
"Can only call Checkpoint/LoadCheckPoint always with"\
|
"Can only call Checkpoint/LoadCheckPoint always with"\
|
||||||
"or without local_model, but not mixed case");
|
"or without local_model, but not mixed case");
|
||||||
}
|
}
|
||||||
@ -691,7 +691,7 @@ AllreduceRobust::TryRecoverData(RecoverType role,
|
|||||||
if (len != -1) {
|
if (len != -1) {
|
||||||
links[i].size_write += len;
|
links[i].size_write += len;
|
||||||
} else {
|
} else {
|
||||||
ReturnType ret = Errno2Return(errno);
|
ReturnType ret = Errno2Return();
|
||||||
if (ret != kSuccess) return ReportError(&links[i], ret);
|
if (ret != kSuccess) return ReportError(&links[i], ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1161,7 +1161,7 @@ AllreduceRobust::RingPassing(void *sendrecvbuf_,
|
|||||||
if (len != -1) {
|
if (len != -1) {
|
||||||
read_ptr += static_cast<size_t>(len);
|
read_ptr += static_cast<size_t>(len);
|
||||||
} else {
|
} else {
|
||||||
ReturnType ret = Errno2Return(errno);
|
ReturnType ret = Errno2Return();
|
||||||
if (ret != kSuccess) return ReportError(&prev, ret);
|
if (ret != kSuccess) return ReportError(&prev, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1171,7 +1171,7 @@ AllreduceRobust::RingPassing(void *sendrecvbuf_,
|
|||||||
if (len != -1) {
|
if (len != -1) {
|
||||||
write_ptr += static_cast<size_t>(len);
|
write_ptr += static_cast<size_t>(len);
|
||||||
} else {
|
} else {
|
||||||
ReturnType ret = Errno2Return(errno);
|
ReturnType ret = Errno2Return();
|
||||||
if (ret != kSuccess) return ReportError(&prev, ret);
|
if (ret != kSuccess) return ReportError(&prev, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -287,6 +287,7 @@ class AllreduceRobust : public AllreduceBase {
|
|||||||
if (seqno_.size() == 0) return -1;
|
if (seqno_.size() == 0) return -1;
|
||||||
return seqno_.back();
|
return seqno_.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// sequence number of each
|
// sequence number of each
|
||||||
std::vector<int> seqno_;
|
std::vector<int> seqno_;
|
||||||
@ -509,7 +510,7 @@ o * the input state must exactly one saved state(local state of current node)
|
|||||||
inline ReturnType MsgPassing(const NodeType &node_value,
|
inline ReturnType MsgPassing(const NodeType &node_value,
|
||||||
std::vector<EdgeType> *p_edge_in,
|
std::vector<EdgeType> *p_edge_in,
|
||||||
std::vector<EdgeType> *p_edge_out,
|
std::vector<EdgeType> *p_edge_out,
|
||||||
EdgeType (*func)
|
EdgeType(*func)
|
||||||
(const NodeType &node_value,
|
(const NodeType &node_value,
|
||||||
const std::vector<EdgeType> &edge_in,
|
const std::vector<EdgeType> &edge_in,
|
||||||
size_t out_index));
|
size_t out_index));
|
||||||
|
|||||||
@ -110,6 +110,8 @@ inline MPI::Datatype GetType(mpi::DataType dtype) {
|
|||||||
case kULong: return MPI::UNSIGNED_LONG;
|
case kULong: return MPI::UNSIGNED_LONG;
|
||||||
case kFloat: return MPI::FLOAT;
|
case kFloat: return MPI::FLOAT;
|
||||||
case kDouble: return MPI::DOUBLE;
|
case kDouble: return MPI::DOUBLE;
|
||||||
|
case kLongLong: return MPI::LONG_LONG;
|
||||||
|
case kULongLong: return MPI::UNSIGNED_LONG_LONG;
|
||||||
}
|
}
|
||||||
utils::Error("unknown mpi::DataType");
|
utils::Error("unknown mpi::DataType");
|
||||||
return MPI::CHAR;
|
return MPI::CHAR;
|
||||||
@ -164,7 +166,7 @@ void ReduceHandle::Init(IEngine::ReduceFunction redfunc, size_t type_nbytes) {
|
|||||||
if (type_nbytes != 0) {
|
if (type_nbytes != 0) {
|
||||||
MPI::Datatype *dtype = new MPI::Datatype();
|
MPI::Datatype *dtype = new MPI::Datatype();
|
||||||
if (type_nbytes % 8 == 0) {
|
if (type_nbytes % 8 == 0) {
|
||||||
*dtype = MPI::LONG.Create_contiguous(type_nbytes / sizeof(long));
|
*dtype = MPI::LONG.Create_contiguous(type_nbytes / sizeof(long)); // NOLINT(*)
|
||||||
} else if (type_nbytes % 4 == 0) {
|
} else if (type_nbytes % 4 == 0) {
|
||||||
*dtype = MPI::INT.Create_contiguous(type_nbytes / sizeof(int));
|
*dtype = MPI::INT.Create_contiguous(type_nbytes / sizeof(int));
|
||||||
} else {
|
} else {
|
||||||
@ -193,7 +195,7 @@ void ReduceHandle::Allreduce(void *sendrecvbuf,
|
|||||||
dtype->Free();
|
dtype->Free();
|
||||||
}
|
}
|
||||||
if (type_nbytes % 8 == 0) {
|
if (type_nbytes % 8 == 0) {
|
||||||
*dtype = MPI::LONG.Create_contiguous(type_nbytes / sizeof(long));
|
*dtype = MPI::LONG.Create_contiguous(type_nbytes / sizeof(long)); // NOLINT(*)
|
||||||
} else if (type_nbytes % 4 == 0) {
|
} else if (type_nbytes % 4 == 0) {
|
||||||
*dtype = MPI::INT.Create_contiguous(type_nbytes / sizeof(int));
|
*dtype = MPI::INT.Create_contiguous(type_nbytes / sizeof(int));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -94,6 +94,25 @@ class Socket {
|
|||||||
inline operator SOCKET() const {
|
inline operator SOCKET() const {
|
||||||
return sockfd;
|
return sockfd;
|
||||||
}
|
}
|
||||||
|
/*!
|
||||||
|
* \return last error of socket operation
|
||||||
|
*/
|
||||||
|
inline static int GetLastError(void) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return WSAGetLastError();
|
||||||
|
#else
|
||||||
|
return errno;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/*! \return whether last error was would block */
|
||||||
|
inline static bool LastErrorWouldBlock(void) {
|
||||||
|
int errsv = GetLastError();
|
||||||
|
#ifdef _WIN32
|
||||||
|
return errsv == WSAEWOULDBLOCK;
|
||||||
|
#else
|
||||||
|
return errsv == EAGAIN || errsv == EWOULDBLOCK;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
/*!
|
/*!
|
||||||
* \brief start up the socket module
|
* \brief start up the socket module
|
||||||
* call this before using the sockets
|
* call this before using the sockets
|
||||||
@ -169,11 +188,11 @@ class Socket {
|
|||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
if (WSAGetLastError() != WSAEADDRINUSE) {
|
if (WSAGetLastError() != WSAEADDRINUSE) {
|
||||||
Socket::Error("TryBindHost");
|
Socket::Error("TryBindHost");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (errno != EADDRINUSE) {
|
if (errno != EADDRINUSE) {
|
||||||
Socket::Error("TryBindHost");
|
Socket::Error("TryBindHost");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -216,8 +235,12 @@ class Socket {
|
|||||||
}
|
}
|
||||||
// report an socket error
|
// report an socket error
|
||||||
inline static void Error(const char *msg) {
|
inline static void Error(const char *msg) {
|
||||||
int errsv = errno;
|
int errsv = GetLastError();
|
||||||
|
#ifdef _WIN32
|
||||||
|
utils::Error("Socket %s Error:WSAError-code=%d", msg, errsv);
|
||||||
|
#else
|
||||||
utils::Error("Socket %s Error:%s", msg, strerror(errsv));
|
utils::Error("Socket %s Error:%s", msg, strerror(errsv));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -241,7 +264,8 @@ class TCPSocket : public Socket{
|
|||||||
*/
|
*/
|
||||||
inline void SetKeepAlive(bool keepalive) {
|
inline void SetKeepAlive(bool keepalive) {
|
||||||
int opt = static_cast<int>(keepalive);
|
int opt = static_cast<int>(keepalive);
|
||||||
if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast<char*>(&opt), sizeof(opt)) < 0) {
|
if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
|
||||||
|
reinterpret_cast<char*>(&opt), sizeof(opt)) < 0) {
|
||||||
Socket::Error("SetKeepAlive");
|
Socket::Error("SetKeepAlive");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,7 +300,7 @@ class TCPSocket : public Socket{
|
|||||||
*/
|
*/
|
||||||
inline int AtMark(void) const {
|
inline int AtMark(void) const {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
unsigned long atmark;
|
unsigned long atmark; // NOLINT(*)
|
||||||
if (ioctlsocket(sockfd, SIOCATMARK, &atmark) != NO_ERROR) return -1;
|
if (ioctlsocket(sockfd, SIOCATMARK, &atmark) != NO_ERROR) return -1;
|
||||||
#else
|
#else
|
||||||
int atmark;
|
int atmark;
|
||||||
@ -330,7 +354,7 @@ class TCPSocket : public Socket{
|
|||||||
while (ndone < len) {
|
while (ndone < len) {
|
||||||
ssize_t ret = send(sockfd, buf, static_cast<ssize_t>(len - ndone), 0);
|
ssize_t ret = send(sockfd, buf, static_cast<ssize_t>(len - ndone), 0);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) return ndone;
|
if (LastErrorWouldBlock()) return ndone;
|
||||||
Socket::Error("SendAll");
|
Socket::Error("SendAll");
|
||||||
}
|
}
|
||||||
buf += ret;
|
buf += ret;
|
||||||
@ -352,7 +376,7 @@ class TCPSocket : public Socket{
|
|||||||
ssize_t ret = recv(sockfd, buf,
|
ssize_t ret = recv(sockfd, buf,
|
||||||
static_cast<sock_size_t>(len - ndone), MSG_WAITALL);
|
static_cast<sock_size_t>(len - ndone), MSG_WAITALL);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) return ndone;
|
if (LastErrorWouldBlock()) return ndone;
|
||||||
Socket::Error("RecvAll");
|
Socket::Error("RecvAll");
|
||||||
}
|
}
|
||||||
if (ret == 0) return ndone;
|
if (ret == 0) return ndone;
|
||||||
@ -450,7 +474,7 @@ struct SelectHelper {
|
|||||||
* \param timeout the timeout counter, can be 0, which means wait until the event happen
|
* \param timeout the timeout counter, can be 0, which means wait until the event happen
|
||||||
* \return 1 if success, 0 if timeout, and -1 if error occurs
|
* \return 1 if success, 0 if timeout, and -1 if error occurs
|
||||||
*/
|
*/
|
||||||
inline static int WaitExcept(SOCKET fd, long timeout = 0) {
|
inline static int WaitExcept(SOCKET fd, long timeout = 0) { // NOLINT(*)
|
||||||
fd_set wait_set;
|
fd_set wait_set;
|
||||||
FD_ZERO(&wait_set);
|
FD_ZERO(&wait_set);
|
||||||
FD_SET(fd, &wait_set);
|
FD_SET(fd, &wait_set);
|
||||||
@ -466,7 +490,7 @@ struct SelectHelper {
|
|||||||
* \return number of active descriptors selected,
|
* \return number of active descriptors selected,
|
||||||
* return -1 if error occurs
|
* return -1 if error occurs
|
||||||
*/
|
*/
|
||||||
inline int Select(long timeout = 0) {
|
inline int Select(long timeout = 0) { // NOLINT(*)
|
||||||
int ret = Select_(static_cast<int>(maxfd + 1),
|
int ret = Select_(static_cast<int>(maxfd + 1),
|
||||||
&read_set, &write_set, &except_set, timeout);
|
&read_set, &write_set, &except_set, timeout);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
@ -477,7 +501,7 @@ struct SelectHelper {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
inline static int Select_(int maxfd, fd_set *rfds,
|
inline static int Select_(int maxfd, fd_set *rfds,
|
||||||
fd_set *wfds, fd_set *efds, long timeout) {
|
fd_set *wfds, fd_set *efds, long timeout) { // NOLINT(*)
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
utils::Assert(maxfd < FD_SETSIZE, "maxdf must be smaller than FDSETSIZE");
|
utils::Assert(maxfd < FD_SETSIZE, "maxdf must be smaller than FDSETSIZE");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -2,7 +2,7 @@ export CC = gcc
|
|||||||
export CXX = g++
|
export CXX = g++
|
||||||
export MPICXX = mpicxx
|
export MPICXX = mpicxx
|
||||||
export LDFLAGS= -L../lib -pthread -lm -lrt
|
export LDFLAGS= -L../lib -pthread -lm -lrt
|
||||||
export CFLAGS = -Wall -O3 -msse2 -Wno-unknown-pragmas -fPIC -I../include -std=c++11
|
export CFLAGS = -Wall -O3 -msse2 -Wno-unknown-pragmas -fPIC -I../include -std=c++0x
|
||||||
|
|
||||||
# specify tensor path
|
# specify tensor path
|
||||||
BIN = speed_test model_recover local_recover lazy_recover
|
BIN = speed_test model_recover local_recover lazy_recover
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# this is a makefile used to show testcases of rabit
|
# this is a makefile used to show testcases of rabit
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
||||||
all:
|
all: model_recover_10_10k model_recover_10_10k_die_same
|
||||||
|
|
||||||
# this experiment test recovery with actually process exit, use keepalive to keep program alive
|
# this experiment test recovery with actually process exit, use keepalive to keep program alive
|
||||||
model_recover_10_10k:
|
model_recover_10_10k:
|
||||||
|
|||||||
@ -132,7 +132,7 @@ class Tracker:
|
|||||||
break
|
break
|
||||||
except socket.error:
|
except socket.error:
|
||||||
continue
|
continue
|
||||||
sock.listen(16)
|
sock.listen(128)
|
||||||
self.sock = sock
|
self.sock = sock
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
if hostIP == 'auto':
|
if hostIP == 'auto':
|
||||||
|
|||||||
@ -100,6 +100,7 @@
|
|||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
"""
|
"""
|
||||||
Python interface for rabit
|
Reliable Allreduce and Broadcast Library.
|
||||||
Reliable Allreduce and Broadcast Library
|
|
||||||
Author: Tianqi Chen
|
Author: Tianqi Chen
|
||||||
"""
|
"""
|
||||||
|
# pylint: disable=unused-argument,invalid-name,global-statement,dangerous-default-value,
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
import ctypes
|
import ctypes
|
||||||
import os
|
import os
|
||||||
@ -10,34 +11,41 @@ import sys
|
|||||||
import warnings
|
import warnings
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
# version information about the doc
|
||||||
|
__version__ = '1.0'
|
||||||
|
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
WRAPPER_PATH = os.path.dirname(__file__) + '\\..\\windows\\x64\\Release\\rabit_wrapper%s.dll'
|
WRAPPER_PATH = os.path.dirname(__file__) + '\\..\\windows\\x64\\Release\\rabit_wrapper%s.dll'
|
||||||
else:
|
else:
|
||||||
WRAPPER_PATH = os.path.dirname(__file__) + '/librabit_wrapper%s.so'
|
WRAPPER_PATH = os.path.dirname(__file__) + '/librabit_wrapper%s.so'
|
||||||
rbtlib = None
|
|
||||||
|
_LIB = None
|
||||||
|
|
||||||
# load in xgboost library
|
# load in xgboost library
|
||||||
def loadlib__(lib = 'standard'):
|
def _loadlib(lib='standard'):
|
||||||
global rbtlib
|
"""Load rabit library."""
|
||||||
if rbtlib != None:
|
global _LIB
|
||||||
warnings.Warn('rabit.int call was ignored because it has already been initialized', level = 2)
|
if _LIB != None:
|
||||||
|
warnings.warn('rabit.int call was ignored because it has'\
|
||||||
|
' already been initialized', level=2)
|
||||||
return
|
return
|
||||||
if lib == 'standard':
|
if lib == 'standard':
|
||||||
rbtlib = ctypes.cdll.LoadLibrary(WRAPPER_PATH % '')
|
_LIB = ctypes.cdll.LoadLibrary(WRAPPER_PATH % '')
|
||||||
elif lib == 'mock':
|
elif lib == 'mock':
|
||||||
rbtlib = ctypes.cdll.LoadLibrary(WRAPPER_PATH % '_mock')
|
_LIB = ctypes.cdll.LoadLibrary(WRAPPER_PATH % '_mock')
|
||||||
elif lib == 'mpi':
|
elif lib == 'mpi':
|
||||||
rbtlib = ctypes.cdll.LoadLibrary(WRAPPER_PATH % '_mpi')
|
_LIB = ctypes.cdll.LoadLibrary(WRAPPER_PATH % '_mpi')
|
||||||
else:
|
else:
|
||||||
raise Exception('unknown rabit lib %s, can be standard, mock, mpi' % lib)
|
raise Exception('unknown rabit lib %s, can be standard, mock, mpi' % lib)
|
||||||
rbtlib.RabitGetRank.restype = ctypes.c_int
|
_LIB.RabitGetRank.restype = ctypes.c_int
|
||||||
rbtlib.RabitGetWorldSize.restype = ctypes.c_int
|
_LIB.RabitGetWorldSize.restype = ctypes.c_int
|
||||||
rbtlib.RabitVersionNumber.restype = ctypes.c_int
|
_LIB.RabitVersionNumber.restype = ctypes.c_int
|
||||||
|
|
||||||
def unloadlib__():
|
def _unloadlib():
|
||||||
global rbtlib
|
"""Unload rabit library."""
|
||||||
del rbtlib
|
global _LIB
|
||||||
rbtlib = None
|
del _LIB
|
||||||
|
_LIB = None
|
||||||
|
|
||||||
# reduction operators
|
# reduction operators
|
||||||
MAX = 0
|
MAX = 0
|
||||||
@ -45,125 +53,118 @@ MIN = 1
|
|||||||
SUM = 2
|
SUM = 2
|
||||||
BITOR = 3
|
BITOR = 3
|
||||||
|
|
||||||
def check_err__():
|
def init(args=None, lib='standard'):
|
||||||
"""
|
"""Intialize the rabit module, call this once before using anything.
|
||||||
reserved function used to check error
|
|
||||||
"""
|
|
||||||
return
|
|
||||||
|
|
||||||
def init(args = sys.argv, lib = 'standard'):
|
Parameters
|
||||||
|
----------
|
||||||
|
args: list of str, optional
|
||||||
|
The list of arguments used to initialized the rabit
|
||||||
|
usually you need to pass in sys.argv.
|
||||||
|
Defaults to sys.argv when it is None.
|
||||||
|
lib: {'standard', 'mock', 'mpi'}
|
||||||
|
Type of library we want to load
|
||||||
"""
|
"""
|
||||||
intialize the rabit module, call this once before using anything
|
if args is None:
|
||||||
Arguments:
|
args = sys.argv
|
||||||
args: list(string) [default=sys.argv]
|
_loadlib(lib)
|
||||||
the list of arguments used to initialized the rabit
|
|
||||||
usually you need to pass in sys.argv
|
|
||||||
with_mock: boolean [default=False]
|
|
||||||
Whether initialize the mock test module
|
|
||||||
"""
|
|
||||||
loadlib__(lib)
|
|
||||||
arr = (ctypes.c_char_p * len(args))()
|
arr = (ctypes.c_char_p * len(args))()
|
||||||
arr[:] = args
|
arr[:] = args
|
||||||
rbtlib.RabitInit(len(args), arr)
|
_LIB.RabitInit(len(args), arr)
|
||||||
check_err__()
|
|
||||||
|
|
||||||
def finalize():
|
def finalize():
|
||||||
|
"""Finalize the rabit engine.
|
||||||
|
|
||||||
|
Call this function after you finished all jobs.
|
||||||
"""
|
"""
|
||||||
finalize the rabit engine, call this function after you finished all jobs
|
_LIB.RabitFinalize()
|
||||||
"""
|
_unloadlib()
|
||||||
rbtlib.RabitFinalize()
|
|
||||||
check_err__()
|
|
||||||
unloadlib__()
|
|
||||||
|
|
||||||
def get_rank():
|
def get_rank():
|
||||||
|
"""Get rank of current process.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
rank : int
|
||||||
|
Rank of current process.
|
||||||
"""
|
"""
|
||||||
Returns rank of current process
|
ret = _LIB.RabitGetRank()
|
||||||
"""
|
|
||||||
ret = rbtlib.RabitGetRank()
|
|
||||||
check_err__()
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def get_world_size():
|
def get_world_size():
|
||||||
|
"""Get total number workers.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
n : int
|
||||||
|
Total number of process.
|
||||||
"""
|
"""
|
||||||
Returns get total number of process
|
ret = _LIB.RabitGetWorldSize()
|
||||||
"""
|
|
||||||
ret = rbtlib.RabitGetWorldSize()
|
|
||||||
check_err__()
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def tracker_print(msg):
|
def tracker_print(msg):
|
||||||
"""
|
"""Print message to the tracker.
|
||||||
print message to the tracker
|
|
||||||
this function can be used to communicate the information of the progress
|
This function can be used to communicate the information of
|
||||||
to the tracker
|
the progress to the tracker
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
msg : str
|
||||||
|
The message to be printed to tracker.
|
||||||
"""
|
"""
|
||||||
if not isinstance(msg, str):
|
if not isinstance(msg, str):
|
||||||
msg = str(msg)
|
msg = str(msg)
|
||||||
rbtlib.RabitTrackerPrint(ctypes.c_char_p(msg).encode('utf-8'))
|
_LIB.RabitTrackerPrint(ctypes.c_char_p(msg).encode('utf-8'))
|
||||||
check_err__()
|
|
||||||
|
|
||||||
def get_processor_name():
|
def get_processor_name():
|
||||||
"""
|
"""Get the processor name.
|
||||||
Returns the name of processor(host)
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
name : str
|
||||||
|
the name of processor(host)
|
||||||
"""
|
"""
|
||||||
mxlen = 256
|
mxlen = 256
|
||||||
length = ctypes.c_ulong()
|
length = ctypes.c_ulong()
|
||||||
buf = ctypes.create_string_buffer(mxlen)
|
buf = ctypes.create_string_buffer(mxlen)
|
||||||
rbtlib.RabitGetProcessorName(buf, ctypes.byref(length),
|
_LIB.RabitGetProcessorName(buf, ctypes.byref(length), mxlen)
|
||||||
mxlen)
|
|
||||||
check_err__()
|
|
||||||
return buf.value
|
return buf.value
|
||||||
|
|
||||||
def broadcast(data, root):
|
def broadcast(data, root):
|
||||||
"""
|
"""Broadcast object from one node to all other nodes.
|
||||||
broadcast object from one node to all other nodes
|
|
||||||
this function will return the broadcasted object
|
|
||||||
|
|
||||||
Example: the following example broadcast hello from rank 0 to all other nodes
|
Parameters
|
||||||
```python
|
----------
|
||||||
rabit.init()
|
data : any type that can be pickled
|
||||||
n = 3
|
Input data, if current rank does not equal root, this can be None
|
||||||
rank = rabit.get_rank()
|
root : int
|
||||||
s = None
|
Rank of the node to broadcast data from.
|
||||||
if rank == 0:
|
|
||||||
s = {'hello world':100, 2:3}
|
|
||||||
print '@node[%d] before-broadcast: s=\"%s\"' % (rank, str(s))
|
|
||||||
s = rabit.broadcast(s, 0)
|
|
||||||
print '@node[%d] after-broadcast: s=\"%s\"' % (rank, str(s))
|
|
||||||
rabit.finalize()
|
|
||||||
```
|
|
||||||
|
|
||||||
Arguments:
|
Returns
|
||||||
data: anytype that can be pickled
|
-------
|
||||||
input data, if current rank does not equal root, this can be None
|
object : int
|
||||||
root: int
|
the result of broadcast.
|
||||||
rank of the node to broadcast data from
|
|
||||||
Returns:
|
|
||||||
the result of broadcast
|
|
||||||
"""
|
"""
|
||||||
rank = get_rank()
|
rank = get_rank()
|
||||||
length = ctypes.c_ulong()
|
length = ctypes.c_ulong()
|
||||||
if root == rank:
|
if root == rank:
|
||||||
assert data is not None, 'need to pass in data when broadcasting'
|
assert data is not None, 'need to pass in data when broadcasting'
|
||||||
s = pickle.dumps(data, protocol = pickle.HIGHEST_PROTOCOL)
|
s = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
|
||||||
length.value = len(s)
|
length.value = len(s)
|
||||||
# run first broadcast
|
# run first broadcast
|
||||||
rbtlib.RabitBroadcast(ctypes.byref(length),
|
_LIB.RabitBroadcast(ctypes.byref(length),
|
||||||
ctypes.sizeof(ctypes.c_ulong),
|
ctypes.sizeof(ctypes.c_ulong), root)
|
||||||
root)
|
|
||||||
check_err__()
|
|
||||||
if root != rank:
|
if root != rank:
|
||||||
dptr = (ctypes.c_char * length.value)()
|
dptr = (ctypes.c_char * length.value)()
|
||||||
# run second
|
# run second
|
||||||
rbtlib.RabitBroadcast(ctypes.cast(dptr, ctypes.c_void_p),
|
_LIB.RabitBroadcast(ctypes.cast(dptr, ctypes.c_void_p),
|
||||||
length.value, root)
|
length.value, root)
|
||||||
check_err__()
|
|
||||||
data = pickle.loads(dptr.raw)
|
data = pickle.loads(dptr.raw)
|
||||||
del dptr
|
del dptr
|
||||||
else:
|
else:
|
||||||
rbtlib.RabitBroadcast(ctypes.cast(ctypes.c_char_p(s), ctypes.c_void_p),
|
_LIB.RabitBroadcast(ctypes.cast(ctypes.c_char_p(s), ctypes.c_void_p),
|
||||||
length.value, root)
|
length.value, root)
|
||||||
check_err__()
|
|
||||||
del s
|
del s
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@ -179,20 +180,29 @@ DTYPE_ENUM__ = {
|
|||||||
np.dtype('float64') : 7
|
np.dtype('float64') : 7
|
||||||
}
|
}
|
||||||
|
|
||||||
def allreduce(data, op, prepare_fun = None):
|
def allreduce(data, op, prepare_fun=None):
|
||||||
"""
|
"""Perform allreduce, return the result.
|
||||||
perform allreduce, return the result, this function is not thread-safe
|
|
||||||
Arguments:
|
Parameters
|
||||||
data: numpy ndarray
|
----------
|
||||||
input data
|
data: numpy array
|
||||||
op: int
|
Input data.
|
||||||
reduction operators, can be MIN, MAX, SUM, BITOR
|
op: int
|
||||||
prepare_fun: lambda data
|
Reduction operators, can be MIN, MAX, SUM, BITOR
|
||||||
Lazy preprocessing function, if it is not None, prepare_fun(data)
|
prepare_fun: function
|
||||||
will be called by the function before performing allreduce, to intialize the data
|
Lazy preprocessing function, if it is not None, prepare_fun(data)
|
||||||
If the result of Allreduce can be recovered directly, then prepare_fun will NOT be called
|
will be called by the function before performing allreduce, to intialize the data
|
||||||
Returns:
|
If the result of Allreduce can be recovered directly,
|
||||||
the result of allreduce, have same shape as data
|
then prepare_fun will NOT be called
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
result : array_like
|
||||||
|
The result of allreduce, have same shape as data
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
This function is not thread-safe.
|
||||||
"""
|
"""
|
||||||
if not isinstance(data, np.ndarray):
|
if not isinstance(data, np.ndarray):
|
||||||
raise Exception('allreduce only takes in numpy.ndarray')
|
raise Exception('allreduce only takes in numpy.ndarray')
|
||||||
@ -202,21 +212,21 @@ def allreduce(data, op, prepare_fun = None):
|
|||||||
if buf.dtype not in DTYPE_ENUM__:
|
if buf.dtype not in DTYPE_ENUM__:
|
||||||
raise Exception('data type %s not supported' % str(buf.dtype))
|
raise Exception('data type %s not supported' % str(buf.dtype))
|
||||||
if prepare_fun is None:
|
if prepare_fun is None:
|
||||||
rbtlib.RabitAllreduce(buf.ctypes.data_as(ctypes.c_void_p),
|
_LIB.RabitAllreduce(buf.ctypes.data_as(ctypes.c_void_p),
|
||||||
buf.size, DTYPE_ENUM__[buf.dtype],
|
buf.size, DTYPE_ENUM__[buf.dtype],
|
||||||
op, None, None)
|
op, None, None)
|
||||||
else:
|
else:
|
||||||
PFUNC = ctypes.CFUNCTYPE(None, ctypes.c_void_p)
|
func_ptr = ctypes.CFUNCTYPE(None, ctypes.c_void_p)
|
||||||
def pfunc(args):
|
def pfunc(args):
|
||||||
|
"""prepare function."""
|
||||||
prepare_fun(data)
|
prepare_fun(data)
|
||||||
rbtlib.RabitAllreduce(buf.ctypes.data_as(ctypes.c_void_p),
|
_LIB.RabitAllreduce(buf.ctypes.data_as(ctypes.c_void_p),
|
||||||
buf.size, DTYPE_ENUM__[buf.dtype],
|
buf.size, DTYPE_ENUM__[buf.dtype],
|
||||||
op, PFUNC(pfunc), None)
|
op, func_ptr(pfunc), None)
|
||||||
check_err__()
|
|
||||||
return buf
|
return buf
|
||||||
|
|
||||||
|
|
||||||
def load_model__(ptr, length):
|
def _load_model(ptr, length):
|
||||||
"""
|
"""
|
||||||
Internal function used by the module,
|
Internal function used by the module,
|
||||||
unpickle a model from a buffer specified by ptr, length
|
unpickle a model from a buffer specified by ptr, length
|
||||||
@ -229,78 +239,89 @@ def load_model__(ptr, length):
|
|||||||
data = (ctypes.c_char * length).from_address(ctypes.addressof(ptr.contents))
|
data = (ctypes.c_char * length).from_address(ctypes.addressof(ptr.contents))
|
||||||
return pickle.loads(data.raw)
|
return pickle.loads(data.raw)
|
||||||
|
|
||||||
def load_checkpoint(with_local = False):
|
def load_checkpoint(with_local=False):
|
||||||
"""
|
"""Load latest check point.
|
||||||
load latest check point
|
|
||||||
Arguments:
|
Parameters
|
||||||
with_local: boolean [default = False]
|
----------
|
||||||
whether the checkpoint contains local model
|
with_local: bool, optional
|
||||||
Returns:
|
whether the checkpoint contains local model
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
tuple : tuple
|
||||||
if with_local: return (version, gobal_model, local_model)
|
if with_local: return (version, gobal_model, local_model)
|
||||||
else return (version, gobal_model)
|
else return (version, gobal_model)
|
||||||
if returned version == 0, this means no model has been CheckPointed
|
if returned version == 0, this means no model has been CheckPointed
|
||||||
and global_model, local_model returned will be None
|
and global_model, local_model returned will be None
|
||||||
"""
|
"""
|
||||||
gp = ctypes.POINTER(ctypes.c_char)()
|
gptr = ctypes.POINTER(ctypes.c_char)()
|
||||||
global_len = ctypes.c_ulong()
|
global_len = ctypes.c_ulong()
|
||||||
if with_local:
|
if with_local:
|
||||||
lp = ctypes.POINTER(ctypes.c_char)()
|
lptr = ctypes.POINTER(ctypes.c_char)()
|
||||||
local_len = ctypes.c_ulong()
|
local_len = ctypes.c_ulong()
|
||||||
version = rbtlib.RabitLoadCheckPoint(
|
version = _LIB.RabitLoadCheckPoint(
|
||||||
ctypes.byref(gp),
|
ctypes.byref(gptr),
|
||||||
ctypes.byref(global_len),
|
ctypes.byref(global_len),
|
||||||
ctypes.byref(lp),
|
ctypes.byref(lptr),
|
||||||
ctypes.byref(local_len))
|
ctypes.byref(local_len))
|
||||||
check_err__()
|
|
||||||
if version == 0:
|
if version == 0:
|
||||||
return (version, None, None)
|
return (version, None, None)
|
||||||
return (version,
|
return (version,
|
||||||
load_model__(gp, global_len.value),
|
_load_model(gptr, global_len.value),
|
||||||
load_model__(lp, local_len.value))
|
_load_model(lptr, local_len.value))
|
||||||
else:
|
else:
|
||||||
version = rbtlib.RabitLoadCheckPoint(
|
version = _LIB.RabitLoadCheckPoint(
|
||||||
ctypes.byref(gp),
|
ctypes.byref(gptr),
|
||||||
ctypes.byref(global_len),
|
ctypes.byref(global_len),
|
||||||
None, None)
|
None, None)
|
||||||
check_err__()
|
|
||||||
if version == 0:
|
if version == 0:
|
||||||
return (version, None)
|
return (version, None)
|
||||||
return (version,
|
return (version,
|
||||||
load_model__(gp, global_len.value))
|
_load_model(gptr, global_len.value))
|
||||||
|
|
||||||
def checkpoint(global_model, local_model = None):
|
def checkpoint(global_model, local_model=None):
|
||||||
"""
|
"""Checkpoint the model.
|
||||||
checkpoint the model, meaning we finished a stage of execution
|
|
||||||
every time we call check point, there is a version number which will increase by one
|
|
||||||
|
|
||||||
Arguments:
|
This means we finished a stage of execution.
|
||||||
global_model: anytype that can be pickled
|
Every time we call check point, there is a version number which will increase by one.
|
||||||
globally shared model/state when calling this function,
|
|
||||||
the caller need to gauranttees that global_model is the same in all nodes
|
Parameters
|
||||||
local_model: anytype that can be pickled
|
----------
|
||||||
local model, that is specific to current node/rank.
|
global_model: anytype that can be pickled
|
||||||
This can be None when no local state is needed.
|
globally shared model/state when calling this function,
|
||||||
local_model requires explicit replication of the model for fault-tolerance,
|
the caller need to gauranttees that global_model is the same in all nodes
|
||||||
which will bring replication cost in checkpoint function,
|
|
||||||
while global_model do not need explicit replication.
|
local_model: anytype that can be pickled
|
||||||
It is recommended to use global_model if possible
|
Local model, that is specific to current node/rank.
|
||||||
|
This can be None when no local state is needed.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
local_model requires explicit replication of the model for fault-tolerance.
|
||||||
|
This will bring replication cost in checkpoint function.
|
||||||
|
while global_model do not need explicit replication.
|
||||||
|
It is recommended to use global_model if possible.
|
||||||
"""
|
"""
|
||||||
sg = pickle.dumps(global_model)
|
sglobal = pickle.dumps(global_model)
|
||||||
if local_model is None:
|
if local_model is None:
|
||||||
rbtlib.RabitCheckPoint(sg, len(sg), None, 0)
|
_LIB.RabitCheckPoint(sglobal, len(sglobal), None, 0)
|
||||||
check_err__()
|
del sglobal
|
||||||
del sg;
|
|
||||||
else:
|
else:
|
||||||
sl = pickle.dumps(local_model)
|
slocal = pickle.dumps(local_model)
|
||||||
rbtlib.RabitCheckPoint(sg, len(sg), sl, len(sl))
|
_LIB.RabitCheckPoint(sglobal, len(sglobal), slocal, len(slocal))
|
||||||
check_err__()
|
del slocal
|
||||||
del sl; del sg;
|
del sglobal
|
||||||
|
|
||||||
def version_number():
|
def version_number():
|
||||||
|
"""Returns version number of current stored model.
|
||||||
|
|
||||||
|
This means how many calls to CheckPoint we made so far.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
version : int
|
||||||
|
Version number of currently stored model
|
||||||
"""
|
"""
|
||||||
Returns version number of current stored model,
|
ret = _LIB.RabitVersionNumber()
|
||||||
which means how many calls to CheckPoint we made so far
|
|
||||||
"""
|
|
||||||
ret = rbtlib.RabitVersionNumber()
|
|
||||||
check_err__()
|
|
||||||
return ret
|
return ret
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
// Copyright by Contributors
|
||||||
// implementations in ctypes
|
// implementations in ctypes
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#define _CRT_SECURE_NO_DEPRECATE
|
#define _CRT_SECURE_NO_DEPRECATE
|
||||||
@ -60,12 +61,12 @@ inline void Allreduce_(void *sendrecvbuf_,
|
|||||||
return;
|
return;
|
||||||
case kLong:
|
case kLong:
|
||||||
rabit::Allreduce<OP>
|
rabit::Allreduce<OP>
|
||||||
(static_cast<long*>(sendrecvbuf_),
|
(static_cast<long*>(sendrecvbuf_), // NOLINT(*)
|
||||||
count, prepare_fun, prepare_arg);
|
count, prepare_fun, prepare_arg);
|
||||||
return;
|
return;
|
||||||
case kULong:
|
case kULong:
|
||||||
rabit::Allreduce<OP>
|
rabit::Allreduce<OP>
|
||||||
(static_cast<unsigned long*>(sendrecvbuf_),
|
(static_cast<unsigned long*>(sendrecvbuf_), // NOLINT(*)
|
||||||
count, prepare_fun, prepare_arg);
|
count, prepare_fun, prepare_arg);
|
||||||
return;
|
return;
|
||||||
case kFloat:
|
case kFloat:
|
||||||
@ -179,7 +180,7 @@ extern "C" {
|
|||||||
if (s.length() > max_len) {
|
if (s.length() > max_len) {
|
||||||
s.resize(max_len - 1);
|
s.resize(max_len - 1);
|
||||||
}
|
}
|
||||||
strcpy(out_name, s.c_str());
|
strcpy(out_name, s.c_str()); // NOLINT(*)
|
||||||
*out_len = static_cast<rbt_ulong>(s.length());
|
*out_len = static_cast<rbt_ulong>(s.length());
|
||||||
}
|
}
|
||||||
void RabitBroadcast(void *sendrecv_data,
|
void RabitBroadcast(void *sendrecv_data,
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
#ifndef RABIT_WRAPPER_H_
|
|
||||||
#define RABIT_WRAPPER_H_
|
|
||||||
/*!
|
/*!
|
||||||
|
* Copyright by Contributors
|
||||||
* \file rabit_wrapper.h
|
* \file rabit_wrapper.h
|
||||||
* \author Tianqi Chen
|
* \author Tianqi Chen
|
||||||
* \brief a C style wrapper of rabit
|
* \brief a C style wrapper of rabit
|
||||||
* can be used to create wrapper of other languages
|
* can be used to create wrapper of other languages
|
||||||
*/
|
*/
|
||||||
|
#ifndef RABIT_WRAPPER_H_
|
||||||
|
#define RABIT_WRAPPER_H_
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define RABIT_DLL __declspec(dllexport)
|
#define RABIT_DLL __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define RABIT_DLL
|
#define RABIT_DLL
|
||||||
#endif
|
#endif
|
||||||
// manually define unsign long
|
// manually define unsign long
|
||||||
typedef unsigned long rbt_ulong;
|
typedef unsigned long rbt_ulong; // NOLINT(*)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -122,4 +123,4 @@ extern "C" {
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // C
|
} // C
|
||||||
#endif
|
#endif
|
||||||
#endif // XGBOOST_WRAPPER_H_
|
#endif // RABIT_WRAPPER_H_
|
||||||
|
|||||||
@ -3,8 +3,11 @@ import numpy as np
|
|||||||
import xgboost as xgb
|
import xgboost as xgb
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
import matplotlib
|
||||||
|
matplotlib.use('Agg')
|
||||||
|
|
||||||
dpath = 'demo/data/'
|
dpath = 'demo/data/'
|
||||||
|
rng = np.random.RandomState(1994)
|
||||||
|
|
||||||
class TestBasic(unittest.TestCase):
|
class TestBasic(unittest.TestCase):
|
||||||
|
|
||||||
@ -197,9 +200,6 @@ class TestBasic(unittest.TestCase):
|
|||||||
bst2 = xgb.Booster(model_file='xgb.model')
|
bst2 = xgb.Booster(model_file='xgb.model')
|
||||||
# plotting
|
# plotting
|
||||||
|
|
||||||
import matplotlib
|
|
||||||
matplotlib.use('Agg')
|
|
||||||
|
|
||||||
from matplotlib.axes import Axes
|
from matplotlib.axes import Axes
|
||||||
from graphviz import Digraph
|
from graphviz import Digraph
|
||||||
|
|
||||||
@ -220,7 +220,6 @@ class TestBasic(unittest.TestCase):
|
|||||||
for p in ax.patches:
|
for p in ax.patches:
|
||||||
assert p.get_facecolor() == (1.0, 0, 0, 1.0) # red
|
assert p.get_facecolor() == (1.0, 0, 0, 1.0) # red
|
||||||
|
|
||||||
|
|
||||||
ax = xgb.plot_importance(bst2, color=['r', 'r', 'b', 'b'],
|
ax = xgb.plot_importance(bst2, color=['r', 'r', 'b', 'b'],
|
||||||
title=None, xlabel=None, ylabel=None)
|
title=None, xlabel=None, ylabel=None)
|
||||||
assert isinstance(ax, Axes)
|
assert isinstance(ax, Axes)
|
||||||
@ -235,5 +234,63 @@ class TestBasic(unittest.TestCase):
|
|||||||
|
|
||||||
g = xgb.to_graphviz(bst2, num_trees=0)
|
g = xgb.to_graphviz(bst2, num_trees=0)
|
||||||
assert isinstance(g, Digraph)
|
assert isinstance(g, Digraph)
|
||||||
|
|
||||||
ax = xgb.plot_tree(bst2, num_trees=0)
|
ax = xgb.plot_tree(bst2, num_trees=0)
|
||||||
assert isinstance(ax, Axes)
|
assert isinstance(ax, Axes)
|
||||||
|
|
||||||
|
def test_importance_plot_lim(self):
|
||||||
|
np.random.seed(1)
|
||||||
|
dm = xgb.DMatrix(np.random.randn(100, 100), label=[0, 1]*50)
|
||||||
|
bst = xgb.train({}, dm)
|
||||||
|
assert len(bst.get_fscore()) == 71
|
||||||
|
ax = xgb.plot_importance(bst)
|
||||||
|
assert ax.get_xlim() == (0., 11.)
|
||||||
|
assert ax.get_ylim() == (-1., 71.)
|
||||||
|
|
||||||
|
ax = xgb.plot_importance(bst, xlim=(0, 5), ylim=(10, 71))
|
||||||
|
assert ax.get_xlim() == (0., 5.)
|
||||||
|
assert ax.get_ylim() == (10., 71.)
|
||||||
|
|
||||||
|
def test_sklearn_api(self):
|
||||||
|
from sklearn import datasets
|
||||||
|
from sklearn.cross_validation import train_test_split
|
||||||
|
|
||||||
|
np.random.seed(1)
|
||||||
|
|
||||||
|
iris = datasets.load_iris()
|
||||||
|
tr_d, te_d, tr_l, te_l = train_test_split(iris.data, iris.target, train_size=120)
|
||||||
|
|
||||||
|
classifier = xgb.XGBClassifier()
|
||||||
|
classifier.fit(tr_d, tr_l)
|
||||||
|
|
||||||
|
preds = classifier.predict(te_d)
|
||||||
|
labels = te_l
|
||||||
|
err = sum([1 for p, l in zip(preds, labels) if p != l]) / len(te_l)
|
||||||
|
# error must be smaller than 10%
|
||||||
|
assert err < 0.1
|
||||||
|
|
||||||
|
def test_sklearn_plotting(self):
|
||||||
|
from sklearn import datasets
|
||||||
|
iris = datasets.load_iris()
|
||||||
|
|
||||||
|
classifier = xgb.XGBClassifier()
|
||||||
|
classifier.fit(iris.data, iris.target)
|
||||||
|
|
||||||
|
import matplotlib
|
||||||
|
matplotlib.use('Agg')
|
||||||
|
|
||||||
|
from matplotlib.axes import Axes
|
||||||
|
from graphviz import Digraph
|
||||||
|
|
||||||
|
ax = xgb.plot_importance(classifier)
|
||||||
|
assert isinstance(ax, Axes)
|
||||||
|
assert ax.get_title() == 'Feature importance'
|
||||||
|
assert ax.get_xlabel() == 'F score'
|
||||||
|
assert ax.get_ylabel() == 'Features'
|
||||||
|
assert len(ax.patches) == 4
|
||||||
|
|
||||||
|
g = xgb.to_graphviz(classifier, num_trees=0)
|
||||||
|
assert isinstance(g, Digraph)
|
||||||
|
|
||||||
|
ax = xgb.plot_tree(classifier, num_trees=0)
|
||||||
|
assert isinstance(ax, Axes)
|
||||||
32
tests/python/test_early_stopping.py
Normal file
32
tests/python/test_early_stopping.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import xgboost as xgb
|
||||||
|
import numpy as np
|
||||||
|
from sklearn.datasets import load_digits
|
||||||
|
from sklearn.cross_validation import KFold, train_test_split
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
rng = np.random.RandomState(1994)
|
||||||
|
|
||||||
|
class TestEarlyStopping(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_early_stopping_nonparallel(self):
|
||||||
|
digits = load_digits(2)
|
||||||
|
X = digits['data']
|
||||||
|
y = digits['target']
|
||||||
|
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
|
||||||
|
clf1 = xgb.XGBClassifier()
|
||||||
|
clf1.fit(X_train, y_train, early_stopping_rounds=5, eval_metric="auc",
|
||||||
|
eval_set=[(X_test, y_test)])
|
||||||
|
clf2 = xgb.XGBClassifier()
|
||||||
|
clf2.fit(X_train, y_train, early_stopping_rounds=4, eval_metric="auc",
|
||||||
|
eval_set=[(X_test, y_test)])
|
||||||
|
# should be the same
|
||||||
|
assert clf1.best_score == clf2.best_score
|
||||||
|
assert clf1.best_score != 1
|
||||||
|
# check overfit
|
||||||
|
clf3 = xgb.XGBClassifier()
|
||||||
|
clf3.fit(X_train, y_train, early_stopping_rounds=10, eval_metric="auc",
|
||||||
|
eval_set=[(X_test, y_test)])
|
||||||
|
assert clf3.best_score == 1
|
||||||
|
|
||||||
|
# TODO: parallel test for early stopping
|
||||||
|
# TODO: comment out for now. Will re-visit later
|
||||||
@ -1,39 +1,80 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import xgboost as xgb
|
import xgboost as xgb
|
||||||
|
import unittest
|
||||||
|
|
||||||
dpath = 'demo/data/'
|
dpath = 'demo/data/'
|
||||||
dtrain = xgb.DMatrix(dpath + 'agaricus.txt.train')
|
dtrain = xgb.DMatrix(dpath + 'agaricus.txt.train')
|
||||||
dtest = xgb.DMatrix(dpath + 'agaricus.txt.test')
|
dtest = xgb.DMatrix(dpath + 'agaricus.txt.test')
|
||||||
|
|
||||||
def test_glm():
|
rng = np.random.RandomState(1994)
|
||||||
param = {'silent':1, 'objective':'binary:logistic', 'booster':'gblinear', 'alpha': 0.0001, 'lambda': 1 }
|
|
||||||
watchlist = [(dtest,'eval'), (dtrain,'train')]
|
|
||||||
num_round = 4
|
|
||||||
bst = xgb.train(param, dtrain, num_round, watchlist)
|
|
||||||
assert isinstance(bst, xgb.core.Booster)
|
|
||||||
preds = bst.predict(dtest)
|
|
||||||
labels = dtest.get_label()
|
|
||||||
err = sum(1 for i in range(len(preds)) if int(preds[i]>0.5)!=labels[i]) / float(len(preds))
|
|
||||||
assert err < 0.1
|
|
||||||
|
|
||||||
def test_custom_objective():
|
class TestModels(unittest.TestCase):
|
||||||
param = {'max_depth':2, 'eta':1, 'silent':1 }
|
|
||||||
watchlist = [(dtest,'eval'), (dtrain,'train')]
|
def test_glm(self):
|
||||||
num_round = 2
|
param = {'silent':1, 'objective':'binary:logistic', 'booster':'gblinear', 'alpha': 0.0001, 'lambda': 1 }
|
||||||
def logregobj(preds, dtrain):
|
watchlist = [(dtest,'eval'), (dtrain,'train')]
|
||||||
labels = dtrain.get_label()
|
num_round = 4
|
||||||
preds = 1.0 / (1.0 + np.exp(-preds))
|
bst = xgb.train(param, dtrain, num_round, watchlist)
|
||||||
grad = preds - labels
|
assert isinstance(bst, xgb.core.Booster)
|
||||||
hess = preds * (1.0-preds)
|
preds = bst.predict(dtest)
|
||||||
return grad, hess
|
labels = dtest.get_label()
|
||||||
def evalerror(preds, dtrain):
|
err = sum(1 for i in range(len(preds)) if int(preds[i]>0.5)!=labels[i]) / float(len(preds))
|
||||||
labels = dtrain.get_label()
|
assert err < 0.1
|
||||||
return 'error', float(sum(labels != (preds > 0.0))) / len(labels)
|
|
||||||
bst = xgb.train(param, dtrain, num_round, watchlist, logregobj, evalerror)
|
def test_eta_decay(self):
|
||||||
assert isinstance(bst, xgb.core.Booster)
|
param = {'max_depth':2, 'eta':1, 'silent':1, 'objective':'binary:logistic' }
|
||||||
preds = bst.predict(dtest)
|
watchlist = [(dtest,'eval'), (dtrain,'train')]
|
||||||
labels = dtest.get_label()
|
num_round = 2
|
||||||
err = sum(1 for i in range(len(preds)) if int(preds[i]>0.5)!=labels[i]) / float(len(preds))
|
# learning_rates as a list
|
||||||
assert err < 0.1
|
bst = xgb.train(param, dtrain, num_round, watchlist, learning_rates=[0.4, 0.3])
|
||||||
|
assert isinstance(bst, xgb.core.Booster)
|
||||||
|
|
||||||
|
# learning_rates as a customized decay function
|
||||||
|
def eta_decay(ithround, num_boost_round):
|
||||||
|
return num_boost_round / ithround
|
||||||
|
bst = xgb.train(param, dtrain, num_round, watchlist, learning_rates=eta_decay)
|
||||||
|
assert isinstance(bst, xgb.core.Booster)
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_objective(self):
|
||||||
|
param = {'max_depth':2, 'eta':1, 'silent':1 }
|
||||||
|
watchlist = [(dtest,'eval'), (dtrain,'train')]
|
||||||
|
num_round = 2
|
||||||
|
def logregobj(preds, dtrain):
|
||||||
|
labels = dtrain.get_label()
|
||||||
|
preds = 1.0 / (1.0 + np.exp(-preds))
|
||||||
|
grad = preds - labels
|
||||||
|
hess = preds * (1.0-preds)
|
||||||
|
return grad, hess
|
||||||
|
def evalerror(preds, dtrain):
|
||||||
|
labels = dtrain.get_label()
|
||||||
|
return 'error', float(sum(labels != (preds > 0.0))) / len(labels)
|
||||||
|
|
||||||
|
# test custom_objective in training
|
||||||
|
bst = xgb.train(param, dtrain, num_round, watchlist, logregobj, evalerror)
|
||||||
|
assert isinstance(bst, xgb.core.Booster)
|
||||||
|
preds = bst.predict(dtest)
|
||||||
|
labels = dtest.get_label()
|
||||||
|
err = sum(1 for i in range(len(preds)) if int(preds[i]>0.5)!=labels[i]) / float(len(preds))
|
||||||
|
assert err < 0.1
|
||||||
|
|
||||||
|
# test custom_objective in cross-validation
|
||||||
|
xgb.cv(param, dtrain, num_round, nfold = 5, seed = 0,
|
||||||
|
obj = logregobj, feval=evalerror)
|
||||||
|
|
||||||
|
def test_fpreproc(self):
|
||||||
|
param = {'max_depth':2, 'eta':1, 'silent':1, 'objective':'binary:logistic'}
|
||||||
|
num_round = 2
|
||||||
|
def fpreproc(dtrain, dtest, param):
|
||||||
|
label = dtrain.get_label()
|
||||||
|
ratio = float(np.sum(label == 0)) / np.sum(label==1)
|
||||||
|
param['scale_pos_weight'] = ratio
|
||||||
|
return (dtrain, dtest, param)
|
||||||
|
xgb.cv(param, dtrain, num_round, nfold=5,
|
||||||
|
metrics={'auc'}, seed = 0, fpreproc = fpreproc)
|
||||||
|
|
||||||
|
def test_show_stdv(self):
|
||||||
|
param = {'max_depth':2, 'eta':1, 'silent':1, 'objective':'binary:logistic'}
|
||||||
|
num_round = 2
|
||||||
|
xgb.cv(param, dtrain, num_round, nfold=5,
|
||||||
|
metrics={'error'}, seed = 0, show_stdv = False)
|
||||||
|
|||||||
52
tests/python/test_training_continuation.py
Normal file
52
tests/python/test_training_continuation.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import xgboost as xgb
|
||||||
|
import numpy as np
|
||||||
|
from sklearn.cross_validation import KFold, train_test_split
|
||||||
|
from sklearn.metrics import mean_squared_error
|
||||||
|
from sklearn.grid_search import GridSearchCV
|
||||||
|
from sklearn.datasets import load_iris, load_digits, load_boston
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
rng = np.random.RandomState(1337)
|
||||||
|
|
||||||
|
class TestTrainingContinuation(unittest.TestCase):
|
||||||
|
|
||||||
|
xgb_params = {
|
||||||
|
'colsample_bytree': 0.7,
|
||||||
|
'silent': 1,
|
||||||
|
'nthread': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_training_continuation(self):
|
||||||
|
digits = load_digits(2)
|
||||||
|
X = digits['data']
|
||||||
|
y = digits['target']
|
||||||
|
|
||||||
|
dtrain = xgb.DMatrix(X,label=y)
|
||||||
|
|
||||||
|
gbdt_01 = xgb.train(self.xgb_params, dtrain, num_boost_round=10)
|
||||||
|
ntrees_01 = len(gbdt_01.get_dump())
|
||||||
|
assert ntrees_01 == 10
|
||||||
|
|
||||||
|
gbdt_02 = xgb.train(self.xgb_params, dtrain, num_boost_round=0)
|
||||||
|
gbdt_02.save_model('xgb_tc.model')
|
||||||
|
|
||||||
|
gbdt_02a = xgb.train(self.xgb_params, dtrain, num_boost_round=10, xgb_model=gbdt_02)
|
||||||
|
gbdt_02b = xgb.train(self.xgb_params, dtrain, num_boost_round=10, xgb_model="xgb_tc.model")
|
||||||
|
ntrees_02a = len(gbdt_02a.get_dump())
|
||||||
|
ntrees_02b = len(gbdt_02b.get_dump())
|
||||||
|
assert ntrees_02a == 10
|
||||||
|
assert ntrees_02b == 10
|
||||||
|
assert mean_squared_error(y, gbdt_01.predict(dtrain)) == mean_squared_error(y, gbdt_02a.predict(dtrain))
|
||||||
|
assert mean_squared_error(y, gbdt_01.predict(dtrain)) == mean_squared_error(y, gbdt_02b.predict(dtrain))
|
||||||
|
|
||||||
|
gbdt_03 = xgb.train(self.xgb_params, dtrain, num_boost_round=3)
|
||||||
|
gbdt_03.save_model('xgb_tc.model')
|
||||||
|
|
||||||
|
gbdt_03a = xgb.train(self.xgb_params, dtrain, num_boost_round=7, xgb_model=gbdt_03)
|
||||||
|
gbdt_03b = xgb.train(self.xgb_params, dtrain, num_boost_round=7, xgb_model="xgb_tc.model")
|
||||||
|
ntrees_03a = len(gbdt_03a.get_dump())
|
||||||
|
ntrees_03b = len(gbdt_03b.get_dump())
|
||||||
|
assert ntrees_03a == 10
|
||||||
|
assert ntrees_03b == 10
|
||||||
|
assert mean_squared_error(y, gbdt_03a.predict(dtrain)) == mean_squared_error(y, gbdt_03b.predict(dtrain))
|
||||||
|
|
||||||
64
tests/python/test_with_sklearn.py
Normal file
64
tests/python/test_with_sklearn.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import xgboost as xgb
|
||||||
|
import numpy as np
|
||||||
|
from sklearn.cross_validation import KFold, train_test_split
|
||||||
|
from sklearn.metrics import mean_squared_error
|
||||||
|
from sklearn.grid_search import GridSearchCV
|
||||||
|
from sklearn.datasets import load_iris, load_digits, load_boston
|
||||||
|
|
||||||
|
rng = np.random.RandomState(1994)
|
||||||
|
|
||||||
|
def test_binary_classification():
|
||||||
|
digits = load_digits(2)
|
||||||
|
y = digits['target']
|
||||||
|
X = digits['data']
|
||||||
|
kf = KFold(y.shape[0], n_folds=2, shuffle=True, random_state=rng)
|
||||||
|
for train_index, test_index in kf:
|
||||||
|
xgb_model = xgb.XGBClassifier().fit(X[train_index],y[train_index])
|
||||||
|
preds = xgb_model.predict(X[test_index])
|
||||||
|
labels = y[test_index]
|
||||||
|
err = sum(1 for i in range(len(preds)) if int(preds[i]>0.5)!=labels[i]) / float(len(preds))
|
||||||
|
assert err < 0.1
|
||||||
|
|
||||||
|
def test_multiclass_classification():
|
||||||
|
iris = load_iris()
|
||||||
|
y = iris['target']
|
||||||
|
X = iris['data']
|
||||||
|
kf = KFold(y.shape[0], n_folds=2, shuffle=True, random_state=rng)
|
||||||
|
for train_index, test_index in kf:
|
||||||
|
xgb_model = xgb.XGBClassifier().fit(X[train_index],y[train_index])
|
||||||
|
preds = xgb_model.predict(X[test_index])
|
||||||
|
# test other params in XGBClassifier().fit
|
||||||
|
preds2 = xgb_model.predict(X[test_index], output_margin=True, ntree_limit=3)
|
||||||
|
preds3 = xgb_model.predict(X[test_index], output_margin=True, ntree_limit=0)
|
||||||
|
preds4 = xgb_model.predict(X[test_index], output_margin=False, ntree_limit=3)
|
||||||
|
labels = y[test_index]
|
||||||
|
err = sum(1 for i in range(len(preds)) if int(preds[i]>0.5)!=labels[i]) / float(len(preds))
|
||||||
|
assert err < 0.4
|
||||||
|
|
||||||
|
def test_boston_housing_regression():
|
||||||
|
boston = load_boston()
|
||||||
|
y = boston['target']
|
||||||
|
X = boston['data']
|
||||||
|
kf = KFold(y.shape[0], n_folds=2, shuffle=True, random_state=rng)
|
||||||
|
for train_index, test_index in kf:
|
||||||
|
xgb_model = xgb.XGBRegressor().fit(X[train_index],y[train_index])
|
||||||
|
preds = xgb_model.predict(X[test_index])
|
||||||
|
# test other params in XGBRegressor().fit
|
||||||
|
preds2 = xgb_model.predict(X[test_index], output_margin=True, ntree_limit=3)
|
||||||
|
preds3 = xgb_model.predict(X[test_index], output_margin=True, ntree_limit=0)
|
||||||
|
preds4 = xgb_model.predict(X[test_index], output_margin=False, ntree_limit=3)
|
||||||
|
labels = y[test_index]
|
||||||
|
assert mean_squared_error(preds, labels) < 25
|
||||||
|
|
||||||
|
def test_parameter_tuning():
|
||||||
|
boston = load_boston()
|
||||||
|
y = boston['target']
|
||||||
|
X = boston['data']
|
||||||
|
xgb_model = xgb.XGBRegressor()
|
||||||
|
clf = GridSearchCV(xgb_model,
|
||||||
|
{'max_depth': [2,4,6],
|
||||||
|
'n_estimators': [50,100,200]}, verbose=1)
|
||||||
|
clf.fit(X,y)
|
||||||
|
assert clf.best_score_ < 0.7
|
||||||
|
assert clf.best_params_ == {'n_estimators': 100, 'max_depth': 4}
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user