De-duplicate GPU parameters. (#4454)
* Only define `gpu_id` and `n_gpus` in `LearnerTrainParam` * Pass LearnerTrainParam through XGBoost vid factory method. * Disable all GPU usage when GPU related parameters are not specified (fixes XGBoost choosing GPU over aggressively). * Test learner train param io. * Fix gpu pickling.
This commit is contained in:
parent
a3fedbeaa8
commit
c589eff941
@ -5,8 +5,8 @@
|
||||
* \author Hyunsu Philip Cho
|
||||
*/
|
||||
|
||||
#ifndef XGBOOST_COMMON_ENUM_CLASS_PARAM_H_
|
||||
#define XGBOOST_COMMON_ENUM_CLASS_PARAM_H_
|
||||
#ifndef XGBOOST_ENUM_CLASS_PARAM_H_
|
||||
#define XGBOOST_ENUM_CLASS_PARAM_H_
|
||||
|
||||
#include <dmlc/parameter.h>
|
||||
#include <string>
|
||||
@ -78,4 +78,4 @@ class FieldEntry<EnumClass> : public FieldEntry<int> { \
|
||||
} /* namespace parameter */ \
|
||||
} /* namespace dmlc */
|
||||
|
||||
#endif // XGBOOST_COMMON_ENUM_CLASS_PARAM_H_
|
||||
#endif // XGBOOST_ENUM_CLASS_PARAM_H_
|
||||
@ -9,15 +9,18 @@
|
||||
#define XGBOOST_GBM_H_
|
||||
|
||||
#include <dmlc/registry.h>
|
||||
#include <xgboost/base.h>
|
||||
#include <xgboost/data.h>
|
||||
#include <xgboost/objective.h>
|
||||
#include <xgboost/feature_map.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "./base.h"
|
||||
#include "./data.h"
|
||||
#include "./objective.h"
|
||||
#include "./feature_map.h"
|
||||
|
||||
#include "../../src/common/host_device_vector.h"
|
||||
|
||||
namespace xgboost {
|
||||
@ -25,6 +28,9 @@ namespace xgboost {
|
||||
* \brief interface of gradient boosting model.
|
||||
*/
|
||||
class GradientBooster {
|
||||
protected:
|
||||
LearnerTrainParam const* learner_param_;
|
||||
|
||||
public:
|
||||
/*! \brief virtual destructor */
|
||||
virtual ~GradientBooster() = default;
|
||||
@ -149,6 +155,7 @@ class GradientBooster {
|
||||
*/
|
||||
static GradientBooster* Create(
|
||||
const std::string& name,
|
||||
LearnerTrainParam const* gparam,
|
||||
const std::vector<std::shared_ptr<DMatrix> >& cache_mats,
|
||||
bst_float base_margin);
|
||||
};
|
||||
|
||||
86
include/xgboost/generic_parameters.h
Normal file
86
include/xgboost/generic_parameters.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*!
|
||||
* Copyright 2014-2019 by Contributors
|
||||
* \file learner.cc
|
||||
*/
|
||||
#ifndef XGBOOST_GENERIC_PARAMETERS_H_
|
||||
#define XGBOOST_GENERIC_PARAMETERS_H_
|
||||
|
||||
#include <dmlc/parameter.h>
|
||||
#include <xgboost/enum_class_param.h>
|
||||
|
||||
namespace xgboost {
|
||||
enum class TreeMethod : int {
|
||||
kAuto = 0, kApprox = 1, kExact = 2, kHist = 3,
|
||||
kGPUExact = 4, kGPUHist = 5
|
||||
};
|
||||
|
||||
enum class DataSplitMode : int {
|
||||
kAuto = 0, kCol = 1, kRow = 2
|
||||
};
|
||||
} // namespace xgboost
|
||||
|
||||
DECLARE_FIELD_ENUM_CLASS(xgboost::TreeMethod);
|
||||
DECLARE_FIELD_ENUM_CLASS(xgboost::DataSplitMode);
|
||||
|
||||
namespace xgboost {
|
||||
struct LearnerTrainParam : public dmlc::Parameter<LearnerTrainParam> {
|
||||
// stored random seed
|
||||
int seed;
|
||||
// whether seed the PRNG each iteration
|
||||
bool seed_per_iteration;
|
||||
// data split mode, can be row, col, or none.
|
||||
DataSplitMode dsplit;
|
||||
// tree construction method
|
||||
TreeMethod tree_method;
|
||||
// number of threads to use if OpenMP is enabled
|
||||
// if equals 0, use system default
|
||||
int nthread;
|
||||
// flag to disable default metric
|
||||
int disable_default_eval_metric;
|
||||
// primary device.
|
||||
int gpu_id;
|
||||
// number of devices to use, -1 implies using all available devices.
|
||||
int n_gpus;
|
||||
|
||||
// declare parameters
|
||||
DMLC_DECLARE_PARAMETER(LearnerTrainParam) {
|
||||
DMLC_DECLARE_FIELD(seed).set_default(0).describe(
|
||||
"Random number seed during training.");
|
||||
DMLC_DECLARE_FIELD(seed_per_iteration)
|
||||
.set_default(false)
|
||||
.describe(
|
||||
"Seed PRNG determnisticly via iterator number, "
|
||||
"this option will be switched on automatically on distributed "
|
||||
"mode.");
|
||||
DMLC_DECLARE_FIELD(dsplit)
|
||||
.set_default(DataSplitMode::kAuto)
|
||||
.add_enum("auto", DataSplitMode::kAuto)
|
||||
.add_enum("col", DataSplitMode::kCol)
|
||||
.add_enum("row", DataSplitMode::kRow)
|
||||
.describe("Data split mode for distributed training.");
|
||||
DMLC_DECLARE_FIELD(tree_method)
|
||||
.set_default(TreeMethod::kAuto)
|
||||
.add_enum("auto", TreeMethod::kAuto)
|
||||
.add_enum("approx", TreeMethod::kApprox)
|
||||
.add_enum("exact", TreeMethod::kExact)
|
||||
.add_enum("hist", TreeMethod::kHist)
|
||||
.add_enum("gpu_exact", TreeMethod::kGPUExact)
|
||||
.add_enum("gpu_hist", TreeMethod::kGPUHist)
|
||||
.describe("Choice of tree construction method.");
|
||||
DMLC_DECLARE_FIELD(nthread).set_default(0).describe(
|
||||
"Number of threads to use.");
|
||||
DMLC_DECLARE_FIELD(disable_default_eval_metric)
|
||||
.set_default(0)
|
||||
.describe("flag to disable default metric. Set to >0 to disable");
|
||||
DMLC_DECLARE_FIELD(gpu_id)
|
||||
.set_default(0)
|
||||
.describe("The primary GPU device ordinal.");
|
||||
DMLC_DECLARE_FIELD(n_gpus)
|
||||
.set_default(0)
|
||||
.set_lower_bound(-1)
|
||||
.describe("Number of GPUs to use for multi-gpu algorithms.");
|
||||
}
|
||||
};
|
||||
} // namespace xgboost
|
||||
|
||||
#endif // XGBOOST_GENERIC_PARAMETERS_H_
|
||||
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright 2015 by Contributors
|
||||
* Copyright 2015-2019 by Contributors
|
||||
* \file learner.h
|
||||
* \brief Learner interface that integrates objective, gbm and evaluation together.
|
||||
* This is the user facing XGBoost training module.
|
||||
@ -9,15 +9,18 @@
|
||||
#define XGBOOST_LEARNER_H_
|
||||
|
||||
#include <rabit/rabit.h>
|
||||
|
||||
#include <xgboost/base.h>
|
||||
#include <xgboost/gbm.h>
|
||||
#include <xgboost/metric.h>
|
||||
#include <xgboost/objective.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
|
||||
#include <utility>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "./base.h"
|
||||
#include "./gbm.h"
|
||||
#include "./metric.h"
|
||||
#include "./objective.h"
|
||||
|
||||
namespace xgboost {
|
||||
/*!
|
||||
@ -144,6 +147,8 @@ class Learner : public rabit::Serializable {
|
||||
* \return vector of attribute name strings.
|
||||
*/
|
||||
virtual std::vector<std::string> GetAttrNames() const = 0;
|
||||
|
||||
virtual LearnerTrainParam const& GetLearnerTrainParameter() const = 0;
|
||||
/*!
|
||||
* \return whether the model allow lazy checkpoint in rabit.
|
||||
*/
|
||||
@ -195,6 +200,8 @@ class Learner : public rabit::Serializable {
|
||||
std::unique_ptr<GradientBooster> gbm_;
|
||||
/*! \brief The evaluation metrics used to evaluate the model. */
|
||||
std::vector<std::unique_ptr<Metric> > metrics_;
|
||||
/*! \brief Training parameter. */
|
||||
LearnerTrainParam tparam_;
|
||||
};
|
||||
|
||||
// implementation of inline functions.
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include <dmlc/registry.h>
|
||||
#include <xgboost/base.h>
|
||||
#include <xgboost/data.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@ -18,6 +19,9 @@ namespace xgboost {
|
||||
* \brief interface of linear updater
|
||||
*/
|
||||
class LinearUpdater {
|
||||
protected:
|
||||
LearnerTrainParam const* learner_param_;
|
||||
|
||||
public:
|
||||
/*! \brief virtual destructor */
|
||||
virtual ~LinearUpdater() = default;
|
||||
@ -45,7 +49,7 @@ class LinearUpdater {
|
||||
* \brief Create a linear updater given name
|
||||
* \param name Name of the linear updater.
|
||||
*/
|
||||
static LinearUpdater* Create(const std::string& name);
|
||||
static LinearUpdater* Create(const std::string& name, LearnerTrainParam const*);
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@ -8,13 +8,15 @@
|
||||
#define XGBOOST_METRIC_H_
|
||||
|
||||
#include <dmlc/registry.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
#include <xgboost/data.h>
|
||||
#include <xgboost/base.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "./data.h"
|
||||
#include "./base.h"
|
||||
#include "../../src/common/host_device_vector.h"
|
||||
|
||||
namespace xgboost {
|
||||
@ -23,6 +25,9 @@ namespace xgboost {
|
||||
* This has nothing to do with training, but merely act as evaluation purpose.
|
||||
*/
|
||||
class Metric {
|
||||
protected:
|
||||
LearnerTrainParam const* tparam_;
|
||||
|
||||
public:
|
||||
/*!
|
||||
* \brief Configure the Metric with the specified parameters.
|
||||
@ -63,7 +68,7 @@ class Metric {
|
||||
* and the name will be matched in the registry.
|
||||
* \return the created metric.
|
||||
*/
|
||||
static Metric* Create(const std::string& name);
|
||||
static Metric* Create(const std::string& name, LearnerTrainParam const* tparam);
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@ -8,19 +8,24 @@
|
||||
#define XGBOOST_OBJECTIVE_H_
|
||||
|
||||
#include <dmlc/registry.h>
|
||||
#include <xgboost/base.h>
|
||||
#include <xgboost/data.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include "./data.h"
|
||||
#include "./base.h"
|
||||
#include "../../src/common/host_device_vector.h"
|
||||
|
||||
#include "../../src/common/host_device_vector.h"
|
||||
|
||||
namespace xgboost {
|
||||
|
||||
/*! \brief interface of objective function */
|
||||
class ObjFunction {
|
||||
protected:
|
||||
LearnerTrainParam const* tparam_;
|
||||
|
||||
public:
|
||||
/*! \brief virtual destructor */
|
||||
virtual ~ObjFunction() = default;
|
||||
@ -77,9 +82,10 @@ class ObjFunction {
|
||||
}
|
||||
/*!
|
||||
* \brief Create an objective function according to name.
|
||||
* \param tparam Generic parameters.
|
||||
* \param name Name of the objective.
|
||||
*/
|
||||
static ObjFunction* Create(const std::string& name);
|
||||
static ObjFunction* Create(const std::string& name, LearnerTrainParam const* tparam);
|
||||
};
|
||||
|
||||
// implementing configure.
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
#include <xgboost/base.h>
|
||||
#include <xgboost/data.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
@ -38,6 +39,9 @@ namespace xgboost {
|
||||
*/
|
||||
|
||||
class Predictor {
|
||||
protected:
|
||||
LearnerTrainParam const* learner_param_;
|
||||
|
||||
public:
|
||||
virtual ~Predictor() = default;
|
||||
|
||||
@ -170,7 +174,7 @@ class Predictor {
|
||||
*
|
||||
*/
|
||||
|
||||
static Predictor* Create(std::string name);
|
||||
static Predictor* Create(std::string const& name, LearnerTrainParam const*);
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright 2014 by Contributors
|
||||
* Copyright 2014-2019 by Contributors
|
||||
* \file tree_updater.h
|
||||
* \brief General primitive for tree learning,
|
||||
* Updating a collection of trees given the information.
|
||||
@ -9,13 +9,16 @@
|
||||
#define XGBOOST_TREE_UPDATER_H_
|
||||
|
||||
#include <dmlc/registry.h>
|
||||
#include <xgboost/base.h>
|
||||
#include <xgboost/data.h>
|
||||
#include <xgboost/tree_model.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include "./base.h"
|
||||
#include "./data.h"
|
||||
#include "./tree_model.h"
|
||||
|
||||
#include "../../src/common/host_device_vector.h"
|
||||
|
||||
namespace xgboost {
|
||||
@ -23,6 +26,9 @@ namespace xgboost {
|
||||
* \brief interface of tree update module, that performs update of a tree.
|
||||
*/
|
||||
class TreeUpdater {
|
||||
protected:
|
||||
LearnerTrainParam const* tparam_;
|
||||
|
||||
public:
|
||||
/*! \brief virtual destructor */
|
||||
virtual ~TreeUpdater() = default;
|
||||
@ -63,7 +69,7 @@ class TreeUpdater {
|
||||
* \brief Create a tree updater given name
|
||||
* \param name Name of the tree updater.
|
||||
*/
|
||||
static TreeUpdater* Create(const std::string& name);
|
||||
static TreeUpdater* Create(const std::string& name, LearnerTrainParam const* tparam);
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
/*!
|
||||
* Copyright 2015-2018 by Contributors
|
||||
* Copyright 2015-2019 by Contributors
|
||||
* \file common.cc
|
||||
* \brief Enable all kinds of global variables in common.
|
||||
*/
|
||||
#include <dmlc/thread_local.h>
|
||||
#include <xgboost/logging.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "./random.h"
|
||||
@ -29,4 +30,39 @@ int AllVisibleImpl::AllVisible() {
|
||||
}
|
||||
#endif // !defined(XGBOOST_USE_CUDA)
|
||||
|
||||
constexpr GPUSet::GpuIdType GPUSet::kAll;
|
||||
|
||||
GPUSet GPUSet::All(GpuIdType gpu_id, GpuIdType n_gpus, int32_t n_rows) {
|
||||
CHECK_GE(gpu_id, 0) << "gpu_id must be >= 0.";
|
||||
CHECK_GE(n_gpus, -1) << "n_gpus must be >= -1.";
|
||||
|
||||
GpuIdType const n_devices_visible = AllVisible().Size();
|
||||
if (n_devices_visible == 0 || n_gpus == 0 || n_rows == 0) {
|
||||
LOG(DEBUG) << "Runing on CPU.";
|
||||
return Empty();
|
||||
}
|
||||
|
||||
GpuIdType const n_available_devices = n_devices_visible - gpu_id;
|
||||
|
||||
if (n_gpus == kAll) { // Use all devices starting from `gpu_id'.
|
||||
CHECK(gpu_id < n_devices_visible)
|
||||
<< "\ngpu_id should be less than number of visible devices.\ngpu_id: "
|
||||
<< gpu_id
|
||||
<< ", number of visible devices: "
|
||||
<< n_devices_visible;
|
||||
GpuIdType n_devices =
|
||||
n_available_devices < n_rows ? n_available_devices : n_rows;
|
||||
LOG(DEBUG) << "GPU ID: " << gpu_id << ", Number of GPUs: " << n_devices;
|
||||
return Range(gpu_id, n_devices);
|
||||
} else { // Use devices in ( gpu_id, gpu_id + n_gpus ).
|
||||
CHECK_LE(n_gpus, n_available_devices)
|
||||
<< "Starting from gpu id: " << gpu_id << ", there are only "
|
||||
<< n_available_devices << " available devices, while n_gpus is set to: "
|
||||
<< n_gpus;
|
||||
GpuIdType n_devices = n_gpus < n_rows ? n_gpus : n_rows;
|
||||
LOG(DEBUG) << "GPU ID: " << gpu_id << ", Number of GPUs: " << n_devices;
|
||||
return Range(gpu_id, n_devices);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xgboost
|
||||
|
||||
@ -135,8 +135,8 @@ class Range {
|
||||
Iterator begin_;
|
||||
Iterator end_;
|
||||
};
|
||||
|
||||
} // namespace common
|
||||
|
||||
struct AllVisibleImpl {
|
||||
static int AllVisible();
|
||||
};
|
||||
@ -160,33 +160,7 @@ class GPUSet {
|
||||
}
|
||||
/*! \brief n_gpus and num_rows both are upper bounds. */
|
||||
static GPUSet All(GpuIdType gpu_id, GpuIdType n_gpus,
|
||||
GpuIdType num_rows = std::numeric_limits<GpuIdType>::max()) {
|
||||
CHECK_GE(gpu_id, 0) << "gpu_id must be >= 0.";
|
||||
CHECK_GE(n_gpus, -1) << "n_gpus must be >= -1.";
|
||||
|
||||
GpuIdType const n_devices_visible = AllVisible().Size();
|
||||
if (n_devices_visible == 0 || n_gpus == 0) { return Empty(); }
|
||||
|
||||
GpuIdType const n_available_devices = n_devices_visible - gpu_id;
|
||||
|
||||
if (n_gpus == kAll) { // Use all devices starting from `gpu_id'.
|
||||
CHECK(gpu_id < n_devices_visible)
|
||||
<< "\ngpu_id should be less than number of visible devices.\ngpu_id: "
|
||||
<< gpu_id
|
||||
<< ", number of visible devices: "
|
||||
<< n_devices_visible;
|
||||
GpuIdType n_devices =
|
||||
n_available_devices < num_rows ? n_available_devices : num_rows;
|
||||
return Range(gpu_id, n_devices);
|
||||
} else { // Use devices in ( gpu_id, gpu_id + n_gpus ).
|
||||
CHECK_LE(n_gpus, n_available_devices)
|
||||
<< "Starting from gpu id: " << gpu_id << ", there are only "
|
||||
<< n_available_devices << " available devices, while n_gpus is set to: "
|
||||
<< n_gpus;
|
||||
GpuIdType n_devices = n_gpus < num_rows ? n_gpus : num_rows;
|
||||
return Range(gpu_id, n_devices);
|
||||
}
|
||||
}
|
||||
GpuIdType num_rows = std::numeric_limits<GpuIdType>::max());
|
||||
|
||||
static GPUSet AllVisible() {
|
||||
GpuIdType n = AllVisibleImpl::AllVisible();
|
||||
|
||||
@ -383,8 +383,8 @@ struct GPUSketcher {
|
||||
hmat->Init(&sketches, param_.max_bin);
|
||||
}
|
||||
|
||||
GPUSketcher(tree::TrainParam param, size_t n_rows) : param_(std::move(param)) {
|
||||
dist_ = GPUDistribution::Block(GPUSet::All(param_.gpu_id, param_.n_gpus, n_rows));
|
||||
GPUSketcher(tree::TrainParam param, GPUSet const& devices) : param_(std::move(param)) {
|
||||
dist_ = GPUDistribution::Block(devices);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -395,8 +395,9 @@ struct GPUSketcher {
|
||||
|
||||
void DeviceSketch
|
||||
(const SparsePage& batch, const MetaInfo& info,
|
||||
const tree::TrainParam& param, HistCutMatrix* hmat, int gpu_batch_nrows) {
|
||||
GPUSketcher sketcher(param, info.num_row_);
|
||||
const tree::TrainParam& param, HistCutMatrix* hmat, int gpu_batch_nrows,
|
||||
GPUSet const& devices) {
|
||||
GPUSketcher sketcher(param, devices);
|
||||
sketcher.Sketch(batch, info, hmat, gpu_batch_nrows);
|
||||
}
|
||||
|
||||
|
||||
@ -118,7 +118,8 @@ struct HistCutMatrix {
|
||||
/*! \brief Builds the cut matrix on the GPU */
|
||||
void DeviceSketch
|
||||
(const SparsePage& batch, const MetaInfo& info,
|
||||
const tree::TrainParam& param, HistCutMatrix* hmat, int gpu_batch_nrows);
|
||||
const tree::TrainParam& param, HistCutMatrix* hmat, int gpu_batch_nrows,
|
||||
GPUSet const& devices);
|
||||
|
||||
/*!
|
||||
* \brief A single row in global histogram index.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright 2017 XGBoost contributors
|
||||
* Copyright 2017-2019 XGBoost contributors
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@ -62,7 +62,7 @@ class GBLinear : public GradientBooster {
|
||||
model_.param.InitAllowUnknown(cfg);
|
||||
}
|
||||
param_.InitAllowUnknown(cfg);
|
||||
updater_.reset(LinearUpdater::Create(param_.updater));
|
||||
updater_.reset(LinearUpdater::Create(param_.updater, learner_param_));
|
||||
updater_->Init(cfg);
|
||||
monitor_.Init("GBLinear");
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
#include <dmlc/io.h>
|
||||
#include <dmlc/parameter.h>
|
||||
#include <xgboost/base.h>
|
||||
#include <xgboost/feature_map.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
@ -13,13 +13,16 @@ DMLC_REGISTRY_ENABLE(::xgboost::GradientBoosterReg);
|
||||
namespace xgboost {
|
||||
GradientBooster* GradientBooster::Create(
|
||||
const std::string& name,
|
||||
LearnerTrainParam const* learner_param,
|
||||
const std::vector<std::shared_ptr<DMatrix> >& cache_mats,
|
||||
bst_float base_margin) {
|
||||
auto *e = ::dmlc::Registry< ::xgboost::GradientBoosterReg>::Get()->Find(name);
|
||||
if (e == nullptr) {
|
||||
LOG(FATAL) << "Unknown gbm type " << name;
|
||||
}
|
||||
return (e->body)(cache_mats, base_margin);
|
||||
auto p_bst = (e->body)(cache_mats, base_margin);
|
||||
p_bst->learner_param_ = learner_param;
|
||||
return p_bst;
|
||||
}
|
||||
|
||||
} // namespace xgboost
|
||||
|
||||
@ -147,7 +147,7 @@ class GBTree : public GradientBooster {
|
||||
}
|
||||
|
||||
// configure predictor
|
||||
predictor_ = std::unique_ptr<Predictor>(Predictor::Create(tparam_.predictor));
|
||||
predictor_ = std::unique_ptr<Predictor>(Predictor::Create(tparam_.predictor, learner_param_));
|
||||
predictor_->Init(cfg, cache_);
|
||||
monitor_.Init("GBTree");
|
||||
}
|
||||
@ -252,7 +252,7 @@ class GBTree : public GradientBooster {
|
||||
std::string tval = tparam_.updater_seq;
|
||||
std::vector<std::string> ups = common::Split(tval, ',');
|
||||
for (const std::string& pstr : ups) {
|
||||
std::unique_ptr<TreeUpdater> up(TreeUpdater::Create(pstr.c_str()));
|
||||
std::unique_ptr<TreeUpdater> up(TreeUpdater::Create(pstr.c_str(), learner_param_));
|
||||
up->Init(this->cfg_);
|
||||
updaters_.push_back(std::move(up));
|
||||
}
|
||||
|
||||
189
src/learner.cc
189
src/learner.cc
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright 2014 by Contributors
|
||||
* Copyright 2014-2019 by Contributors
|
||||
* \file learner.cc
|
||||
* \brief Implementation of learning algorithm.
|
||||
* \author Tianqi Chen
|
||||
@ -8,6 +8,7 @@
|
||||
#include <dmlc/timer.h>
|
||||
#include <xgboost/learner.h>
|
||||
#include <xgboost/logging.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
@ -20,22 +21,12 @@
|
||||
#include "./common/host_device_vector.h"
|
||||
#include "./common/io.h"
|
||||
#include "./common/random.h"
|
||||
#include "./common/enum_class_param.h"
|
||||
#include "./common/timer.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const char* kMaxDeltaStepDefaultValue = "0.7";
|
||||
|
||||
enum class TreeMethod : int {
|
||||
kAuto = 0, kApprox = 1, kExact = 2, kHist = 3,
|
||||
kGPUExact = 4, kGPUHist = 5
|
||||
};
|
||||
|
||||
enum class DataSplitMode : int {
|
||||
kAuto = 0, kCol = 1, kRow = 2
|
||||
};
|
||||
|
||||
inline bool IsFloat(const std::string& str) {
|
||||
std::stringstream ss(str);
|
||||
float f;
|
||||
@ -58,9 +49,6 @@ inline std::string RenderParamVal(const std::string& str) {
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
DECLARE_FIELD_ENUM_CLASS(TreeMethod);
|
||||
DECLARE_FIELD_ENUM_CLASS(DataSplitMode);
|
||||
|
||||
namespace xgboost {
|
||||
// implementation of base learner.
|
||||
bool Learner::AllowLazyCheckPoint() const {
|
||||
@ -108,56 +96,6 @@ struct LearnerModelParam : public dmlc::Parameter<LearnerModelParam> {
|
||||
}
|
||||
};
|
||||
|
||||
struct LearnerTrainParam : public dmlc::Parameter<LearnerTrainParam> {
|
||||
// stored random seed
|
||||
int seed;
|
||||
// whether seed the PRNG each iteration
|
||||
bool seed_per_iteration;
|
||||
// data split mode, can be row, col, or none.
|
||||
DataSplitMode dsplit;
|
||||
// tree construction method
|
||||
TreeMethod tree_method;
|
||||
// internal test flag
|
||||
std::string test_flag;
|
||||
// number of threads to use if OpenMP is enabled
|
||||
// if equals 0, use system default
|
||||
int nthread;
|
||||
// flag to disable default metric
|
||||
int disable_default_eval_metric;
|
||||
// declare parameters
|
||||
DMLC_DECLARE_PARAMETER(LearnerTrainParam) {
|
||||
DMLC_DECLARE_FIELD(seed).set_default(0).describe(
|
||||
"Random number seed during training.");
|
||||
DMLC_DECLARE_FIELD(seed_per_iteration)
|
||||
.set_default(false)
|
||||
.describe(
|
||||
"Seed PRNG determnisticly via iterator number, "
|
||||
"this option will be switched on automatically on distributed "
|
||||
"mode.");
|
||||
DMLC_DECLARE_FIELD(dsplit)
|
||||
.set_default(DataSplitMode::kAuto)
|
||||
.add_enum("auto", DataSplitMode::kAuto)
|
||||
.add_enum("col", DataSplitMode::kCol)
|
||||
.add_enum("row", DataSplitMode::kRow)
|
||||
.describe("Data split mode for distributed training.");
|
||||
DMLC_DECLARE_FIELD(tree_method)
|
||||
.set_default(TreeMethod::kAuto)
|
||||
.add_enum("auto", TreeMethod::kAuto)
|
||||
.add_enum("approx", TreeMethod::kApprox)
|
||||
.add_enum("exact", TreeMethod::kExact)
|
||||
.add_enum("hist", TreeMethod::kHist)
|
||||
.add_enum("gpu_exact", TreeMethod::kGPUExact)
|
||||
.add_enum("gpu_hist", TreeMethod::kGPUHist)
|
||||
.describe("Choice of tree construction method.");
|
||||
DMLC_DECLARE_FIELD(test_flag).set_default("").describe(
|
||||
"Internal test flag");
|
||||
DMLC_DECLARE_FIELD(nthread).set_default(0).describe(
|
||||
"Number of threads to use.");
|
||||
DMLC_DECLARE_FIELD(disable_default_eval_metric)
|
||||
.set_default(0)
|
||||
.describe("flag to disable default metric. Set to >0 to disable");
|
||||
}
|
||||
};
|
||||
|
||||
DMLC_REGISTER_PARAMETER(LearnerModelParam);
|
||||
DMLC_REGISTER_PARAMETER(LearnerTrainParam);
|
||||
@ -237,6 +175,29 @@ class LearnerImpl : public Learner {
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureObjective() {
|
||||
if (cfg_.count("num_class") != 0) {
|
||||
cfg_["num_output_group"] = cfg_["num_class"];
|
||||
if (atoi(cfg_["num_class"].c_str()) > 1 && cfg_.count("objective") == 0) {
|
||||
cfg_["objective"] = "multi:softmax";
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg_.find("max_delta_step") == cfg_.cend() &&
|
||||
cfg_.find("objective") != cfg_.cend() &&
|
||||
cfg_["objective"] == "count:poisson") {
|
||||
cfg_["max_delta_step"] = kMaxDeltaStepDefaultValue;
|
||||
}
|
||||
|
||||
if (cfg_.count("objective") == 0) {
|
||||
cfg_["objective"] = "reg:squarederror";
|
||||
}
|
||||
if (cfg_.count("booster") == 0) {
|
||||
cfg_["booster"] = "gbtree";
|
||||
}
|
||||
}
|
||||
|
||||
// Configuration before data is known.
|
||||
void Configure(
|
||||
const std::vector<std::pair<std::string, std::string> >& args) override {
|
||||
// add to configurations
|
||||
@ -252,7 +213,7 @@ class LearnerImpl : public Learner {
|
||||
return m->Name() != kv.second;
|
||||
};
|
||||
if (std::all_of(metrics_.begin(), metrics_.end(), dup_check)) {
|
||||
metrics_.emplace_back(Metric::Create(kv.second));
|
||||
metrics_.emplace_back(Metric::Create(kv.second, &tparam_));
|
||||
mparam_.contain_eval_metrics = 1;
|
||||
}
|
||||
} else {
|
||||
@ -268,27 +229,11 @@ class LearnerImpl : public Learner {
|
||||
if (tparam_.dsplit == DataSplitMode::kAuto && rabit::IsDistributed()) {
|
||||
tparam_.dsplit = DataSplitMode::kRow;
|
||||
}
|
||||
if (cfg_.count("num_class") != 0) {
|
||||
cfg_["num_output_group"] = cfg_["num_class"];
|
||||
if (atoi(cfg_["num_class"].c_str()) > 1 && cfg_.count("objective") == 0) {
|
||||
cfg_["objective"] = "multi:softmax";
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg_.count("max_delta_step") == 0 && cfg_.count("objective") != 0 &&
|
||||
cfg_["objective"] == "count:poisson") {
|
||||
cfg_["max_delta_step"] = kMaxDeltaStepDefaultValue;
|
||||
}
|
||||
|
||||
if (cfg_.count("objective") == 0) {
|
||||
cfg_["objective"] = "reg:squarederror";
|
||||
}
|
||||
if (cfg_.count("booster") == 0) {
|
||||
cfg_["booster"] = "gbtree";
|
||||
}
|
||||
|
||||
ConfigureObjective();
|
||||
ConfigureUpdaters();
|
||||
|
||||
// FIXME(trivialfis): So which one should go first? Init or Configure?
|
||||
if (!this->ModelInitialized()) {
|
||||
mparam_.InitAllowUnknown(args);
|
||||
name_obj_ = cfg_["objective"];
|
||||
@ -315,7 +260,27 @@ class LearnerImpl : public Learner {
|
||||
|
||||
void InitModel() override { this->LazyInitModel(); }
|
||||
|
||||
// Configuration can only be done after data is known
|
||||
void ConfigurationWithKnownData(DMatrix* dmat) {
|
||||
CHECK(ModelInitialized())
|
||||
<< "Always call InitModel or Load before any evaluation.";
|
||||
this->ValidateDMatrix(dmat);
|
||||
// Configure GPU parameters
|
||||
// FIXME(trivialfis): How do we know dependent parameters are all set?
|
||||
if (tparam_.tree_method == TreeMethod::kGPUHist ||
|
||||
tparam_.tree_method == TreeMethod::kGPUExact ||
|
||||
(cfg_.find("updater") != cfg_.cend() && cfg_.at("updater") == "gpu_coord_descent") ||
|
||||
(cfg_.find("predictor") != cfg_.cend() &&
|
||||
cfg_.at("predictor") == "gpu_predictor")) {
|
||||
if (cfg_.find("n_gpus") == cfg_.cend()) {
|
||||
tparam_.n_gpus = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load(dmlc::Stream* fi) override {
|
||||
tparam_ = LearnerTrainParam();
|
||||
tparam_.Init(std::vector<std::pair<std::string, std::string>>{});
|
||||
// TODO(tqchen) mark deprecation of old format.
|
||||
common::PeekableInStream fp(fi);
|
||||
// backward compatible header check.
|
||||
@ -352,8 +317,9 @@ class LearnerImpl : public Learner {
|
||||
}
|
||||
CHECK(fi->Read(&name_gbm_)) << "BoostLearner: wrong model format";
|
||||
// duplicated code with LazyInitModel
|
||||
obj_.reset(ObjFunction::Create(name_obj_));
|
||||
gbm_.reset(GradientBooster::Create(name_gbm_, cache_, mparam_.base_score));
|
||||
obj_.reset(ObjFunction::Create(name_obj_, &tparam_));
|
||||
gbm_.reset(GradientBooster::Create(name_gbm_, &tparam_,
|
||||
cache_, mparam_.base_score));
|
||||
gbm_->Load(fi);
|
||||
if (mparam_.contain_extra_attrs != 0) {
|
||||
std::vector<std::pair<std::string, std::string> > attr;
|
||||
@ -380,14 +346,13 @@ class LearnerImpl : public Learner {
|
||||
<< " * JVM packages: bst.setParam(\""
|
||||
<< saved_param << "\", [new value])";
|
||||
}
|
||||
#else
|
||||
if (saved_param == "predictor" && kv.second == "gpu_predictor") {
|
||||
LOG(INFO) << "Parameter 'predictor' will be set to 'cpu_predictor' "
|
||||
<< "since XGBoost wasn't compiled with GPU support.";
|
||||
#endif // XGBOOST_USE_CUDA
|
||||
// NO visiable GPU on current environment
|
||||
if (GPUSet::AllVisible().Size() == 0 &&
|
||||
(saved_param == "predictor" && kv.second == "gpu_predictor")) {
|
||||
cfg_["predictor"] = "cpu_predictor";
|
||||
kv.second = "cpu_predictor";
|
||||
}
|
||||
#endif // XGBOOST_USE_CUDA
|
||||
}
|
||||
}
|
||||
attributes_ =
|
||||
@ -402,7 +367,8 @@ class LearnerImpl : public Learner {
|
||||
std::vector<std::string> metr;
|
||||
fi->Read(&metr);
|
||||
for (auto name : metr) {
|
||||
metrics_.emplace_back(Metric::Create(name));
|
||||
metrics_.emplace_back(
|
||||
Metric::Create(name, &tparam_));
|
||||
}
|
||||
}
|
||||
cfg_["num_class"] = common::ToString(mparam_.num_class);
|
||||
@ -475,14 +441,11 @@ class LearnerImpl : public Learner {
|
||||
void UpdateOneIter(int iter, DMatrix* train) override {
|
||||
monitor_.Start("UpdateOneIter");
|
||||
|
||||
// TODO(trivialfis): Merge the duplicated code with BoostOneIter
|
||||
CHECK(ModelInitialized())
|
||||
<< "Always call InitModel or LoadModel before update";
|
||||
if (tparam_.seed_per_iteration || rabit::IsDistributed()) {
|
||||
common::GlobalRandom().seed(tparam_.seed * kRandSeedMagic + iter);
|
||||
}
|
||||
this->ValidateDMatrix(train);
|
||||
this->PerformTreeMethodHeuristic(train);
|
||||
this->ConfigurationWithKnownData(train);
|
||||
|
||||
monitor_.Start("PredictRaw");
|
||||
this->PredictRaw(train, &preds_[train]);
|
||||
@ -497,14 +460,11 @@ class LearnerImpl : public Learner {
|
||||
void BoostOneIter(int iter, DMatrix* train,
|
||||
HostDeviceVector<GradientPair>* in_gpair) override {
|
||||
monitor_.Start("BoostOneIter");
|
||||
|
||||
CHECK(ModelInitialized())
|
||||
<< "Always call InitModel or LoadModel before boost.";
|
||||
if (tparam_.seed_per_iteration || rabit::IsDistributed()) {
|
||||
common::GlobalRandom().seed(tparam_.seed * kRandSeedMagic + iter);
|
||||
}
|
||||
this->ValidateDMatrix(train);
|
||||
this->PerformTreeMethodHeuristic(train);
|
||||
this->ConfigurationWithKnownData(train);
|
||||
|
||||
gbm_->DoBoost(train, in_gpair);
|
||||
monitor_.Stop("BoostOneIter");
|
||||
@ -513,14 +473,16 @@ class LearnerImpl : public Learner {
|
||||
std::string EvalOneIter(int iter, const std::vector<DMatrix*>& data_sets,
|
||||
const std::vector<std::string>& data_names) override {
|
||||
monitor_.Start("EvalOneIter");
|
||||
|
||||
std::ostringstream os;
|
||||
os << '[' << iter << ']' << std::setiosflags(std::ios::fixed);
|
||||
if (metrics_.size() == 0 && tparam_.disable_default_eval_metric <= 0) {
|
||||
metrics_.emplace_back(Metric::Create(obj_->DefaultEvalMetric()));
|
||||
metrics_.emplace_back(Metric::Create(obj_->DefaultEvalMetric(), &tparam_));
|
||||
metrics_.back()->Configure(cfg_.begin(), cfg_.end());
|
||||
}
|
||||
for (size_t i = 0; i < data_sets.size(); ++i) {
|
||||
DMatrix * dmat = data_sets[i];
|
||||
this->ConfigurationWithKnownData(dmat);
|
||||
this->PredictRaw(data_sets[i], &preds_[dmat]);
|
||||
obj_->EvalTransform(&preds_[dmat]);
|
||||
for (auto& ev : metrics_) {
|
||||
@ -562,10 +524,15 @@ class LearnerImpl : public Learner {
|
||||
return out;
|
||||
}
|
||||
|
||||
LearnerTrainParam const& GetLearnerTrainParameter() const override {
|
||||
return tparam_;
|
||||
}
|
||||
|
||||
std::pair<std::string, bst_float> Evaluate(DMatrix* data,
|
||||
std::string metric) {
|
||||
if (metric == "auto") metric = obj_->DefaultEvalMetric();
|
||||
std::unique_ptr<Metric> ev(Metric::Create(metric.c_str()));
|
||||
std::unique_ptr<Metric> ev(Metric::Create(metric.c_str(), &tparam_));
|
||||
this->ConfigurationWithKnownData(data);
|
||||
this->PredictRaw(data, &preds_[data]);
|
||||
obj_->EvalTransform(&preds_[data]);
|
||||
return std::make_pair(metric,
|
||||
@ -577,6 +544,10 @@ class LearnerImpl : public Learner {
|
||||
HostDeviceVector<bst_float>* out_preds, unsigned ntree_limit,
|
||||
bool pred_leaf, bool pred_contribs, bool approx_contribs,
|
||||
bool pred_interactions) const override {
|
||||
bool multiple_predictions = static_cast<int>(pred_leaf) +
|
||||
static_cast<int>(pred_interactions) +
|
||||
static_cast<int>(pred_contribs);
|
||||
CHECK_LE(multiple_predictions, 1) << "Perform one kind of prediction at a time.";
|
||||
if (pred_contribs) {
|
||||
gbm_->PredictContribution(data, &out_preds->HostVector(), ntree_limit, approx_contribs);
|
||||
} else if (pred_interactions) {
|
||||
@ -628,7 +599,7 @@ class LearnerImpl : public Learner {
|
||||
// things are okay, do nothing
|
||||
break;
|
||||
case TreeMethod::kExact:
|
||||
LOG(CONSOLE) << "Tree method was set to be "
|
||||
LOG(WARNING) << "Tree method was set to be "
|
||||
<< "exact"
|
||||
<< "', but only 'approx' and 'hist' is available for distributed "
|
||||
"training. The `tree_method` parameter is now being "
|
||||
@ -643,11 +614,11 @@ class LearnerImpl : public Learner {
|
||||
<< static_cast<int>(current_tree_method) << ") detected";
|
||||
}
|
||||
if (current_tree_method != TreeMethod::kHist) {
|
||||
LOG(CONSOLE) << "Tree method is automatically selected to be 'approx'"
|
||||
LOG(WARNING) << "Tree method is automatically selected to be 'approx'"
|
||||
" for distributed training.";
|
||||
tparam_.tree_method = TreeMethod::kApprox;
|
||||
} else {
|
||||
LOG(CONSOLE) << "Tree method is specified to be 'hist'"
|
||||
LOG(WARNING) << "Tree method is specified to be 'hist'"
|
||||
" for distributed training.";
|
||||
tparam_.tree_method = TreeMethod::kHist;
|
||||
}
|
||||
@ -701,7 +672,7 @@ class LearnerImpl : public Learner {
|
||||
|
||||
// return whether model is already initialized.
|
||||
inline bool ModelInitialized() const { return gbm_ != nullptr; }
|
||||
// lazily initialize the model if it haven't yet been initialized.
|
||||
// lazily initialize the model based on configuration if it haven't yet been initialized.
|
||||
inline void LazyInitModel() {
|
||||
if (this->ModelInitialized()) return;
|
||||
// estimate feature bound
|
||||
@ -725,13 +696,15 @@ class LearnerImpl : public Learner {
|
||||
// setup
|
||||
cfg_["num_feature"] = common::ToString(mparam_.num_feature);
|
||||
CHECK(obj_ == nullptr && gbm_ == nullptr);
|
||||
obj_.reset(ObjFunction::Create(name_obj_));
|
||||
obj_.reset(ObjFunction::Create(name_obj_, &tparam_));
|
||||
obj_->Configure(cfg_.begin(), cfg_.end());
|
||||
// reset the base score
|
||||
mparam_.base_score = obj_->ProbToMargin(mparam_.base_score);
|
||||
gbm_.reset(GradientBooster::Create(name_gbm_, cache_, mparam_.base_score));
|
||||
gbm_.reset(GradientBooster::Create(name_gbm_, &tparam_,
|
||||
cache_, mparam_.base_score));
|
||||
gbm_->Configure(cfg_.begin(), cfg_.end());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief get un-transformed prediction
|
||||
* \param data training data matrix
|
||||
@ -761,8 +734,6 @@ class LearnerImpl : public Learner {
|
||||
|
||||
// model parameter
|
||||
LearnerModelParam mparam_;
|
||||
// training parameter
|
||||
LearnerTrainParam tparam_;
|
||||
// configurations
|
||||
std::map<std::string, std::string> cfg_;
|
||||
// attributes
|
||||
|
||||
@ -9,7 +9,9 @@
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
#include "xgboost/data.h"
|
||||
#include "./param.h"
|
||||
#include "../gbm/gblinear_model.h"
|
||||
#include "../common/random.h"
|
||||
|
||||
namespace xgboost {
|
||||
|
||||
@ -11,12 +11,14 @@ DMLC_REGISTRY_ENABLE(::xgboost::LinearUpdaterReg);
|
||||
|
||||
namespace xgboost {
|
||||
|
||||
LinearUpdater* LinearUpdater::Create(const std::string& name) {
|
||||
LinearUpdater* LinearUpdater::Create(const std::string& name, LearnerTrainParam const* lparam) {
|
||||
auto *e = ::dmlc::Registry< ::xgboost::LinearUpdaterReg>::Get()->Find(name);
|
||||
if (e == nullptr) {
|
||||
LOG(FATAL) << "Unknown linear updater " << name;
|
||||
}
|
||||
return (e->body)();
|
||||
auto p_linear = (e->body)();
|
||||
p_linear->learner_param_ = lparam;
|
||||
return p_linear;
|
||||
}
|
||||
|
||||
} // namespace xgboost
|
||||
|
||||
@ -28,8 +28,6 @@ struct LinearTrainParam : public dmlc::Parameter<LinearTrainParam> {
|
||||
/*! \brief regularization weight for L1 norm */
|
||||
float reg_alpha;
|
||||
int feature_selector;
|
||||
int n_gpus;
|
||||
int gpu_id;
|
||||
// declare parameters
|
||||
DMLC_DECLARE_PARAMETER(LinearTrainParam) {
|
||||
DMLC_DECLARE_FIELD(learning_rate)
|
||||
@ -52,10 +50,6 @@ struct LinearTrainParam : public dmlc::Parameter<LinearTrainParam> {
|
||||
.add_enum("greedy", kGreedy)
|
||||
.add_enum("random", kRandom)
|
||||
.describe("Feature selection or ordering method.");
|
||||
DMLC_DECLARE_FIELD(n_gpus).set_default(1).describe(
|
||||
"Number of devices to use.");
|
||||
DMLC_DECLARE_FIELD(gpu_id).set_default(0).describe(
|
||||
"Primary device ordinal.");
|
||||
// alias of parameters
|
||||
DMLC_DECLARE_ALIAS(learning_rate, eta);
|
||||
DMLC_DECLARE_ALIAS(reg_lambda, lambda);
|
||||
|
||||
@ -164,7 +164,7 @@ class GPUCoordinateUpdater : public LinearUpdater {
|
||||
const gbm::GBLinearModelParam &model_param) {
|
||||
if (!shards_.empty()) return;
|
||||
|
||||
dist_ = GPUDistribution::Block(GPUSet::All(tparam_.gpu_id, tparam_.n_gpus,
|
||||
dist_ = GPUDistribution::Block(GPUSet::All(learner_param_->gpu_id, learner_param_->n_gpus,
|
||||
p_fmat->Info().num_row_));
|
||||
auto devices = dist_.Devices();
|
||||
|
||||
|
||||
@ -314,11 +314,6 @@ struct EvalEWiseBase : public Metric {
|
||||
explicit EvalEWiseBase(char const* policy_param) :
|
||||
policy_{policy_param}, reducer_{policy_} {}
|
||||
|
||||
void Configure(
|
||||
const std::vector<std::pair<std::string, std::string> >& args) override {
|
||||
param_.InitAllowUnknown(args);
|
||||
}
|
||||
|
||||
bst_float Eval(const HostDeviceVector<bst_float>& preds,
|
||||
const MetaInfo& info,
|
||||
bool distributed) override {
|
||||
@ -328,7 +323,7 @@ struct EvalEWiseBase : public Metric {
|
||||
<< "hint: use merror or mlogloss for multi-class classification";
|
||||
const auto ndata = static_cast<omp_ulong>(info.labels_.Size());
|
||||
// Dealing with ndata < n_gpus.
|
||||
GPUSet devices = GPUSet::All(param_.gpu_id, param_.n_gpus, ndata);
|
||||
GPUSet devices = GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, ndata);
|
||||
|
||||
auto result =
|
||||
reducer_.Reduce(devices, info.weights_, info.labels_, preds);
|
||||
@ -347,8 +342,6 @@ struct EvalEWiseBase : public Metric {
|
||||
private:
|
||||
Policy policy_;
|
||||
|
||||
MetricParam param_;
|
||||
|
||||
ElementWiseMetricsReduction<Policy> reducer_;
|
||||
};
|
||||
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
/*!
|
||||
* Copyright 2015 by Contributors
|
||||
* Copyright 2015-2019 by Contributors
|
||||
* \file metric_registry.cc
|
||||
* \brief Registry of objective functions.
|
||||
*/
|
||||
#include <xgboost/metric.h>
|
||||
#include <dmlc/registry.h>
|
||||
|
||||
#include "metric_common.h"
|
||||
#include <xgboost/metric.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
|
||||
namespace dmlc {
|
||||
DMLC_REGISTRY_ENABLE(::xgboost::MetricReg);
|
||||
}
|
||||
|
||||
namespace xgboost {
|
||||
Metric* Metric::Create(const std::string& name) {
|
||||
Metric* Metric::Create(const std::string& name, LearnerTrainParam const* tparam) {
|
||||
std::string buf = name;
|
||||
std::string prefix = name;
|
||||
auto pos = buf.find('@');
|
||||
@ -22,21 +21,24 @@ Metric* Metric::Create(const std::string& name) {
|
||||
if (e == nullptr) {
|
||||
LOG(FATAL) << "Unknown metric function " << name;
|
||||
}
|
||||
return (e->body)(nullptr);
|
||||
auto p_metric = (e->body)(nullptr);
|
||||
p_metric->tparam_ = tparam;
|
||||
return p_metric;
|
||||
} else {
|
||||
std::string prefix = buf.substr(0, pos);
|
||||
auto *e = ::dmlc::Registry< ::xgboost::MetricReg>::Get()->Find(prefix.c_str());
|
||||
if (e == nullptr) {
|
||||
LOG(FATAL) << "Unknown metric function " << name;
|
||||
}
|
||||
return (e->body)(buf.substr(pos + 1, buf.length()).c_str());
|
||||
auto p_metric = (e->body)(buf.substr(pos + 1, buf.length()).c_str());
|
||||
p_metric->tparam_ = tparam;
|
||||
return p_metric;
|
||||
}
|
||||
}
|
||||
} // namespace xgboost
|
||||
|
||||
namespace xgboost {
|
||||
namespace metric {
|
||||
DMLC_REGISTER_PARAMETER(MetricParam);
|
||||
|
||||
// List of files that will be force linked in static links.
|
||||
DMLC_REGISTRY_LINK_TAG(elementwise_metric);
|
||||
|
||||
@ -11,20 +11,6 @@
|
||||
namespace xgboost {
|
||||
namespace metric {
|
||||
|
||||
// Created exclusively for GPU.
|
||||
struct MetricParam : public dmlc::Parameter<MetricParam> {
|
||||
int n_gpus;
|
||||
int gpu_id;
|
||||
DMLC_DECLARE_PARAMETER(MetricParam) {
|
||||
DMLC_DECLARE_FIELD(n_gpus).set_default(1).set_lower_bound(GPUSet::kAll)
|
||||
.describe("Number of GPUs to use for multi-gpu algorithms.");
|
||||
DMLC_DECLARE_FIELD(gpu_id)
|
||||
.set_lower_bound(0)
|
||||
.set_default(0)
|
||||
.describe("gpu to use for objective function evaluation");
|
||||
};
|
||||
};
|
||||
|
||||
class PackedReduceResult {
|
||||
double residue_sum_;
|
||||
double weights_sum_;
|
||||
|
||||
@ -168,11 +168,6 @@ class MultiClassMetricsReduction {
|
||||
*/
|
||||
template<typename Derived>
|
||||
struct EvalMClassBase : public Metric {
|
||||
void Configure(
|
||||
const std::vector<std::pair<std::string, std::string> >& args) override {
|
||||
param_.InitAllowUnknown(args);
|
||||
}
|
||||
|
||||
bst_float Eval(const HostDeviceVector<bst_float> &preds,
|
||||
const MetaInfo &info,
|
||||
bool distributed) override {
|
||||
@ -185,7 +180,7 @@ struct EvalMClassBase : public Metric {
|
||||
<< " use logloss for binary classification";
|
||||
const auto ndata = static_cast<bst_omp_uint>(info.labels_.Size());
|
||||
|
||||
GPUSet devices = GPUSet::All(param_.gpu_id, param_.n_gpus, ndata);
|
||||
GPUSet devices = GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, ndata);
|
||||
auto result = reducer_.Reduce(devices, nclass, info.weights_, info.labels_, preds);
|
||||
double dat[2] { result.Residue(), result.Weights() };
|
||||
|
||||
@ -215,7 +210,6 @@ struct EvalMClassBase : public Metric {
|
||||
|
||||
private:
|
||||
MultiClassMetricsReduction<Derived> reducer_;
|
||||
MetricParam param_;
|
||||
// used to store error message
|
||||
const char *error_msg_;
|
||||
};
|
||||
|
||||
@ -18,29 +18,12 @@ namespace obj {
|
||||
DMLC_REGISTRY_FILE_TAG(hinge_obj_gpu);
|
||||
#endif // defined(XGBOOST_USE_CUDA)
|
||||
|
||||
struct HingeObjParam : public dmlc::Parameter<HingeObjParam> {
|
||||
int n_gpus;
|
||||
int gpu_id;
|
||||
DMLC_DECLARE_PARAMETER(HingeObjParam) {
|
||||
DMLC_DECLARE_FIELD(n_gpus).set_default(1).set_lower_bound(GPUSet::kAll)
|
||||
.describe("Number of GPUs to use for multi-gpu algorithms.");
|
||||
DMLC_DECLARE_FIELD(gpu_id)
|
||||
.set_lower_bound(0)
|
||||
.set_default(0)
|
||||
.describe("gpu to use for objective function evaluation");
|
||||
}
|
||||
};
|
||||
|
||||
class HingeObj : public ObjFunction {
|
||||
public:
|
||||
HingeObj() = default;
|
||||
|
||||
void Configure(
|
||||
const std::vector<std::pair<std::string, std::string> > &args) override {
|
||||
param_.InitAllowUnknown(args);
|
||||
devices_ = GPUSet::All(param_.gpu_id, param_.n_gpus);
|
||||
label_correct_.Resize(devices_.IsEmpty() ? 1 : devices_.Size());
|
||||
}
|
||||
const std::vector<std::pair<std::string, std::string> > &args) override {}
|
||||
|
||||
void GetGradient(const HostDeviceVector<bst_float> &preds,
|
||||
const MetaInfo &info,
|
||||
@ -57,7 +40,6 @@ class HingeObj : public ObjFunction {
|
||||
out_gpair->Resize(ndata);
|
||||
common::Transform<>::Init(
|
||||
[=] XGBOOST_DEVICE(size_t _idx,
|
||||
common::Span<int> _label_correct,
|
||||
common::Span<GradientPair> _out_gpair,
|
||||
common::Span<const bst_float> _preds,
|
||||
common::Span<const bst_float> _labels,
|
||||
@ -75,8 +57,9 @@ class HingeObj : public ObjFunction {
|
||||
}
|
||||
_out_gpair[_idx] = GradientPair(g, h);
|
||||
},
|
||||
common::Range{0, static_cast<int64_t>(ndata)}, devices_).Eval(
|
||||
&label_correct_, out_gpair, &preds, &info.labels_, &info.weights_);
|
||||
common::Range{0, static_cast<int64_t>(ndata)},
|
||||
GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, ndata)).Eval(
|
||||
out_gpair, &preds, &info.labels_, &info.weights_);
|
||||
}
|
||||
|
||||
void PredTransform(HostDeviceVector<bst_float> *io_preds) override {
|
||||
@ -84,22 +67,16 @@ class HingeObj : public ObjFunction {
|
||||
[] XGBOOST_DEVICE(size_t _idx, common::Span<bst_float> _preds) {
|
||||
_preds[_idx] = _preds[_idx] > 0.0 ? 1.0 : 0.0;
|
||||
},
|
||||
common::Range{0, static_cast<int64_t>(io_preds->Size()), 1}, devices_)
|
||||
common::Range{0, static_cast<int64_t>(io_preds->Size()), 1},
|
||||
GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, io_preds->Size()))
|
||||
.Eval(io_preds);
|
||||
}
|
||||
|
||||
const char* DefaultEvalMetric() const override {
|
||||
return "error";
|
||||
}
|
||||
|
||||
private:
|
||||
GPUSet devices_;
|
||||
HostDeviceVector<int> label_correct_;
|
||||
HingeObjParam param_;
|
||||
};
|
||||
|
||||
// register the objective functions
|
||||
DMLC_REGISTER_PARAMETER(HingeObjParam);
|
||||
// register the objective functions
|
||||
XGBOOST_REGISTER_OBJECTIVE(HingeObj, "binary:hinge")
|
||||
.describe("Hinge loss. Expects labels to be in [0,1f]")
|
||||
|
||||
@ -13,6 +13,8 @@
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "../common/math.h"
|
||||
#include "../common/transform.h"
|
||||
|
||||
@ -25,18 +27,10 @@ DMLC_REGISTRY_FILE_TAG(multiclass_obj_gpu);
|
||||
|
||||
struct SoftmaxMultiClassParam : public dmlc::Parameter<SoftmaxMultiClassParam> {
|
||||
int num_class;
|
||||
int n_gpus;
|
||||
int gpu_id;
|
||||
// declare parameters
|
||||
DMLC_DECLARE_PARAMETER(SoftmaxMultiClassParam) {
|
||||
DMLC_DECLARE_FIELD(num_class).set_lower_bound(1)
|
||||
.describe("Number of output class in the multi-class classification.");
|
||||
DMLC_DECLARE_FIELD(n_gpus).set_default(1).set_lower_bound(GPUSet::kAll)
|
||||
.describe("Number of GPUs to use for multi-gpu algorithms.");
|
||||
DMLC_DECLARE_FIELD(gpu_id)
|
||||
.set_lower_bound(0)
|
||||
.set_default(0)
|
||||
.describe("gpu to use for objective function evaluation");
|
||||
}
|
||||
};
|
||||
// TODO(trivialfis): Currently the sharding in softmax is less than ideal
|
||||
@ -49,8 +43,6 @@ class SoftmaxMultiClassObj : public ObjFunction {
|
||||
}
|
||||
void Configure(const std::vector<std::pair<std::string, std::string> >& args) override {
|
||||
param_.InitAllowUnknown(args);
|
||||
devices_ = GPUSet::All(param_.gpu_id, param_.n_gpus);
|
||||
label_correct_.Resize(devices_.IsEmpty() ? 1 : devices_.Size());
|
||||
}
|
||||
void GetGradient(const HostDeviceVector<bst_float>& preds,
|
||||
const MetaInfo& info,
|
||||
@ -63,11 +55,14 @@ class SoftmaxMultiClassObj : public ObjFunction {
|
||||
const int nclass = param_.num_class;
|
||||
const auto ndata = static_cast<int64_t>(preds.Size() / nclass);
|
||||
|
||||
out_gpair->Shard(GPUDistribution::Granular(devices_, nclass));
|
||||
info.labels_.Shard(GPUDistribution::Block(devices_));
|
||||
info.weights_.Shard(GPUDistribution::Block(devices_));
|
||||
preds.Shard(GPUDistribution::Granular(devices_, nclass));
|
||||
label_correct_.Shard(GPUDistribution::Block(devices_));
|
||||
auto devices = GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, preds.Size());
|
||||
out_gpair->Shard(GPUDistribution::Granular(devices, nclass));
|
||||
info.labels_.Shard(GPUDistribution::Block(devices));
|
||||
info.weights_.Shard(GPUDistribution::Block(devices));
|
||||
preds.Shard(GPUDistribution::Granular(devices, nclass));
|
||||
|
||||
label_correct_.Resize(devices.IsEmpty() ? 1 : devices.Size());
|
||||
label_correct_.Shard(GPUDistribution::Block(devices));
|
||||
|
||||
out_gpair->Resize(preds.Size());
|
||||
label_correct_.Fill(1);
|
||||
@ -101,7 +96,7 @@ class SoftmaxMultiClassObj : public ObjFunction {
|
||||
p = label == k ? p - 1.0f : p;
|
||||
gpair[idx * nclass + k] = GradientPair(p * wt, h);
|
||||
}
|
||||
}, common::Range{0, ndata}, devices_, false)
|
||||
}, common::Range{0, ndata}, devices, false)
|
||||
.Eval(out_gpair, &info.labels_, &preds, &info.weights_, &label_correct_);
|
||||
|
||||
std::vector<int>& label_correct_h = label_correct_.HostVector();
|
||||
@ -126,6 +121,7 @@ class SoftmaxMultiClassObj : public ObjFunction {
|
||||
const auto ndata = static_cast<int64_t>(io_preds->Size() / nclass);
|
||||
max_preds_.Resize(ndata);
|
||||
|
||||
auto devices = GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, io_preds->Size());
|
||||
if (prob) {
|
||||
common::Transform<>::Init(
|
||||
[=] XGBOOST_DEVICE(size_t _idx, common::Span<bst_float> _preds) {
|
||||
@ -133,11 +129,11 @@ class SoftmaxMultiClassObj : public ObjFunction {
|
||||
_preds.subspan(_idx * nclass, nclass);
|
||||
common::Softmax(point.begin(), point.end());
|
||||
},
|
||||
common::Range{0, ndata}, GPUDistribution::Granular(devices_, nclass))
|
||||
common::Range{0, ndata}, GPUDistribution::Granular(devices, nclass))
|
||||
.Eval(io_preds);
|
||||
} else {
|
||||
io_preds->Shard(GPUDistribution::Granular(devices_, nclass));
|
||||
max_preds_.Shard(GPUDistribution::Block(devices_));
|
||||
io_preds->Shard(GPUDistribution::Granular(devices, nclass));
|
||||
max_preds_.Shard(GPUDistribution::Block(devices));
|
||||
common::Transform<>::Init(
|
||||
[=] XGBOOST_DEVICE(size_t _idx,
|
||||
common::Span<const bst_float> _preds,
|
||||
@ -148,7 +144,7 @@ class SoftmaxMultiClassObj : public ObjFunction {
|
||||
common::FindMaxIndex(point.cbegin(),
|
||||
point.cend()) - point.cbegin();
|
||||
},
|
||||
common::Range{0, ndata}, devices_, false)
|
||||
common::Range{0, ndata}, devices, false)
|
||||
.Eval(io_preds, &max_preds_);
|
||||
}
|
||||
if (!prob) {
|
||||
@ -162,7 +158,6 @@ class SoftmaxMultiClassObj : public ObjFunction {
|
||||
bool output_prob_;
|
||||
// parameter
|
||||
SoftmaxMultiClassParam param_;
|
||||
GPUSet devices_;
|
||||
// Cache for max_preds
|
||||
HostDeviceVector<bst_float> max_preds_;
|
||||
HostDeviceVector<int> label_correct_;
|
||||
|
||||
@ -14,7 +14,7 @@ DMLC_REGISTRY_ENABLE(::xgboost::ObjFunctionReg);
|
||||
|
||||
namespace xgboost {
|
||||
// implement factory functions
|
||||
ObjFunction* ObjFunction::Create(const std::string& name) {
|
||||
ObjFunction* ObjFunction::Create(const std::string& name, LearnerTrainParam const* tparam) {
|
||||
auto *e = ::dmlc::Registry< ::xgboost::ObjFunctionReg>::Get()->Find(name);
|
||||
if (e == nullptr) {
|
||||
for (const auto& entry : ::dmlc::Registry< ::xgboost::ObjFunctionReg>::List()) {
|
||||
@ -22,7 +22,9 @@ ObjFunction* ObjFunction::Create(const std::string& name) {
|
||||
}
|
||||
LOG(FATAL) << "Unknown objective function " << name;
|
||||
}
|
||||
return (e->body)();
|
||||
auto pobj = (e->body)();
|
||||
pobj->tparam_ = tparam;
|
||||
return pobj;
|
||||
}
|
||||
|
||||
} // namespace xgboost
|
||||
|
||||
@ -28,18 +28,10 @@ DMLC_REGISTRY_FILE_TAG(regression_obj_gpu);
|
||||
|
||||
struct RegLossParam : public dmlc::Parameter<RegLossParam> {
|
||||
float scale_pos_weight;
|
||||
int n_gpus;
|
||||
int gpu_id;
|
||||
// declare parameters
|
||||
DMLC_DECLARE_PARAMETER(RegLossParam) {
|
||||
DMLC_DECLARE_FIELD(scale_pos_weight).set_default(1.0f).set_lower_bound(0.0f)
|
||||
.describe("Scale the weight of positive examples by this factor");
|
||||
DMLC_DECLARE_FIELD(n_gpus).set_default(1).set_lower_bound(GPUSet::kAll)
|
||||
.describe("Number of GPUs to use for multi-gpu algorithms.");
|
||||
DMLC_DECLARE_FIELD(gpu_id)
|
||||
.set_lower_bound(0)
|
||||
.set_default(0)
|
||||
.describe("gpu to use for objective function evaluation");
|
||||
}
|
||||
};
|
||||
|
||||
@ -53,8 +45,6 @@ class RegLossObj : public ObjFunction {
|
||||
|
||||
void Configure(const std::vector<std::pair<std::string, std::string> >& args) override {
|
||||
param_.InitAllowUnknown(args);
|
||||
devices_ = GPUSet::All(param_.gpu_id, param_.n_gpus);
|
||||
label_correct_.Resize(devices_.IsEmpty() ? 1 : devices_.Size());
|
||||
}
|
||||
|
||||
void GetGradient(const HostDeviceVector<bst_float>& preds,
|
||||
@ -67,6 +57,8 @@ class RegLossObj : public ObjFunction {
|
||||
<< "preds.size=" << preds.Size() << ", label.size=" << info.labels_.Size();
|
||||
size_t ndata = preds.Size();
|
||||
out_gpair->Resize(ndata);
|
||||
auto devices = GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, preds.Size());
|
||||
label_correct_.Resize(devices.IsEmpty() ? 1 : devices.Size());
|
||||
label_correct_.Fill(1);
|
||||
|
||||
bool is_null_weight = info.weights_.Size() == 0;
|
||||
@ -91,7 +83,7 @@ class RegLossObj : public ObjFunction {
|
||||
_out_gpair[_idx] = GradientPair(Loss::FirstOrderGradient(p, label) * w,
|
||||
Loss::SecondOrderGradient(p, label) * w);
|
||||
},
|
||||
common::Range{0, static_cast<int64_t>(ndata)}, devices_).Eval(
|
||||
common::Range{0, static_cast<int64_t>(ndata)}, devices).Eval(
|
||||
&label_correct_, out_gpair, &preds, &info.labels_, &info.weights_);
|
||||
|
||||
// copy "label correct" flags back to host
|
||||
@ -113,7 +105,8 @@ class RegLossObj : public ObjFunction {
|
||||
[] XGBOOST_DEVICE(size_t _idx, common::Span<float> _preds) {
|
||||
_preds[_idx] = Loss::PredTransform(_preds[_idx]);
|
||||
}, common::Range{0, static_cast<int64_t>(io_preds->Size())},
|
||||
devices_).Eval(io_preds);
|
||||
GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, io_preds->Size()))
|
||||
.Eval(io_preds);
|
||||
}
|
||||
|
||||
float ProbToMargin(float base_score) const override {
|
||||
@ -122,7 +115,6 @@ class RegLossObj : public ObjFunction {
|
||||
|
||||
protected:
|
||||
RegLossParam param_;
|
||||
GPUSet devices_;
|
||||
};
|
||||
|
||||
// register the objective functions
|
||||
@ -181,18 +173,10 @@ XGBOOST_REGISTER_OBJECTIVE(GPULogisticRaw, "gpu:binary:logitraw")
|
||||
// declare parameter
|
||||
struct PoissonRegressionParam : public dmlc::Parameter<PoissonRegressionParam> {
|
||||
float max_delta_step;
|
||||
int n_gpus;
|
||||
int gpu_id;
|
||||
DMLC_DECLARE_PARAMETER(PoissonRegressionParam) {
|
||||
DMLC_DECLARE_FIELD(max_delta_step).set_lower_bound(0.0f).set_default(0.7f)
|
||||
.describe("Maximum delta step we allow each weight estimation to be." \
|
||||
" This parameter is required for possion regression.");
|
||||
DMLC_DECLARE_FIELD(n_gpus).set_default(1).set_lower_bound(GPUSet::kAll)
|
||||
.describe("Number of GPUs to use for multi-gpu algorithms.");
|
||||
DMLC_DECLARE_FIELD(gpu_id)
|
||||
.set_lower_bound(0)
|
||||
.set_default(0)
|
||||
.describe("gpu to use for objective function evaluation");
|
||||
}
|
||||
};
|
||||
|
||||
@ -202,8 +186,6 @@ class PoissonRegression : public ObjFunction {
|
||||
// declare functions
|
||||
void Configure(const std::vector<std::pair<std::string, std::string> >& args) override {
|
||||
param_.InitAllowUnknown(args);
|
||||
devices_ = GPUSet::All(param_.gpu_id, param_.n_gpus);
|
||||
label_correct_.Resize(devices_.IsEmpty() ? 1 : devices_.Size());
|
||||
}
|
||||
|
||||
void GetGradient(const HostDeviceVector<bst_float>& preds,
|
||||
@ -214,6 +196,8 @@ class PoissonRegression : public ObjFunction {
|
||||
CHECK_EQ(preds.Size(), info.labels_.Size()) << "labels are not correctly provided";
|
||||
size_t ndata = preds.Size();
|
||||
out_gpair->Resize(ndata);
|
||||
auto devices = GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, preds.Size());
|
||||
label_correct_.Resize(devices.IsEmpty() ? 1 : devices.Size());
|
||||
label_correct_.Fill(1);
|
||||
|
||||
bool is_null_weight = info.weights_.Size() == 0;
|
||||
@ -234,7 +218,7 @@ class PoissonRegression : public ObjFunction {
|
||||
_out_gpair[_idx] = GradientPair{(expf(p) - y) * w,
|
||||
expf(p + max_delta_step) * w};
|
||||
},
|
||||
common::Range{0, static_cast<int64_t>(ndata)}, devices_).Eval(
|
||||
common::Range{0, static_cast<int64_t>(ndata)}, devices).Eval(
|
||||
&label_correct_, out_gpair, &preds, &info.labels_, &info.weights_);
|
||||
// copy "label correct" flags back to host
|
||||
std::vector<int>& label_correct_h = label_correct_.HostVector();
|
||||
@ -249,7 +233,8 @@ class PoissonRegression : public ObjFunction {
|
||||
[] XGBOOST_DEVICE(size_t _idx, common::Span<bst_float> _preds) {
|
||||
_preds[_idx] = expf(_preds[_idx]);
|
||||
},
|
||||
common::Range{0, static_cast<int64_t>(io_preds->Size())}, devices_)
|
||||
common::Range{0, static_cast<int64_t>(io_preds->Size())},
|
||||
GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, io_preds->Size()))
|
||||
.Eval(io_preds);
|
||||
}
|
||||
void EvalTransform(HostDeviceVector<bst_float> *io_preds) override {
|
||||
@ -263,7 +248,6 @@ class PoissonRegression : public ObjFunction {
|
||||
}
|
||||
|
||||
private:
|
||||
GPUSet devices_;
|
||||
PoissonRegressionParam param_;
|
||||
HostDeviceVector<int> label_correct_;
|
||||
};
|
||||
@ -279,8 +263,9 @@ XGBOOST_REGISTER_OBJECTIVE(PoissonRegression, "count:poisson")
|
||||
// cox regression for survival data (negative values mean they are censored)
|
||||
class CoxRegression : public ObjFunction {
|
||||
public:
|
||||
// declare functions
|
||||
void Configure(const std::vector<std::pair<std::string, std::string> >& args) override {}
|
||||
void Configure(
|
||||
const std::vector<std::pair<std::string, std::string> > &args) override {}
|
||||
|
||||
void GetGradient(const HostDeviceVector<bst_float>& preds,
|
||||
const MetaInfo &info,
|
||||
int iter,
|
||||
@ -363,29 +348,11 @@ XGBOOST_REGISTER_OBJECTIVE(CoxRegression, "survival:cox")
|
||||
.describe("Cox regression for censored survival data (negative labels are considered censored).")
|
||||
.set_body([]() { return new CoxRegression(); });
|
||||
|
||||
|
||||
struct GammaRegressionParam : public dmlc::Parameter<GammaRegressionParam> {
|
||||
int n_gpus;
|
||||
int gpu_id;
|
||||
DMLC_DECLARE_PARAMETER(GammaRegressionParam) {
|
||||
DMLC_DECLARE_FIELD(n_gpus).set_default(1).set_lower_bound(GPUSet::kAll)
|
||||
.describe("Number of GPUs to use for multi-gpu algorithms.");
|
||||
DMLC_DECLARE_FIELD(gpu_id)
|
||||
.set_lower_bound(0)
|
||||
.set_default(0)
|
||||
.describe("gpu to use for objective function evaluation");
|
||||
}
|
||||
};
|
||||
|
||||
// gamma regression
|
||||
class GammaRegression : public ObjFunction {
|
||||
public:
|
||||
// declare functions
|
||||
void Configure(const std::vector<std::pair<std::string, std::string> >& args) override {
|
||||
param_.InitAllowUnknown(args);
|
||||
devices_ = GPUSet::All(param_.gpu_id, param_.n_gpus);
|
||||
label_correct_.Resize(devices_.IsEmpty() ? 1 : devices_.Size());
|
||||
}
|
||||
void Configure(
|
||||
const std::vector<std::pair<std::string, std::string> > &args) override {}
|
||||
|
||||
void GetGradient(const HostDeviceVector<bst_float> &preds,
|
||||
const MetaInfo &info,
|
||||
@ -394,7 +361,9 @@ class GammaRegression : public ObjFunction {
|
||||
CHECK_NE(info.labels_.Size(), 0U) << "label set cannot be empty";
|
||||
CHECK_EQ(preds.Size(), info.labels_.Size()) << "labels are not correctly provided";
|
||||
const size_t ndata = preds.Size();
|
||||
auto devices = GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, ndata);
|
||||
out_gpair->Resize(ndata);
|
||||
label_correct_.Resize(devices.IsEmpty() ? 1 : devices.Size());
|
||||
label_correct_.Fill(1);
|
||||
|
||||
const bool is_null_weight = info.weights_.Size() == 0;
|
||||
@ -413,7 +382,7 @@ class GammaRegression : public ObjFunction {
|
||||
}
|
||||
_out_gpair[_idx] = GradientPair((1 - y / expf(p)) * w, y / expf(p) * w);
|
||||
},
|
||||
common::Range{0, static_cast<int64_t>(ndata)}, devices_).Eval(
|
||||
common::Range{0, static_cast<int64_t>(ndata)}, devices).Eval(
|
||||
&label_correct_, out_gpair, &preds, &info.labels_, &info.weights_);
|
||||
|
||||
// copy "label correct" flags back to host
|
||||
@ -429,7 +398,8 @@ class GammaRegression : public ObjFunction {
|
||||
[] XGBOOST_DEVICE(size_t _idx, common::Span<bst_float> _preds) {
|
||||
_preds[_idx] = expf(_preds[_idx]);
|
||||
},
|
||||
common::Range{0, static_cast<int64_t>(io_preds->Size())}, devices_)
|
||||
common::Range{0, static_cast<int64_t>(io_preds->Size())},
|
||||
GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, io_preds->Size()))
|
||||
.Eval(io_preds);
|
||||
}
|
||||
void EvalTransform(HostDeviceVector<bst_float> *io_preds) override {
|
||||
@ -443,13 +413,9 @@ class GammaRegression : public ObjFunction {
|
||||
}
|
||||
|
||||
private:
|
||||
GPUSet devices_;
|
||||
GammaRegressionParam param_;
|
||||
HostDeviceVector<int> label_correct_;
|
||||
};
|
||||
|
||||
// register the objective functions
|
||||
DMLC_REGISTER_PARAMETER(GammaRegressionParam);
|
||||
// register the objective functions
|
||||
XGBOOST_REGISTER_OBJECTIVE(GammaRegression, "reg:gamma")
|
||||
.describe("Gamma regression for severity data.")
|
||||
@ -459,17 +425,9 @@ XGBOOST_REGISTER_OBJECTIVE(GammaRegression, "reg:gamma")
|
||||
// declare parameter
|
||||
struct TweedieRegressionParam : public dmlc::Parameter<TweedieRegressionParam> {
|
||||
float tweedie_variance_power;
|
||||
int n_gpus;
|
||||
int gpu_id;
|
||||
DMLC_DECLARE_PARAMETER(TweedieRegressionParam) {
|
||||
DMLC_DECLARE_FIELD(tweedie_variance_power).set_range(1.0f, 2.0f).set_default(1.5f)
|
||||
.describe("Tweedie variance power. Must be between in range [1, 2).");
|
||||
DMLC_DECLARE_FIELD(n_gpus).set_default(1).set_lower_bound(GPUSet::kAll)
|
||||
.describe("Number of GPUs to use for multi-gpu algorithms.");
|
||||
DMLC_DECLARE_FIELD(gpu_id)
|
||||
.set_lower_bound(0)
|
||||
.set_default(0)
|
||||
.describe("gpu to use for objective function evaluation");
|
||||
}
|
||||
};
|
||||
|
||||
@ -479,8 +437,6 @@ class TweedieRegression : public ObjFunction {
|
||||
// declare functions
|
||||
void Configure(const std::vector<std::pair<std::string, std::string> >& args) override {
|
||||
param_.InitAllowUnknown(args);
|
||||
devices_ = GPUSet::All(param_.gpu_id, param_.n_gpus);
|
||||
label_correct_.Resize(devices_.IsEmpty() ? 1 : devices_.Size());
|
||||
}
|
||||
|
||||
void GetGradient(const HostDeviceVector<bst_float>& preds,
|
||||
@ -491,6 +447,9 @@ class TweedieRegression : public ObjFunction {
|
||||
CHECK_EQ(preds.Size(), info.labels_.Size()) << "labels are not correctly provided";
|
||||
const size_t ndata = preds.Size();
|
||||
out_gpair->Resize(ndata);
|
||||
|
||||
auto devices = GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, preds.Size());
|
||||
label_correct_.Resize(devices.IsEmpty() ? 1 : devices.Size());
|
||||
label_correct_.Fill(1);
|
||||
|
||||
const bool is_null_weight = info.weights_.Size() == 0;
|
||||
@ -514,7 +473,7 @@ class TweedieRegression : public ObjFunction {
|
||||
std::exp((1 - rho) * p) + (2 - rho) * expf((2 - rho) * p);
|
||||
_out_gpair[_idx] = GradientPair(grad * w, hess * w);
|
||||
},
|
||||
common::Range{0, static_cast<int64_t>(ndata), 1}, devices_)
|
||||
common::Range{0, static_cast<int64_t>(ndata), 1}, devices)
|
||||
.Eval(&label_correct_, out_gpair, &preds, &info.labels_, &info.weights_);
|
||||
|
||||
// copy "label correct" flags back to host
|
||||
@ -530,7 +489,8 @@ class TweedieRegression : public ObjFunction {
|
||||
[] XGBOOST_DEVICE(size_t _idx, common::Span<bst_float> _preds) {
|
||||
_preds[_idx] = expf(_preds[_idx]);
|
||||
},
|
||||
common::Range{0, static_cast<int64_t>(io_preds->Size())}, devices_)
|
||||
common::Range{0, static_cast<int64_t>(io_preds->Size())},
|
||||
GPUSet::All(tparam_->gpu_id, tparam_->n_gpus, io_preds->Size()))
|
||||
.Eval(io_preds);
|
||||
}
|
||||
|
||||
@ -546,7 +506,6 @@ class TweedieRegression : public ObjFunction {
|
||||
}
|
||||
|
||||
private:
|
||||
GPUSet devices_;
|
||||
TweedieRegressionParam param_;
|
||||
HostDeviceVector<int> label_correct_;
|
||||
};
|
||||
|
||||
@ -82,7 +82,7 @@ class CPUPredictor : public Predictor {
|
||||
for (bst_omp_uint i = nsize - rest; i < nsize; ++i) {
|
||||
RegTree::FVec& feats = thread_temp[0];
|
||||
const auto ridx = static_cast<int64_t>(batch.base_rowid + i);
|
||||
auto inst = batch[i];
|
||||
auto inst = batch[i];
|
||||
for (int gid = 0; gid < num_group; ++gid) {
|
||||
const size_t offset = ridx * num_group + gid;
|
||||
preds[offset] +=
|
||||
|
||||
@ -20,20 +20,6 @@ namespace predictor {
|
||||
|
||||
DMLC_REGISTRY_FILE_TAG(gpu_predictor);
|
||||
|
||||
/*! \brief prediction parameters */
|
||||
struct GPUPredictionParam : public dmlc::Parameter<GPUPredictionParam> {
|
||||
int gpu_id;
|
||||
int n_gpus;
|
||||
// declare parameters
|
||||
DMLC_DECLARE_PARAMETER(GPUPredictionParam) {
|
||||
DMLC_DECLARE_FIELD(gpu_id).set_lower_bound(0).set_default(0).describe(
|
||||
"Device ordinal for GPU prediction.");
|
||||
DMLC_DECLARE_FIELD(n_gpus).set_lower_bound(-1).set_default(1).describe(
|
||||
"Number of devices to use for prediction.");
|
||||
}
|
||||
};
|
||||
DMLC_REGISTER_PARAMETER(GPUPredictionParam);
|
||||
|
||||
template <typename IterT>
|
||||
void IncrementOffset(IterT begin_itr, IterT end_itr, size_t amount) {
|
||||
thrust::transform(begin_itr, end_itr, begin_itr,
|
||||
@ -387,14 +373,15 @@ class GPUPredictor : public xgboost::Predictor {
|
||||
}
|
||||
|
||||
public:
|
||||
GPUPredictor() // NOLINT
|
||||
: cpu_predictor_(Predictor::Create("cpu_predictor")) {} // NOLINT
|
||||
GPUPredictor()
|
||||
: cpu_predictor_(Predictor::Create("cpu_predictor", learner_param_)) {}
|
||||
|
||||
void PredictBatch(DMatrix* dmat, HostDeviceVector<bst_float>* out_preds,
|
||||
const gbm::GBTreeModel& model, int tree_begin,
|
||||
unsigned ntree_limit = 0) override {
|
||||
GPUSet devices = GPUSet::All(
|
||||
param_.gpu_id, param_.n_gpus, dmat->Info().num_row_);
|
||||
GPUSet devices = GPUSet::All(learner_param_->gpu_id, learner_param_->n_gpus,
|
||||
dmat->Info().num_row_);
|
||||
CHECK_NE(devices.Size(), 0);
|
||||
ConfigureShards(devices);
|
||||
|
||||
if (this->PredictFromCache(dmat, out_preds, model, ntree_limit)) {
|
||||
@ -508,9 +495,8 @@ class GPUPredictor : public xgboost::Predictor {
|
||||
const std::vector<std::shared_ptr<DMatrix>>& cache) override {
|
||||
Predictor::Init(cfg, cache);
|
||||
cpu_predictor_->Init(cfg, cache);
|
||||
param_.InitAllowUnknown(cfg);
|
||||
|
||||
GPUSet devices = GPUSet::All(param_.gpu_id, param_.n_gpus);
|
||||
GPUSet devices = GPUSet::All(learner_param_->gpu_id, learner_param_->n_gpus);
|
||||
ConfigureShards(devices);
|
||||
}
|
||||
|
||||
@ -527,7 +513,6 @@ class GPUPredictor : public xgboost::Predictor {
|
||||
});
|
||||
}
|
||||
|
||||
GPUPredictionParam param_;
|
||||
std::unique_ptr<Predictor> cpu_predictor_;
|
||||
std::vector<DeviceShard> shards_;
|
||||
GPUSet devices_;
|
||||
|
||||
@ -15,12 +15,14 @@ void Predictor::Init(
|
||||
cache_[d.get()].data = d;
|
||||
}
|
||||
}
|
||||
Predictor* Predictor::Create(std::string name) {
|
||||
Predictor* Predictor::Create(std::string const& name, LearnerTrainParam const* learner_param) {
|
||||
auto* e = ::dmlc::Registry<PredictorReg>::Get()->Find(name);
|
||||
if (e == nullptr) {
|
||||
LOG(FATAL) << "Unknown predictor type " << name;
|
||||
}
|
||||
return (e->body)();
|
||||
auto p_predictor = (e->body)();
|
||||
p_predictor->learner_param_ = learner_param;
|
||||
return p_predictor;
|
||||
}
|
||||
} // namespace xgboost
|
||||
|
||||
|
||||
@ -72,10 +72,6 @@ struct TrainParam : public dmlc::Parameter<TrainParam> {
|
||||
bool refresh_leaf;
|
||||
// auxiliary data structure
|
||||
std::vector<int> monotone_constraints;
|
||||
// gpu to use for single gpu algorithms
|
||||
int gpu_id;
|
||||
// number of GPUs to use
|
||||
int n_gpus;
|
||||
// the criteria to use for ranking splits
|
||||
std::string split_evaluator;
|
||||
|
||||
@ -191,14 +187,6 @@ struct TrainParam : public dmlc::Parameter<TrainParam> {
|
||||
DMLC_DECLARE_FIELD(monotone_constraints)
|
||||
.set_default(std::vector<int>())
|
||||
.describe("Constraint of variable monotonicity");
|
||||
DMLC_DECLARE_FIELD(gpu_id)
|
||||
.set_lower_bound(0)
|
||||
.set_default(0)
|
||||
.describe("gpu to use for single gpu algorithms");
|
||||
DMLC_DECLARE_FIELD(n_gpus)
|
||||
.set_lower_bound(-1)
|
||||
.set_default(1)
|
||||
.describe("Number of GPUs to use for multi-gpu algorithms: -1=use all GPUs");
|
||||
DMLC_DECLARE_FIELD(split_evaluator)
|
||||
.set_default("elastic_net,monotonic,interaction")
|
||||
.describe("The criteria to use for ranking splits");
|
||||
|
||||
@ -14,12 +14,14 @@ DMLC_REGISTRY_ENABLE(::xgboost::TreeUpdaterReg);
|
||||
|
||||
namespace xgboost {
|
||||
|
||||
TreeUpdater* TreeUpdater::Create(const std::string& name) {
|
||||
TreeUpdater* TreeUpdater::Create(const std::string& name, LearnerTrainParam const* tparam) {
|
||||
auto *e = ::dmlc::Registry< ::xgboost::TreeUpdaterReg>::Get()->Find(name);
|
||||
if (e == nullptr) {
|
||||
LOG(FATAL) << "Unknown tree updater " << name;
|
||||
}
|
||||
return (e->body)();
|
||||
auto p_updater = (e->body)();
|
||||
p_updater->tparam_ = tparam;
|
||||
return p_updater;
|
||||
}
|
||||
|
||||
} // namespace xgboost
|
||||
|
||||
@ -769,7 +769,7 @@ class DistColMaker : public ColMaker {
|
||||
public:
|
||||
void Init(const std::vector<std::pair<std::string, std::string> >& args) override {
|
||||
param_.InitAllowUnknown(args);
|
||||
pruner_.reset(TreeUpdater::Create("prune"));
|
||||
pruner_.reset(TreeUpdater::Create("prune", tparam_));
|
||||
pruner_->Init(args);
|
||||
spliteval_.reset(SplitEvaluator::Create(param_.split_evaluator));
|
||||
spliteval_->Init(args);
|
||||
|
||||
@ -443,9 +443,10 @@ void ArgMaxByKey(common::Span<ExactSplitCandidate> nodeSplits,
|
||||
common::Span<const DeviceNodeStats> nodes,
|
||||
int nUniqKeys,
|
||||
NodeIdT nodeStart, int len, const TrainParam param,
|
||||
ArgMaxByKeyAlgo algo) {
|
||||
ArgMaxByKeyAlgo algo,
|
||||
GPUSet const& devices) {
|
||||
dh::FillConst<ExactSplitCandidate, BLKDIM, ITEMS_PER_THREAD>(
|
||||
param.gpu_id, nodeSplits.data(), nUniqKeys,
|
||||
*(devices.begin()), nodeSplits.data(), nUniqKeys,
|
||||
ExactSplitCandidate());
|
||||
int nBlks = dh::DivRoundUp(len, ITEMS_PER_THREAD * BLKDIM);
|
||||
switch (algo) {
|
||||
@ -585,7 +586,7 @@ class GPUMaker : public TreeUpdater {
|
||||
maxNodes_ = (1 << (param_.max_depth + 1)) - 1;
|
||||
maxLeaves_ = 1 << param_.max_depth;
|
||||
|
||||
devices_ = GPUSet::All(param_.gpu_id, param_.n_gpus);
|
||||
devices_ = GPUSet::All(tparam_->gpu_id, tparam_->n_gpus);
|
||||
}
|
||||
|
||||
void Update(HostDeviceVector<GradientPair>* gpair, DMatrix* dmat,
|
||||
@ -641,7 +642,7 @@ class GPUMaker : public TreeUpdater {
|
||||
float min_split_loss = param_.min_split_loss;
|
||||
auto gpu_param = GPUTrainingParam(param_);
|
||||
|
||||
dh::LaunchN(param_.gpu_id, nNodes, [=] __device__(int uid) {
|
||||
dh::LaunchN(*(devices_.begin()), nNodes, [=] __device__(int uid) {
|
||||
int absNodeId = uid + nodeStart;
|
||||
ExactSplitCandidate s = d_nodeSplits[uid];
|
||||
if (s.IsSplittable(min_split_loss)) {
|
||||
@ -683,16 +684,18 @@ class GPUMaker : public TreeUpdater {
|
||||
instIds_.CurrentSpan(), nodeAssigns_.CurrentSpan(), n_vals_, nNodes,
|
||||
n_cols_, tmpScanGradBuff_, tmp_scan_key_buff_,
|
||||
colIds_, nodeStart);
|
||||
auto devices = GPUSet::All(tparam_->gpu_id, tparam_->n_gpus);
|
||||
ArgMaxByKey(nodeSplits_, gradscans_, gradsums_,
|
||||
vals_.CurrentSpan(), colIds_, nodeAssigns_.CurrentSpan(),
|
||||
nodes_, nNodes, nodeStart, n_vals_, param_,
|
||||
level <= kMaxAbkLevels ? kAbkSmem : kAbkGmem);
|
||||
level <= kMaxAbkLevels ? kAbkSmem : kAbkGmem,
|
||||
devices);
|
||||
Split2Node(nNodes, nodeStart);
|
||||
}
|
||||
|
||||
void AllocateAllData(int offsetSize) {
|
||||
int tmpBuffSize = ScanTempBufferSize(n_vals_);
|
||||
ba_.Allocate(param_.gpu_id, &vals_, n_vals_,
|
||||
ba_.Allocate(*(devices_.begin()), &vals_, n_vals_,
|
||||
&vals_cached_, n_vals_, &instIds_, n_vals_, &inst_ids_cached_, n_vals_,
|
||||
&colOffsets_, offsetSize, &gradsInst_, n_rows_, &nodeAssigns_, n_vals_,
|
||||
&nodeLocations_, n_vals_, &nodes_, maxNodes_, &node_assigns_per_inst_,
|
||||
@ -783,7 +786,7 @@ class GPUMaker : public TreeUpdater {
|
||||
auto d_nodes = nodes_;
|
||||
auto d_sums = gradsums_;
|
||||
auto gpu_params = GPUTrainingParam(param_);
|
||||
dh::LaunchN(param_.gpu_id, 1, [=] __device__(int idx) {
|
||||
dh::LaunchN(*(devices_.begin()), 1, [=] __device__(int idx) {
|
||||
d_nodes[0] = DeviceNodeStats(d_sums[0], 0, gpu_params);
|
||||
});
|
||||
} else {
|
||||
@ -800,7 +803,7 @@ class GPUMaker : public TreeUpdater {
|
||||
nodeAssigns_.Current(), instIds_.Current(), nodes_.data(),
|
||||
colOffsets_.data(), vals_.Current(), n_vals_, n_cols_);
|
||||
// gather the node assignments across all other columns too
|
||||
dh::Gather(param_.gpu_id, nodeAssigns_.Current(),
|
||||
dh::Gather(*(devices_.begin()), nodeAssigns_.Current(),
|
||||
node_assigns_per_inst_.data(), instIds_.Current(), n_vals_);
|
||||
SortKeys(level);
|
||||
}
|
||||
@ -811,7 +814,7 @@ class GPUMaker : public TreeUpdater {
|
||||
// but we don't need more than level+1 bits for sorting!
|
||||
SegmentedSort(&tmp_mem_, &nodeAssigns_, &nodeLocations_, n_vals_, n_cols_,
|
||||
colOffsets_, 0, level + 1);
|
||||
dh::Gather<float, int>(param_.gpu_id, vals_.other(),
|
||||
dh::Gather<float, int>(*(devices_.begin()), vals_.other(),
|
||||
vals_.Current(), instIds_.other(), instIds_.Current(),
|
||||
nodeLocations_.Current(), n_vals_);
|
||||
vals_.buff.selector ^= 1;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright 2017-2018 XGBoost contributors
|
||||
* Copyright 2017-2019 XGBoost contributors
|
||||
*/
|
||||
#include <thrust/copy.h>
|
||||
#include <thrust/functional.h>
|
||||
@ -322,7 +322,7 @@ __global__ void EvaluateSplitKernel(
|
||||
node_histogram, // histogram for gradients
|
||||
common::Span<const int> feature_set, // Selected features
|
||||
DeviceNodeStats node,
|
||||
ELLPackMatrix matrix,
|
||||
ELLPackMatrix matrix,
|
||||
GPUTrainingParam gpu_param,
|
||||
common::Span<DeviceSplitCandidate> split_candidates, // resulting split
|
||||
ValueConstraint value_constraint,
|
||||
@ -1377,13 +1377,16 @@ template <typename GradientSumT>
|
||||
class GPUHistMakerSpecialised{
|
||||
public:
|
||||
GPUHistMakerSpecialised() : initialised_{false}, p_last_fmat_{nullptr} {}
|
||||
void Init(
|
||||
const std::vector<std::pair<std::string, std::string>>& args) {
|
||||
void Init(const std::vector<std::pair<std::string, std::string>>& args,
|
||||
LearnerTrainParam const* lparam) {
|
||||
param_.InitAllowUnknown(args);
|
||||
learner_param_ = lparam;
|
||||
hist_maker_param_.InitAllowUnknown(args);
|
||||
CHECK(param_.n_gpus != 0) << "Must have at least one device";
|
||||
n_devices_ = param_.n_gpus;
|
||||
dist_ = GPUDistribution::Block(GPUSet::All(param_.gpu_id, param_.n_gpus));
|
||||
auto devices = GPUSet::All(learner_param_->gpu_id,
|
||||
learner_param_->n_gpus);
|
||||
n_devices_ = devices.Size();
|
||||
CHECK(n_devices_ != 0) << "Must have at least one device";
|
||||
dist_ = GPUDistribution::Block(devices);
|
||||
|
||||
dh::CheckComputeCapability();
|
||||
|
||||
@ -1446,7 +1449,8 @@ class GPUHistMakerSpecialised{
|
||||
|
||||
// Find the cuts.
|
||||
monitor_.StartCuda("Quantiles");
|
||||
common::DeviceSketch(batch, *info_, param_, &hmat_, hist_maker_param_.gpu_batch_nrows);
|
||||
common::DeviceSketch(batch, *info_, param_, &hmat_, hist_maker_param_.gpu_batch_nrows,
|
||||
GPUSet::All(learner_param_->gpu_id, learner_param_->n_gpus));
|
||||
n_bins_ = hmat_.row_ptr.back();
|
||||
monitor_.StopCuda("Quantiles");
|
||||
auto is_dense = info_->num_nonzero_ == info_->num_row_ * info_->num_col_;
|
||||
@ -1552,6 +1556,7 @@ class GPUHistMakerSpecialised{
|
||||
int n_bins_;
|
||||
|
||||
GPUHistMakerTrainParam hist_maker_param_;
|
||||
LearnerTrainParam const* learner_param_;
|
||||
common::GHistIndexMatrix gmat_;
|
||||
|
||||
dh::AllReducer reducer_;
|
||||
@ -1573,10 +1578,10 @@ class GPUHistMaker : public TreeUpdater {
|
||||
double_maker_.reset();
|
||||
if (hist_maker_param_.single_precision_histogram) {
|
||||
float_maker_.reset(new GPUHistMakerSpecialised<GradientPair>());
|
||||
float_maker_->Init(args);
|
||||
float_maker_->Init(args, tparam_);
|
||||
} else {
|
||||
double_maker_.reset(new GPUHistMakerSpecialised<GradientPairPrecise>());
|
||||
double_maker_->Init(args);
|
||||
double_maker_->Init(args, tparam_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ DMLC_REGISTRY_FILE_TAG(updater_prune);
|
||||
class TreePruner: public TreeUpdater {
|
||||
public:
|
||||
TreePruner() {
|
||||
syncher_.reset(TreeUpdater::Create("sync"));
|
||||
syncher_.reset(TreeUpdater::Create("sync", tparam_));
|
||||
}
|
||||
// set training parameter
|
||||
void Init(const std::vector<std::pair<std::string, std::string> >& args) override {
|
||||
|
||||
@ -35,7 +35,7 @@ DMLC_REGISTRY_FILE_TAG(updater_quantile_hist);
|
||||
void QuantileHistMaker::Init(const std::vector<std::pair<std::string, std::string> >& args) {
|
||||
// initialize pruner
|
||||
if (!pruner_) {
|
||||
pruner_.reset(TreeUpdater::Create("prune"));
|
||||
pruner_.reset(TreeUpdater::Create("prune", tparam_));
|
||||
}
|
||||
pruner_->Init(args);
|
||||
param_.InitAllowUnknown(args);
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
#include "../../../src/common/common.h"
|
||||
#include <gtest/gtest.h>
|
||||
#include <xgboost/logging.h>
|
||||
#include "../../../src/common/common.h"
|
||||
#include "../helpers.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace xgboost {
|
||||
|
||||
@ -36,6 +40,23 @@ TEST(GPUSet, GPUBasic) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GPUSet, Verbose) {
|
||||
{
|
||||
std::map<std::string, std::string> args {};
|
||||
args["verbosity"] = "3"; // LOG INFO
|
||||
|
||||
testing::internal::CaptureStderr();
|
||||
ConsoleLogger::Configure(args.cbegin(), args.cend());
|
||||
GPUSet::All(0, 1);
|
||||
std::string output = testing::internal::GetCapturedStderr();
|
||||
ASSERT_NE(output.find("GPU ID: 0"), std::string::npos);
|
||||
ASSERT_NE(output.find("GPUs: 1"), std::string::npos);
|
||||
|
||||
args["verbosity"] = "1"; // restore
|
||||
ConsoleLogger::Configure(args.cbegin(), args.cend());
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(XGBOOST_USE_NCCL)
|
||||
TEST(GPUSet, MGPU_GPUBasic) {
|
||||
{
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <thrust/device_vector.h>
|
||||
#include <xgboost/base.h>
|
||||
#include "../../../src/common/device_helpers.cuh"
|
||||
#include "../helpers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using xgboost::common::Span;
|
||||
@ -65,7 +66,9 @@ void TestLbs() {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(cub_lbs, Test) { TestLbs(); }
|
||||
TEST(cub_lbs, Test) {
|
||||
TestLbs();
|
||||
}
|
||||
|
||||
TEST(sumReduce, Test) {
|
||||
thrust::device_vector<float> data(100, 1.0f);
|
||||
@ -89,4 +92,6 @@ void TestAllocator() {
|
||||
}
|
||||
|
||||
// Define the test in a function so we can use device lambda
|
||||
TEST(bulkAllocator, Test) { TestAllocator(); }
|
||||
TEST(bulkAllocator, Test) {
|
||||
TestAllocator();
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "../../../src/common/enum_class_param.h"
|
||||
#include <dmlc/parameter.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <xgboost/enum_class_param.h>
|
||||
|
||||
enum class Foo : int {
|
||||
kBar = 0, kFrog = 1, kCat = 2, kDog = 3
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
#include "../../../src/common/device_helpers.cuh"
|
||||
#include "../../../src/common/hist_util.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "xgboost/c_api.h"
|
||||
#include <algorithm>
|
||||
@ -7,6 +5,10 @@
|
||||
#include <thrust/device_vector.h>
|
||||
#include <thrust/iterator/counting_iterator.h>
|
||||
|
||||
#include "../helpers.h"
|
||||
#include "../../../src/common/device_helpers.cuh"
|
||||
#include "../../../src/common/hist_util.h"
|
||||
|
||||
namespace xgboost {
|
||||
namespace common {
|
||||
|
||||
@ -27,8 +29,6 @@ void TestDeviceSketch(const GPUSet& devices) {
|
||||
// parameters for finding quantiles
|
||||
tree::TrainParam p;
|
||||
p.max_bin = 20;
|
||||
p.gpu_id = 0;
|
||||
p.n_gpus = devices.Size();
|
||||
// ensure that the exact quantiles are found
|
||||
int gpu_batch_nrows = nrows * 10;
|
||||
|
||||
@ -39,7 +39,7 @@ void TestDeviceSketch(const GPUSet& devices) {
|
||||
// find the cuts on the GPU
|
||||
const SparsePage& batch = *(*dmat)->GetRowBatches().begin();
|
||||
HistCutMatrix hmat_gpu;
|
||||
DeviceSketch(batch, (*dmat)->Info(), p, &hmat_gpu, gpu_batch_nrows);
|
||||
DeviceSketch(batch, (*dmat)->Info(), p, &hmat_gpu, gpu_batch_nrows, devices);
|
||||
|
||||
// compare the cuts
|
||||
double eps = 1e-2;
|
||||
|
||||
@ -18,6 +18,9 @@
|
||||
#include <xgboost/objective.h>
|
||||
#include <xgboost/metric.h>
|
||||
#include <xgboost/predictor.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
|
||||
#include "../../src/common/common.h"
|
||||
|
||||
#if defined(__CUDACC__)
|
||||
#define DeclareUnifiedTest(name) GPU ## name
|
||||
@ -25,6 +28,12 @@
|
||||
#define DeclareUnifiedTest(name) name
|
||||
#endif
|
||||
|
||||
#if defined(__CUDACC__)
|
||||
#define NGPUS 1
|
||||
#else
|
||||
#define NGPUS 0
|
||||
#endif
|
||||
|
||||
bool FileExists(const std::string& filename);
|
||||
|
||||
int64_t GetFileSize(const std::string& filename);
|
||||
@ -158,5 +167,14 @@ std::unique_ptr<DMatrix> CreateSparsePageDMatrix(size_t n_entries, size_t page_s
|
||||
|
||||
gbm::GBTreeModel CreateTestModel();
|
||||
|
||||
inline LearnerTrainParam CreateEmptyGenericParam(int gpu_id, int n_gpus) {
|
||||
xgboost::LearnerTrainParam tparam;
|
||||
std::vector<std::pair<std::string, std::string>> args {
|
||||
{"gpu_id", std::to_string(gpu_id)},
|
||||
{"n_gpus", std::to_string(n_gpus)}};
|
||||
tparam.Init(args);
|
||||
return tparam;
|
||||
}
|
||||
|
||||
} // namespace xgboost
|
||||
#endif
|
||||
|
||||
@ -7,9 +7,10 @@
|
||||
|
||||
TEST(Linear, shotgun) {
|
||||
auto mat = xgboost::CreateDMatrix(10, 10, 0);
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(0, 0);
|
||||
{
|
||||
auto updater = std::unique_ptr<xgboost::LinearUpdater>(
|
||||
xgboost::LinearUpdater::Create("shotgun"));
|
||||
xgboost::LinearUpdater::Create("shotgun", &lparam));
|
||||
updater->Init({{"eta", "1."}});
|
||||
xgboost::HostDeviceVector<xgboost::GradientPair> gpair(
|
||||
(*mat)->Info().num_row_, xgboost::GradientPair(-5, 1.0));
|
||||
@ -24,7 +25,7 @@ TEST(Linear, shotgun) {
|
||||
}
|
||||
{
|
||||
auto updater = std::unique_ptr<xgboost::LinearUpdater>(
|
||||
xgboost::LinearUpdater::Create("shotgun"));
|
||||
xgboost::LinearUpdater::Create("shotgun", &lparam));
|
||||
EXPECT_ANY_THROW(updater->Init({{"feature_selector", "random"}}));
|
||||
}
|
||||
delete mat;
|
||||
@ -32,8 +33,9 @@ TEST(Linear, shotgun) {
|
||||
|
||||
TEST(Linear, coordinate) {
|
||||
auto mat = xgboost::CreateDMatrix(10, 10, 0);
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(0, 0);
|
||||
auto updater = std::unique_ptr<xgboost::LinearUpdater>(
|
||||
xgboost::LinearUpdater::Create("coord_descent"));
|
||||
xgboost::LinearUpdater::Create("coord_descent", &lparam));
|
||||
updater->Init({{"eta", "1."}});
|
||||
xgboost::HostDeviceVector<xgboost::GradientPair> gpair(
|
||||
(*mat)->Info().num_row_, xgboost::GradientPair(-5, 1.0));
|
||||
|
||||
@ -6,11 +6,12 @@
|
||||
namespace xgboost {
|
||||
|
||||
TEST(Linear, GPUCoordinate) {
|
||||
dh::safe_cuda(cudaSetDevice(0));
|
||||
auto mat = xgboost::CreateDMatrix(10, 10, 0);
|
||||
auto lparam = CreateEmptyGenericParam(0, 1);
|
||||
lparam.n_gpus = 1;
|
||||
auto updater = std::unique_ptr<xgboost::LinearUpdater>(
|
||||
xgboost::LinearUpdater::Create("gpu_coord_descent"));
|
||||
updater->Init({{"eta", "1."}, {"n_gpus", "1"}});
|
||||
xgboost::LinearUpdater::Create("gpu_coord_descent", &lparam));
|
||||
updater->Init({{"eta", "1."}});
|
||||
xgboost::HostDeviceVector<xgboost::GradientPair> gpair(
|
||||
(*mat)->Info().num_row_, xgboost::GradientPair(-5, 1.0));
|
||||
xgboost::gbm::GBLinearModel model;
|
||||
@ -26,12 +27,13 @@ TEST(Linear, GPUCoordinate) {
|
||||
|
||||
#if defined(XGBOOST_USE_NCCL)
|
||||
TEST(Linear, MGPU_GPUCoordinate) {
|
||||
dh::safe_cuda(cudaSetDevice(0));
|
||||
{
|
||||
auto mat = xgboost::CreateDMatrix(10, 10, 0);
|
||||
auto lparam = CreateEmptyGenericParam(0, -1);
|
||||
lparam.n_gpus = -1;
|
||||
auto updater = std::unique_ptr<xgboost::LinearUpdater>(
|
||||
xgboost::LinearUpdater::Create("gpu_coord_descent"));
|
||||
updater->Init({{"eta", "1."}, {"n_gpus", "-1"}});
|
||||
xgboost::LinearUpdater::Create("gpu_coord_descent", &lparam));
|
||||
updater->Init({{"eta", "1."}});
|
||||
xgboost::HostDeviceVector<xgboost::GradientPair> gpair(
|
||||
(*mat)->Info().num_row_, xgboost::GradientPair(-5, 1.0));
|
||||
xgboost::gbm::GBLinearModel model;
|
||||
@ -44,15 +46,13 @@ TEST(Linear, MGPU_GPUCoordinate) {
|
||||
delete mat;
|
||||
}
|
||||
|
||||
dh::safe_cuda(cudaSetDevice(0));
|
||||
{
|
||||
auto lparam = CreateEmptyGenericParam(1, -1);
|
||||
lparam.n_gpus = -1;
|
||||
auto mat = xgboost::CreateDMatrix(10, 10, 0);
|
||||
auto updater = std::unique_ptr<xgboost::LinearUpdater>(
|
||||
xgboost::LinearUpdater::Create("gpu_coord_descent"));
|
||||
updater->Init({
|
||||
{"eta", "1."},
|
||||
{"n_gpus", "-1"},
|
||||
{"gpu_id", "1"}});
|
||||
xgboost::LinearUpdater::Create("gpu_coord_descent", &lparam));
|
||||
updater->Init({{"eta", "1."}});
|
||||
xgboost::HostDeviceVector<xgboost::GradientPair> gpair(
|
||||
(*mat)->Info().num_row_, xgboost::GradientPair(-5, 1.0));
|
||||
xgboost::gbm::GBLinearModel model;
|
||||
|
||||
@ -1,21 +1,14 @@
|
||||
/*!
|
||||
* Copyright 2018 XGBoost contributors
|
||||
* Copyright 2018-2019 XGBoost contributors
|
||||
*/
|
||||
#include <xgboost/metric.h>
|
||||
#include <map>
|
||||
#include "../helpers.h"
|
||||
|
||||
using Arg = std::pair<std::string, std::string>;
|
||||
|
||||
#if defined(__CUDACC__)
|
||||
#define N_GPU() Arg{"n_gpus", "1"}
|
||||
#else
|
||||
#define N_GPU() Arg{"n_gpus", "0"}
|
||||
#endif
|
||||
|
||||
TEST(Metric, DeclareUnifiedTest(RMSE)) {
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("rmse");
|
||||
metric->Configure({N_GPU()});
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("rmse", &lparam);
|
||||
metric->Configure({});
|
||||
ASSERT_STREQ(metric->Name(), "rmse");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -27,8 +20,9 @@ TEST(Metric, DeclareUnifiedTest(RMSE)) {
|
||||
}
|
||||
|
||||
TEST(Metric, DeclareUnifiedTest(MAE)) {
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("mae");
|
||||
metric->Configure({N_GPU()});
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("mae", &lparam);
|
||||
metric->Configure({});
|
||||
ASSERT_STREQ(metric->Name(), "mae");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -39,8 +33,9 @@ TEST(Metric, DeclareUnifiedTest(MAE)) {
|
||||
}
|
||||
|
||||
TEST(Metric, DeclareUnifiedTest(LogLoss)) {
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("logloss");
|
||||
metric->Configure({N_GPU()});
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("logloss", &lparam);
|
||||
metric->Configure({});
|
||||
ASSERT_STREQ(metric->Name(), "logloss");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -51,8 +46,9 @@ TEST(Metric, DeclareUnifiedTest(LogLoss)) {
|
||||
}
|
||||
|
||||
TEST(Metric, DeclareUnifiedTest(Error)) {
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("error");
|
||||
metric->Configure({N_GPU()});
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("error", &lparam);
|
||||
metric->Configure({});
|
||||
ASSERT_STREQ(metric->Name(), "error");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -60,17 +56,17 @@ TEST(Metric, DeclareUnifiedTest(Error)) {
|
||||
{ 0, 0, 1, 1}),
|
||||
0.5f, 0.001f);
|
||||
|
||||
EXPECT_ANY_THROW(xgboost::Metric::Create("error@abc"));
|
||||
EXPECT_ANY_THROW(xgboost::Metric::Create("error@abc", &lparam));
|
||||
delete metric;
|
||||
|
||||
metric = xgboost::Metric::Create("error@0.5f");
|
||||
metric->Configure({N_GPU()});
|
||||
metric = xgboost::Metric::Create("error@0.5f", &lparam);
|
||||
metric->Configure({});
|
||||
EXPECT_STREQ(metric->Name(), "error");
|
||||
|
||||
delete metric;
|
||||
|
||||
metric = xgboost::Metric::Create("error@0.1");
|
||||
metric->Configure({N_GPU()});
|
||||
metric = xgboost::Metric::Create("error@0.1", &lparam);
|
||||
metric->Configure({});
|
||||
ASSERT_STREQ(metric->Name(), "error@0.1");
|
||||
EXPECT_STREQ(metric->Name(), "error@0.1");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0, 1e-10);
|
||||
@ -82,8 +78,9 @@ TEST(Metric, DeclareUnifiedTest(Error)) {
|
||||
}
|
||||
|
||||
TEST(Metric, DeclareUnifiedTest(PoissionNegLogLik)) {
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("poisson-nloglik");
|
||||
metric->Configure({N_GPU()});
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("poisson-nloglik", &lparam);
|
||||
metric->Configure({});
|
||||
ASSERT_STREQ(metric->Name(), "poisson-nloglik");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0.5f, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -96,8 +93,9 @@ TEST(Metric, DeclareUnifiedTest(PoissionNegLogLik)) {
|
||||
#if defined(XGBOOST_USE_NCCL) && defined(__CUDACC__)
|
||||
TEST(Metric, MGPU_RMSE) {
|
||||
{
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("rmse");
|
||||
metric->Configure({Arg{"n_gpus", "-1"}});
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(0, -1);
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("rmse", &lparam);
|
||||
metric->Configure({});
|
||||
ASSERT_STREQ(metric->Name(), "rmse");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0}, {0}), 0, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -108,8 +106,8 @@ TEST(Metric, MGPU_RMSE) {
|
||||
}
|
||||
|
||||
{
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("rmse");
|
||||
metric->Configure({Arg{"n_gpus", "-1"}, Arg{"gpu_id", "1"}});
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(1, -1);
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("rmse", &lparam);
|
||||
ASSERT_STREQ(metric->Name(), "rmse");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
|
||||
@ -4,15 +4,16 @@
|
||||
#include "../helpers.h"
|
||||
|
||||
TEST(Metric, UnknownMetric) {
|
||||
auto tparam = xgboost::CreateEmptyGenericParam(0, 0);
|
||||
xgboost::Metric * metric = nullptr;
|
||||
EXPECT_ANY_THROW(metric = xgboost::Metric::Create("unknown_name"));
|
||||
EXPECT_NO_THROW(metric = xgboost::Metric::Create("rmse"));
|
||||
EXPECT_ANY_THROW(metric = xgboost::Metric::Create("unknown_name", &tparam));
|
||||
EXPECT_NO_THROW(metric = xgboost::Metric::Create("rmse", &tparam));
|
||||
if (metric) {
|
||||
delete metric;
|
||||
}
|
||||
metric = nullptr;
|
||||
EXPECT_ANY_THROW(metric = xgboost::Metric::Create("unknown_name@1"));
|
||||
EXPECT_NO_THROW(metric = xgboost::Metric::Create("error@0.5f"));
|
||||
EXPECT_ANY_THROW(metric = xgboost::Metric::Create("unknown_name@1", &tparam));
|
||||
EXPECT_NO_THROW(metric = xgboost::Metric::Create("error@0.5f", &tparam));
|
||||
if (metric) {
|
||||
delete metric;
|
||||
}
|
||||
|
||||
@ -4,17 +4,12 @@
|
||||
|
||||
#include "../helpers.h"
|
||||
|
||||
using Arg = std::pair<std::string, std::string>;
|
||||
|
||||
#if defined(__CUDACC__)
|
||||
#define N_GPU() Arg{"n_gpus", "1"}
|
||||
#else
|
||||
#define N_GPU() Arg{"n_gpus", "0"}
|
||||
#endif
|
||||
|
||||
inline void TestMultiClassError(std::vector<Arg> args) {
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("merror");
|
||||
metric->Configure(args);
|
||||
inline void TestMultiClassError(xgboost::GPUSet const& devices) {
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
lparam.gpu_id = *devices.begin();
|
||||
lparam.n_gpus = devices.Size();
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("merror", &lparam);
|
||||
metric->Configure({});
|
||||
ASSERT_STREQ(metric->Name(), "merror");
|
||||
EXPECT_ANY_THROW(GetMetricEval(metric, {0}, {0, 0}));
|
||||
EXPECT_NEAR(GetMetricEval(
|
||||
@ -28,12 +23,16 @@ inline void TestMultiClassError(std::vector<Arg> args) {
|
||||
}
|
||||
|
||||
TEST(Metric, DeclareUnifiedTest(MultiClassError)) {
|
||||
TestMultiClassError({N_GPU()});
|
||||
auto devices = xgboost::GPUSet::Range(0, NGPUS);
|
||||
TestMultiClassError(devices);
|
||||
}
|
||||
|
||||
inline void TestMultiClassLogLoss(std::vector<Arg> args) {
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("mlogloss");
|
||||
metric->Configure(args);
|
||||
inline void TestMultiClassLogLoss(xgboost::GPUSet const& devices) {
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
lparam.gpu_id = *devices.begin();
|
||||
lparam.n_gpus = devices.Size();
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("mlogloss", &lparam);
|
||||
metric->Configure({});
|
||||
ASSERT_STREQ(metric->Name(), "mlogloss");
|
||||
EXPECT_ANY_THROW(GetMetricEval(metric, {0}, {0, 0}));
|
||||
EXPECT_NEAR(GetMetricEval(
|
||||
@ -47,15 +46,27 @@ inline void TestMultiClassLogLoss(std::vector<Arg> args) {
|
||||
}
|
||||
|
||||
TEST(Metric, DeclareUnifiedTest(MultiClassLogLoss)) {
|
||||
TestMultiClassLogLoss({N_GPU()});
|
||||
auto devices = xgboost::GPUSet::Range(0, NGPUS);
|
||||
TestMultiClassLogLoss(devices);
|
||||
}
|
||||
|
||||
#if defined(XGBOOST_USE_NCCL) && defined(__CUDACC__)
|
||||
TEST(Metric, MGPU_MultiClassError) {
|
||||
TestMultiClassError({Arg{"n_gpus", "-1"}});
|
||||
TestMultiClassError({Arg{"n_gpus", "-1"}, Arg{"gpu_id", "1"}});
|
||||
|
||||
TestMultiClassLogLoss({Arg{"n_gpus", "-1"}});
|
||||
TestMultiClassLogLoss({Arg{"n_gpus", "-1"}, Arg{"gpu_id", "1"}});
|
||||
{
|
||||
auto devices = xgboost::GPUSet::All(0, -1);
|
||||
TestMultiClassError(devices);
|
||||
}
|
||||
{
|
||||
auto devices = xgboost::GPUSet::All(1, -1);
|
||||
TestMultiClassError(devices);
|
||||
}
|
||||
{
|
||||
auto devices = xgboost::GPUSet::All(0, -1);
|
||||
TestMultiClassLogLoss(devices);
|
||||
}
|
||||
{
|
||||
auto devices = xgboost::GPUSet::All(1, -1);
|
||||
TestMultiClassLogLoss(devices);
|
||||
}
|
||||
}
|
||||
#endif // defined(XGBOOST_USE_NCCL)
|
||||
|
||||
@ -4,8 +4,9 @@
|
||||
#include "../helpers.h"
|
||||
|
||||
TEST(Metric, AMS) {
|
||||
EXPECT_ANY_THROW(xgboost::Metric::Create("ams"));
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("ams@0.5f");
|
||||
auto tparam = xgboost::CreateEmptyGenericParam(0, 0);
|
||||
EXPECT_ANY_THROW(xgboost::Metric::Create("ams", &tparam));
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("ams@0.5f", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "ams@0.5");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0.311f, 0.001f);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -14,7 +15,7 @@ TEST(Metric, AMS) {
|
||||
0.29710f, 0.001f);
|
||||
|
||||
delete metric;
|
||||
metric = xgboost::Metric::Create("ams@0");
|
||||
metric = xgboost::Metric::Create("ams@0", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "ams@0");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0.311f, 0.001f);
|
||||
|
||||
@ -22,7 +23,8 @@ TEST(Metric, AMS) {
|
||||
}
|
||||
|
||||
TEST(Metric, AUC) {
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("auc");
|
||||
auto tparam = xgboost::CreateEmptyGenericParam(0, 0);
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("auc", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "auc");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 1, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -36,7 +38,8 @@ TEST(Metric, AUC) {
|
||||
}
|
||||
|
||||
TEST(Metric, AUCPR) {
|
||||
xgboost::Metric *metric = xgboost::Metric::Create("aucpr");
|
||||
auto tparam = xgboost::CreateEmptyGenericParam(0, 0);
|
||||
xgboost::Metric *metric = xgboost::Metric::Create("aucpr", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "aucpr");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 0, 1, 1}, {0, 0, 1, 1}), 1, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0.1f, 0.9f, 0.1f, 0.9f}, {0, 0, 1, 1}),
|
||||
@ -62,7 +65,8 @@ TEST(Metric, Precision) {
|
||||
// When the limit for precision is not given, it takes the limit at
|
||||
// std::numeric_limits<unsigned>::max(); hence all values are very small
|
||||
// NOTE(AbdealiJK): Maybe this should be fixed to be num_row by default.
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("pre");
|
||||
auto tparam = xgboost::CreateEmptyGenericParam(0, 0);
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("pre", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "pre");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0, 1e-7);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -71,7 +75,7 @@ TEST(Metric, Precision) {
|
||||
0, 1e-7);
|
||||
|
||||
delete metric;
|
||||
metric = xgboost::Metric::Create("pre@2");
|
||||
metric = xgboost::Metric::Create("pre@2", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "pre@2");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0.5f, 1e-7);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -85,7 +89,8 @@ TEST(Metric, Precision) {
|
||||
}
|
||||
|
||||
TEST(Metric, NDCG) {
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("ndcg");
|
||||
auto tparam = xgboost::CreateEmptyGenericParam(0, 0);
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("ndcg", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "ndcg");
|
||||
EXPECT_ANY_THROW(GetMetricEval(metric, {0, 1}, {}));
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -98,7 +103,7 @@ TEST(Metric, NDCG) {
|
||||
0.6509f, 0.001f);
|
||||
|
||||
delete metric;
|
||||
metric = xgboost::Metric::Create("ndcg@2");
|
||||
metric = xgboost::Metric::Create("ndcg@2", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "ndcg@2");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 1, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -107,7 +112,7 @@ TEST(Metric, NDCG) {
|
||||
0.3868f, 0.001f);
|
||||
|
||||
delete metric;
|
||||
metric = xgboost::Metric::Create("ndcg@-");
|
||||
metric = xgboost::Metric::Create("ndcg@-", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "ndcg@-");
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
xgboost::HostDeviceVector<xgboost::bst_float>{},
|
||||
@ -119,7 +124,7 @@ TEST(Metric, NDCG) {
|
||||
0.6509f, 0.001f);
|
||||
|
||||
delete metric;
|
||||
metric = xgboost::Metric::Create("ndcg@2-");
|
||||
metric = xgboost::Metric::Create("ndcg@2-", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "ndcg@2-");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 1, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -131,7 +136,8 @@ TEST(Metric, NDCG) {
|
||||
}
|
||||
|
||||
TEST(Metric, MAP) {
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("map");
|
||||
auto tparam = xgboost::CreateEmptyGenericParam(0, 0);
|
||||
xgboost::Metric * metric = xgboost::Metric::Create("map", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "map");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 1, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
@ -143,14 +149,14 @@ TEST(Metric, MAP) {
|
||||
std::vector<xgboost::bst_float>{}), 1, 1e-10);
|
||||
|
||||
delete metric;
|
||||
metric = xgboost::Metric::Create("map@-");
|
||||
metric = xgboost::Metric::Create("map@-", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "map@-");
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
xgboost::HostDeviceVector<xgboost::bst_float>{},
|
||||
{}), 0, 1e-10);
|
||||
|
||||
delete metric;
|
||||
metric = xgboost::Metric::Create("map@2");
|
||||
metric = xgboost::Metric::Create("map@2", &tparam);
|
||||
ASSERT_STREQ(metric->Name(), "map@2");
|
||||
EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 1, 1e-10);
|
||||
EXPECT_NEAR(GetMetricEval(metric,
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
// Copyright by Contributors
|
||||
#include <xgboost/objective.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
#include <limits>
|
||||
|
||||
#include "../helpers.h"
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(HingeObj)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("binary:hinge");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
obj->Configure(args);
|
||||
xgboost::LearnerTrainParam tparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("binary:hinge", &tparam);
|
||||
|
||||
xgboost::bst_float eps = std::numeric_limits<xgboost::bst_float>::min();
|
||||
CheckObjFunction(obj,
|
||||
{-1.0f, -0.5f, 0.5f, 1.0f, -1.0f, -0.5f, 0.5f, 1.0f},
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
/*!
|
||||
* Copyright 2018 XGBoost contributors
|
||||
* Copyright 2018-2019 XGBoost contributors
|
||||
*/
|
||||
#include <xgboost/objective.h>
|
||||
|
||||
#include <xgboost/generic_parameters.h>
|
||||
#include "../../src/common/common.h"
|
||||
#include "../helpers.h"
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(SoftmaxMultiClassObjGPair)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("multi:softmax");
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args {{"num_class", "3"}};
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("multi:softmax", &lparam);
|
||||
|
||||
obj->Configure(args);
|
||||
CheckObjFunction(obj,
|
||||
{1.0f, 0.0f, 2.0f, 2.0f, 0.0f, 1.0f}, // preds
|
||||
@ -22,9 +25,11 @@ TEST(Objective, DeclareUnifiedTest(SoftmaxMultiClassObjGPair)) {
|
||||
}
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(SoftmaxMultiClassBasic)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("multi:softmax");
|
||||
std::vector<std::pair<std::string, std::string>> args
|
||||
{std::pair<std::string, std::string>("num_class", "3")};
|
||||
auto lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args{
|
||||
std::pair<std::string, std::string>("num_class", "3")};
|
||||
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("multi:softmax", &lparam);
|
||||
obj->Configure(args);
|
||||
|
||||
xgboost::HostDeviceVector<xgboost::bst_float> io_preds = {2.0f, 0.0f, 1.0f,
|
||||
@ -42,9 +47,11 @@ TEST(Objective, DeclareUnifiedTest(SoftmaxMultiClassBasic)) {
|
||||
}
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(SoftprobMultiClassBasic)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("multi:softprob");
|
||||
std::vector<std::pair<std::string, std::string>> args
|
||||
{std::pair<std::string, std::string>("num_class", "3")};
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args {
|
||||
std::pair<std::string, std::string>("num_class", "3")};
|
||||
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("multi:softprob", &lparam);
|
||||
obj->Configure(args);
|
||||
|
||||
xgboost::HostDeviceVector<xgboost::bst_float> io_preds = {2.0f, 0.0f, 1.0f};
|
||||
|
||||
@ -1,13 +1,18 @@
|
||||
// Copyright by Contributors
|
||||
#include <gtest/gtest.h>
|
||||
#include <xgboost/objective.h>
|
||||
#include <xgboost/generic_parameters.h>
|
||||
|
||||
#include "../helpers.h"
|
||||
|
||||
TEST(Objective, UnknownFunction) {
|
||||
xgboost::ObjFunction* obj = nullptr;
|
||||
EXPECT_ANY_THROW(obj = xgboost::ObjFunction::Create("unknown_name"));
|
||||
EXPECT_NO_THROW(obj = xgboost::ObjFunction::Create("reg:squarederror"));
|
||||
xgboost::LearnerTrainParam tparam;
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
tparam.InitAllowUnknown(args);
|
||||
|
||||
EXPECT_ANY_THROW(obj = xgboost::ObjFunction::Create("unknown_name", &tparam));
|
||||
EXPECT_NO_THROW(obj = xgboost::ObjFunction::Create("reg:squarederror", &tparam));
|
||||
if (obj) {
|
||||
delete obj;
|
||||
}
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
// Copyright by Contributors
|
||||
#include <xgboost/objective.h>
|
||||
|
||||
#include <xgboost/generic_parameters.h>
|
||||
#include "../helpers.h"
|
||||
|
||||
TEST(Objective, PairwiseRankingGPair) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("rank:pairwise");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam tparam;
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
tparam.InitAllowUnknown(args);
|
||||
|
||||
xgboost::ObjFunction * obj =
|
||||
xgboost::ObjFunction::Create("rank:pairwise", &tparam);
|
||||
obj->Configure(args);
|
||||
// Test with setting sample weight to second query group
|
||||
CheckRankingObjFunction(obj,
|
||||
|
||||
@ -3,12 +3,16 @@
|
||||
*/
|
||||
#include <gtest/gtest.h>
|
||||
#include <xgboost/objective.h>
|
||||
|
||||
#include <xgboost/generic_parameters.h>
|
||||
#include "../helpers.h"
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(LinearRegressionGPair)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:squarederror");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam tparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
|
||||
xgboost::ObjFunction * obj =
|
||||
xgboost::ObjFunction::Create("reg:squarederror", &tparam);
|
||||
|
||||
obj->Configure(args);
|
||||
CheckObjFunction(obj,
|
||||
{0, 0.1f, 0.9f, 1, 0, 0.1f, 0.9f, 1},
|
||||
@ -28,8 +32,10 @@ TEST(Objective, DeclareUnifiedTest(LinearRegressionGPair)) {
|
||||
}
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(LogisticRegressionGPair)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:logistic");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam tparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:logistic", &tparam);
|
||||
|
||||
obj->Configure(args);
|
||||
CheckObjFunction(obj,
|
||||
{ 0, 0.1f, 0.9f, 1, 0, 0.1f, 0.9f, 1}, // preds
|
||||
@ -42,8 +48,10 @@ TEST(Objective, DeclareUnifiedTest(LogisticRegressionGPair)) {
|
||||
}
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(LogisticRegressionBasic)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:logistic");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:logistic", &lparam);
|
||||
|
||||
obj->Configure(args);
|
||||
|
||||
// test label validation
|
||||
@ -70,8 +78,10 @@ TEST(Objective, DeclareUnifiedTest(LogisticRegressionBasic)) {
|
||||
}
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(LogisticRawGPair)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("binary:logitraw");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("binary:logitraw", &lparam);
|
||||
|
||||
obj->Configure(args);
|
||||
CheckObjFunction(obj,
|
||||
{ 0, 0.1f, 0.9f, 1, 0, 0.1f, 0.9f, 1},
|
||||
@ -84,8 +94,10 @@ TEST(Objective, DeclareUnifiedTest(LogisticRawGPair)) {
|
||||
}
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(PoissonRegressionGPair)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("count:poisson");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("count:poisson", &lparam);
|
||||
|
||||
args.emplace_back(std::make_pair("max_delta_step", "0.1f"));
|
||||
obj->Configure(args);
|
||||
CheckObjFunction(obj,
|
||||
@ -104,8 +116,10 @@ TEST(Objective, DeclareUnifiedTest(PoissonRegressionGPair)) {
|
||||
}
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(PoissonRegressionBasic)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("count:poisson");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("count:poisson", &lparam);
|
||||
|
||||
obj->Configure(args);
|
||||
|
||||
// test label validation
|
||||
@ -130,8 +144,10 @@ TEST(Objective, DeclareUnifiedTest(PoissonRegressionBasic)) {
|
||||
}
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(GammaRegressionGPair)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:gamma");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:gamma", &lparam);
|
||||
|
||||
obj->Configure(args);
|
||||
CheckObjFunction(obj,
|
||||
{0, 0.1f, 0.9f, 1, 0, 0.1f, 0.9f, 1},
|
||||
@ -149,8 +165,10 @@ TEST(Objective, DeclareUnifiedTest(GammaRegressionGPair)) {
|
||||
}
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(GammaRegressionBasic)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:gamma");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:gamma", &lparam);
|
||||
|
||||
obj->Configure(args);
|
||||
|
||||
// test label validation
|
||||
@ -175,8 +193,10 @@ TEST(Objective, DeclareUnifiedTest(GammaRegressionBasic)) {
|
||||
}
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(TweedieRegressionGPair)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:tweedie");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:tweedie", &lparam);
|
||||
|
||||
args.emplace_back(std::make_pair("tweedie_variance_power", "1.1f"));
|
||||
obj->Configure(args);
|
||||
CheckObjFunction(obj,
|
||||
@ -195,9 +215,65 @@ TEST(Objective, DeclareUnifiedTest(TweedieRegressionGPair)) {
|
||||
delete obj;
|
||||
}
|
||||
|
||||
#if defined(__CUDACC__)
|
||||
TEST(Objective, CPU_vs_CUDA) {
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, 1);
|
||||
|
||||
xgboost::ObjFunction * obj =
|
||||
xgboost::ObjFunction::Create("reg:squarederror", &lparam);
|
||||
xgboost::HostDeviceVector<xgboost::GradientPair> cpu_out_preds;
|
||||
xgboost::HostDeviceVector<xgboost::GradientPair> cuda_out_preds;
|
||||
|
||||
constexpr size_t kRows = 400;
|
||||
constexpr size_t kCols = 100;
|
||||
auto ppdmat = xgboost::CreateDMatrix(kRows, kCols, 0, 0);
|
||||
xgboost::HostDeviceVector<float> preds;
|
||||
preds.Resize(kRows);
|
||||
auto& h_preds = preds.HostVector();
|
||||
for (size_t i = 0; i < h_preds.size(); ++i) {
|
||||
h_preds[i] = static_cast<float>(i);
|
||||
}
|
||||
auto& info = (*ppdmat)->Info();
|
||||
|
||||
info.labels_.Resize(kRows);
|
||||
auto& h_labels = info.labels_.HostVector();
|
||||
for (size_t i = 0; i < h_labels.size(); ++i) {
|
||||
h_labels[i] = 1 / (float)(i+1);
|
||||
}
|
||||
|
||||
{
|
||||
// CPU
|
||||
lparam.n_gpus = 0;
|
||||
obj->GetGradient(preds, info, 0, &cpu_out_preds);
|
||||
}
|
||||
{
|
||||
// CUDA
|
||||
lparam.n_gpus = 1;
|
||||
obj->GetGradient(preds, info, 0, &cuda_out_preds);
|
||||
}
|
||||
|
||||
auto& h_cpu_out = cpu_out_preds.HostVector();
|
||||
auto& h_cuda_out = cuda_out_preds.HostVector();
|
||||
|
||||
float sgrad = 0;
|
||||
float shess = 0;
|
||||
for (size_t i = 0; i < kRows; ++i) {
|
||||
sgrad += std::pow(h_cpu_out[i].GetGrad() - h_cuda_out[i].GetGrad(), 2);
|
||||
shess += std::pow(h_cpu_out[i].GetHess() - h_cuda_out[i].GetHess(), 2);
|
||||
}
|
||||
ASSERT_NEAR(sgrad, 0.0f, xgboost::kRtEps);
|
||||
ASSERT_NEAR(shess, 0.0f, xgboost::kRtEps);
|
||||
|
||||
delete ppdmat;
|
||||
delete obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(Objective, DeclareUnifiedTest(TweedieRegressionBasic)) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:tweedie");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, NGPUS);
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("reg:tweedie", &lparam);
|
||||
|
||||
obj->Configure(args);
|
||||
|
||||
// test label validation
|
||||
@ -225,8 +301,11 @@ TEST(Objective, DeclareUnifiedTest(TweedieRegressionBasic)) {
|
||||
// CoxRegression not implemented in GPU code, no need for testing.
|
||||
#if !defined(__CUDACC__)
|
||||
TEST(Objective, CoxRegressionGPair) {
|
||||
xgboost::ObjFunction * obj = xgboost::ObjFunction::Create("survival:cox");
|
||||
std::vector<std::pair<std::string, std::string> > args;
|
||||
xgboost::LearnerTrainParam lparam = xgboost::CreateEmptyGenericParam(0, 0);
|
||||
std::vector<std::pair<std::string, std::string>> args;
|
||||
xgboost::ObjFunction * obj =
|
||||
xgboost::ObjFunction::Create("survival:cox", &lparam);
|
||||
|
||||
obj->Configure(args);
|
||||
CheckObjFunction(obj,
|
||||
{ 0, 0.1f, 0.9f, 1, 0, 0.1f, 0.9f, 1},
|
||||
|
||||
@ -6,8 +6,9 @@
|
||||
|
||||
namespace xgboost {
|
||||
TEST(cpu_predictor, Test) {
|
||||
auto lparam = CreateEmptyGenericParam(0, 0);
|
||||
std::unique_ptr<Predictor> cpu_predictor =
|
||||
std::unique_ptr<Predictor>(Predictor::Create("cpu_predictor"));
|
||||
std::unique_ptr<Predictor>(Predictor::Create("cpu_predictor", &lparam));
|
||||
|
||||
gbm::GBTreeModel model = CreateTestModel();
|
||||
|
||||
@ -56,9 +57,9 @@ TEST(cpu_predictor, Test) {
|
||||
|
||||
TEST(cpu_predictor, ExternalMemoryTest) {
|
||||
std::unique_ptr<DMatrix> dmat = CreateSparsePageDMatrix(12, 64);
|
||||
|
||||
auto lparam = CreateEmptyGenericParam(0, 0);
|
||||
std::unique_ptr<Predictor> cpu_predictor =
|
||||
std::unique_ptr<Predictor>(Predictor::Create("cpu_predictor"));
|
||||
std::unique_ptr<Predictor>(Predictor::Create("cpu_predictor", &lparam));
|
||||
|
||||
gbm::GBTreeModel model = CreateTestModel();
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
|
||||
/*!
|
||||
* Copyright 2017 XGBoost contributors
|
||||
* Copyright 2017-2019 XGBoost contributors
|
||||
*/
|
||||
#include <dmlc/logging.h>
|
||||
#include <dmlc/filesystem.h>
|
||||
@ -25,10 +25,13 @@ namespace xgboost {
|
||||
namespace predictor {
|
||||
|
||||
TEST(gpu_predictor, Test) {
|
||||
auto cpu_lparam = CreateEmptyGenericParam(0, 0);
|
||||
auto gpu_lparam = CreateEmptyGenericParam(0, 1);
|
||||
|
||||
std::unique_ptr<Predictor> gpu_predictor =
|
||||
std::unique_ptr<Predictor>(Predictor::Create("gpu_predictor"));
|
||||
std::unique_ptr<Predictor>(Predictor::Create("gpu_predictor", &gpu_lparam));
|
||||
std::unique_ptr<Predictor> cpu_predictor =
|
||||
std::unique_ptr<Predictor>(Predictor::Create("cpu_predictor"));
|
||||
std::unique_ptr<Predictor>(Predictor::Create("cpu_predictor", &cpu_lparam));
|
||||
|
||||
gpu_predictor->Init({}, {});
|
||||
cpu_predictor->Init({}, {});
|
||||
@ -85,8 +88,9 @@ TEST(gpu_predictor, Test) {
|
||||
}
|
||||
|
||||
TEST(gpu_predictor, ExternalMemoryTest) {
|
||||
auto lparam = CreateEmptyGenericParam(0, 1);
|
||||
std::unique_ptr<Predictor> gpu_predictor =
|
||||
std::unique_ptr<Predictor>(Predictor::Create("gpu_predictor"));
|
||||
std::unique_ptr<Predictor>(Predictor::Create("gpu_predictor", &lparam));
|
||||
gpu_predictor->Init({}, {});
|
||||
gbm::GBTreeModel model = CreateTestModel();
|
||||
std::unique_ptr<DMatrix> dmat = CreateSparsePageDMatrix(32, 64);
|
||||
@ -127,8 +131,7 @@ TEST(gpu_predictor, ExternalMemoryTest) {
|
||||
#if defined(XGBOOST_USE_NCCL)
|
||||
// Test whether pickling preserves predictor parameters
|
||||
TEST(gpu_predictor, MGPU_PicklingTest) {
|
||||
int ngpu;
|
||||
dh::safe_cuda(cudaGetDeviceCount(&ngpu));
|
||||
int const ngpu = GPUSet::AllVisible().Size();
|
||||
|
||||
dmlc::TemporaryDirectory tempdir;
|
||||
const std::string tmp_file = tempdir.path + "/simple.libsvm";
|
||||
@ -201,12 +204,14 @@ TEST(gpu_predictor, MGPU_PicklingTest) {
|
||||
|
||||
// multi-GPU predictor test
|
||||
TEST(gpu_predictor, MGPU_Test) {
|
||||
std::unique_ptr<Predictor> gpu_predictor =
|
||||
std::unique_ptr<Predictor>(Predictor::Create("gpu_predictor"));
|
||||
std::unique_ptr<Predictor> cpu_predictor =
|
||||
std::unique_ptr<Predictor>(Predictor::Create("cpu_predictor"));
|
||||
auto cpu_lparam = CreateEmptyGenericParam(0, 0);
|
||||
auto gpu_lparam = CreateEmptyGenericParam(0, -1);
|
||||
|
||||
std::unique_ptr<Predictor> gpu_predictor =
|
||||
std::unique_ptr<Predictor>(Predictor::Create("gpu_predictor", &gpu_lparam));
|
||||
std::unique_ptr<Predictor> cpu_predictor =
|
||||
std::unique_ptr<Predictor>(Predictor::Create("cpu_predictor", &cpu_lparam));
|
||||
|
||||
gpu_predictor->Init({std::pair<std::string, std::string>("n_gpus", "-1")}, {});
|
||||
cpu_predictor->Init({}, {});
|
||||
|
||||
for (size_t i = 1; i < 33; i *= 2) {
|
||||
@ -234,9 +239,11 @@ TEST(gpu_predictor, MGPU_Test) {
|
||||
|
||||
// multi-GPU predictor external memory test
|
||||
TEST(gpu_predictor, MGPU_ExternalMemoryTest) {
|
||||
auto gpu_lparam = CreateEmptyGenericParam(0, -1);
|
||||
|
||||
std::unique_ptr<Predictor> gpu_predictor =
|
||||
std::unique_ptr<Predictor>(Predictor::Create("gpu_predictor"));
|
||||
gpu_predictor->Init({std::pair<std::string, std::string>("n_gpus", "-1")}, {});
|
||||
std::unique_ptr<Predictor>(Predictor::Create("gpu_predictor", &gpu_lparam));
|
||||
gpu_predictor->Init({}, {});
|
||||
|
||||
gbm::GBTreeModel model = CreateTestModel();
|
||||
const int n_classes = 3;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vector>
|
||||
#include "helpers.h"
|
||||
|
||||
#include "xgboost/learner.h"
|
||||
#include "dmlc/filesystem.h"
|
||||
|
||||
@ -115,4 +116,119 @@ TEST(Learner, SLOW_CheckMultiBatch) {
|
||||
learner->UpdateOneIter(0, dmat.get());
|
||||
}
|
||||
|
||||
#if defined(XGBOOST_USE_CUDA)
|
||||
|
||||
TEST(Learner, IO) {
|
||||
using Arg = std::pair<std::string, std::string>;
|
||||
size_t constexpr kRows = 10;
|
||||
auto pp_dmat = CreateDMatrix(kRows, 10, 0);
|
||||
auto p_dmat = *pp_dmat;
|
||||
|
||||
std::vector<bst_float> labels(kRows);
|
||||
for (size_t i = 0; i < labels.size(); ++i) {
|
||||
labels[i] = i;
|
||||
}
|
||||
p_dmat->Info().labels_.HostVector() = labels;
|
||||
std::vector<std::shared_ptr<DMatrix>> mat {p_dmat};
|
||||
|
||||
std::unique_ptr<Learner> learner {Learner::Create(mat)};
|
||||
learner->Configure({Arg{"tree_method", "auto"},
|
||||
Arg{"predictor", "gpu_predictor"},
|
||||
Arg{"n_gpus", "-1"}});
|
||||
learner->InitModel();
|
||||
learner->UpdateOneIter(0, p_dmat.get());
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().gpu_id, 0);
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().n_gpus, -1);
|
||||
|
||||
dmlc::TemporaryDirectory tempdir;
|
||||
const std::string fname = tempdir.path + "/model.bst";
|
||||
|
||||
{
|
||||
// Create a scope to close the stream before next read.
|
||||
std::unique_ptr<dmlc::Stream> fo(dmlc::Stream::Create(fname.c_str(), "w"));
|
||||
learner->Save(fo.get());
|
||||
}
|
||||
|
||||
std::unique_ptr<dmlc::Stream> fi(dmlc::Stream::Create(fname.c_str(), "r"));
|
||||
learner->Load(fi.get());
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().gpu_id, 0);
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().n_gpus, 0);
|
||||
|
||||
delete pp_dmat;
|
||||
}
|
||||
|
||||
// Tests for automatic GPU configuration.
|
||||
TEST(Learner, GPUConfiguration) {
|
||||
using Arg = std::pair<std::string, std::string>;
|
||||
size_t constexpr kRows = 10;
|
||||
auto pp_dmat = CreateDMatrix(kRows, 10, 0);
|
||||
auto p_dmat = *pp_dmat;
|
||||
std::vector<std::shared_ptr<DMatrix>> mat {p_dmat};
|
||||
std::vector<bst_float> labels(kRows);
|
||||
for (size_t i = 0; i < labels.size(); ++i) {
|
||||
labels[i] = i;
|
||||
}
|
||||
p_dmat->Info().labels_.HostVector() = labels;
|
||||
{
|
||||
std::unique_ptr<Learner> learner {Learner::Create(mat)};
|
||||
learner->Configure({Arg{"booster", "gblinear"},
|
||||
Arg{"updater", "gpu_coord_descent"}});
|
||||
learner->InitModel();
|
||||
learner->UpdateOneIter(0, p_dmat.get());
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().gpu_id, 0);
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().n_gpus, 1);
|
||||
}
|
||||
{
|
||||
std::unique_ptr<Learner> learner {Learner::Create(mat)};
|
||||
learner->Configure({Arg{"tree_method", "gpu_exact"}});
|
||||
learner->InitModel();
|
||||
learner->UpdateOneIter(0, p_dmat.get());
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().gpu_id, 0);
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().n_gpus, 1);
|
||||
}
|
||||
{
|
||||
std::unique_ptr<Learner> learner {Learner::Create(mat)};
|
||||
learner->Configure({Arg{"tree_method", "gpu_hist"}});
|
||||
learner->InitModel();
|
||||
learner->UpdateOneIter(0, p_dmat.get());
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().gpu_id, 0);
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().n_gpus, 1);
|
||||
}
|
||||
{
|
||||
// with CPU algorithm
|
||||
std::unique_ptr<Learner> learner {Learner::Create(mat)};
|
||||
learner->Configure({Arg{"tree_method", "hist"}});
|
||||
learner->InitModel();
|
||||
learner->UpdateOneIter(0, p_dmat.get());
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().gpu_id, 0);
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().n_gpus, 0);
|
||||
}
|
||||
{
|
||||
// with CPU algorithm, but `n_gpus` takes priority
|
||||
std::unique_ptr<Learner> learner {Learner::Create(mat)};
|
||||
learner->Configure({Arg{"tree_method", "hist"},
|
||||
Arg{"n_gpus", "1"}});
|
||||
learner->InitModel();
|
||||
learner->UpdateOneIter(0, p_dmat.get());
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().gpu_id, 0);
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().n_gpus, 1);
|
||||
}
|
||||
{
|
||||
// With CPU algorithm but GPU Predictor, this is to simulate when
|
||||
// XGBoost is only used for prediction, so tree method is not
|
||||
// specified.
|
||||
std::unique_ptr<Learner> learner {Learner::Create(mat)};
|
||||
learner->Configure({Arg{"tree_method", "hist"},
|
||||
Arg{"predictor", "gpu_predictor"}});
|
||||
learner->InitModel();
|
||||
learner->UpdateOneIter(0, p_dmat.get());
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().gpu_id, 0);
|
||||
ASSERT_EQ(learner->GetLearnerTrainParameter().n_gpus, 1);
|
||||
}
|
||||
|
||||
delete pp_dmat;
|
||||
}
|
||||
|
||||
#endif // XGBOOST_USE_CUDA
|
||||
|
||||
} // namespace xgboost
|
||||
|
||||
@ -52,6 +52,9 @@ TEST(Logging, Basic) {
|
||||
LOG(CONSOLE) << "Test Log Console"; // ignore global setting.
|
||||
output = testing::internal::GetCapturedStderr();
|
||||
ASSERT_NE(output.find("Test Log Console"), std::string::npos);
|
||||
|
||||
args["verbosity"] = "1"; // restore
|
||||
ConsoleLogger::Configure(args.cbegin(), args.cend());
|
||||
}
|
||||
|
||||
} // namespace xgboost
|
||||
|
||||
@ -1,7 +1,12 @@
|
||||
// Copyright by Contributors
|
||||
#include <gtest/gtest.h>
|
||||
#include <xgboost/logging.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
std::vector<std::pair<std::string, std::string>> args {{"verbosity", "3"}};
|
||||
xgboost::ConsoleLogger::Configure(args.begin(), args.end());
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
testing::FLAGS_gtest_death_test_style = "threadsafe";
|
||||
return RUN_ALL_TESTS();
|
||||
|
||||
@ -12,12 +12,10 @@ namespace tree {
|
||||
|
||||
TEST(GPUExact, Update) {
|
||||
using Arg = std::pair<std::string, std::string>;
|
||||
std::vector<Arg> args{
|
||||
{"n_gpus", "1"},
|
||||
{"gpu_id", "0"},
|
||||
{"max_depth", "1"}};
|
||||
auto lparam = CreateEmptyGenericParam(0, 1);
|
||||
std::vector<Arg> args{{"max_depth", "1"}};
|
||||
|
||||
auto* p_gpuexact_maker = TreeUpdater::Create("grow_gpu");
|
||||
auto* p_gpuexact_maker = TreeUpdater::Create("grow_gpu", &lparam);
|
||||
p_gpuexact_maker->Init(args);
|
||||
|
||||
size_t constexpr kNRows = 4;
|
||||
|
||||
@ -86,7 +86,6 @@ TEST(GpuHist, BuildGidxDense) {
|
||||
int constexpr kNRows = 16, kNCols = 8;
|
||||
TrainParam param;
|
||||
param.max_depth = 1;
|
||||
param.n_gpus = 1;
|
||||
param.max_leaves = 0;
|
||||
|
||||
DeviceShard<GradientPairPrecise> shard(0, 0, 0, kNRows, param, kNCols);
|
||||
@ -125,7 +124,6 @@ TEST(GpuHist, BuildGidxSparse) {
|
||||
int constexpr kNRows = 16, kNCols = 8;
|
||||
TrainParam param;
|
||||
param.max_depth = 1;
|
||||
param.n_gpus = 1;
|
||||
param.max_leaves = 0;
|
||||
|
||||
DeviceShard<GradientPairPrecise> shard(0, 0, 0, kNRows, param, kNCols);
|
||||
@ -169,7 +167,6 @@ void TestBuildHist(GPUHistBuilderBase<GradientSumT>& builder) {
|
||||
|
||||
TrainParam param;
|
||||
param.max_depth = 6;
|
||||
param.n_gpus = 1;
|
||||
param.max_leaves = 0;
|
||||
|
||||
DeviceShard<GradientSumT> shard(0, 0, 0, kNRows, param, kNCols);
|
||||
@ -264,7 +261,6 @@ TEST(GpuHist, EvaluateSplits) {
|
||||
|
||||
TrainParam param;
|
||||
param.max_depth = 1;
|
||||
param.n_gpus = 1;
|
||||
param.colsample_bynode = 1;
|
||||
param.colsample_bylevel = 1;
|
||||
param.colsample_bytree = 1;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright 2018 by Contributors
|
||||
* Copyright 2018-2019 by Contributors
|
||||
*/
|
||||
#include "../helpers.h"
|
||||
#include "../../../src/common/host_device_vector.h"
|
||||
@ -29,12 +29,14 @@ TEST(Updater, Prune) {
|
||||
{0.25f, 0.24f}, {0.25f, 0.24f}, {0.25f, 0.24f}, {0.25f, 0.24f} };
|
||||
auto dmat = CreateDMatrix(32, 16, 0.4, 3);
|
||||
|
||||
auto lparam = CreateEmptyGenericParam(0, 0);
|
||||
|
||||
// prepare tree
|
||||
RegTree tree = RegTree();
|
||||
tree.param.InitAllowUnknown(cfg);
|
||||
std::vector<RegTree*> trees {&tree};
|
||||
// prepare pruner
|
||||
std::unique_ptr<TreeUpdater> pruner(TreeUpdater::Create("prune"));
|
||||
std::unique_ptr<TreeUpdater> pruner(TreeUpdater::Create("prune", &lparam));
|
||||
pruner->Init(cfg);
|
||||
|
||||
// loss_chg < min_split_loss;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright 2018 by Contributors
|
||||
* Copyright 2018-2019 by Contributors
|
||||
*/
|
||||
#include "../helpers.h"
|
||||
#include "../../../src/common/host_device_vector.h"
|
||||
@ -25,9 +25,10 @@ TEST(Updater, Refresh) {
|
||||
{"reg_lambda", "1"}};
|
||||
|
||||
RegTree tree = RegTree();
|
||||
auto lparam = CreateEmptyGenericParam(0, 0);
|
||||
tree.param.InitAllowUnknown(cfg);
|
||||
std::vector<RegTree*> trees {&tree};
|
||||
std::unique_ptr<TreeUpdater> refresher(TreeUpdater::Create("refresh"));
|
||||
std::unique_ptr<TreeUpdater> refresher(TreeUpdater::Create("refresh", &lparam));
|
||||
|
||||
tree.ExpandNode(0, 2, 0.2f, false, 0.0, 0.2f, 0.8f, 0.0f, 0.0f);
|
||||
int cleft = tree[0].LeftChild();
|
||||
|
||||
20
tests/python-gpu/load_pickle.py
Normal file
20
tests/python-gpu/load_pickle.py
Normal file
@ -0,0 +1,20 @@
|
||||
'''Loading a pickled model generated by test_pickling.py'''
|
||||
import pickle
|
||||
import unittest
|
||||
import os
|
||||
import xgboost as xgb
|
||||
import sys
|
||||
|
||||
sys.path.append("tests/python")
|
||||
from test_pickling import build_dataset, model_path
|
||||
|
||||
|
||||
class TestLoadPickle(unittest.TestCase):
|
||||
def test_load_pkl(self):
|
||||
assert os.environ['CUDA_VISIBLE_DEVICES'] == ''
|
||||
with open(model_path, 'rb') as fd:
|
||||
bst = pickle.load(fd)
|
||||
x, y = build_dataset()
|
||||
test_x = xgb.DMatrix(x)
|
||||
res = bst.predict(test_x)
|
||||
assert len(res) == 10
|
||||
@ -29,6 +29,7 @@ class TestGPUPredict(unittest.TestCase):
|
||||
"objective": "binary:logistic",
|
||||
"predictor": "gpu_predictor",
|
||||
'eval_metric': 'auc',
|
||||
'verbosity': '3'
|
||||
}
|
||||
bst = xgb.train(param, dtrain, iterations, evals=watchlist,
|
||||
evals_result=res)
|
||||
@ -42,12 +43,13 @@ class TestGPUPredict(unittest.TestCase):
|
||||
cpu_pred_train = bst_cpu.predict(dtrain, output_margin=True)
|
||||
cpu_pred_test = bst_cpu.predict(dtest, output_margin=True)
|
||||
cpu_pred_val = bst_cpu.predict(dval, output_margin=True)
|
||||
|
||||
np.testing.assert_allclose(cpu_pred_train, gpu_pred_train,
|
||||
rtol=1e-5)
|
||||
rtol=1e-3)
|
||||
np.testing.assert_allclose(cpu_pred_val, gpu_pred_val,
|
||||
rtol=1e-5)
|
||||
rtol=1e-3)
|
||||
np.testing.assert_allclose(cpu_pred_test, gpu_pred_test,
|
||||
rtol=1e-5)
|
||||
rtol=1e-3)
|
||||
|
||||
def non_decreasing(self, L):
|
||||
return all((x - y) < 0.001 for x, y in zip(L, L[1:]))
|
||||
|
||||
53
tests/python-gpu/test_pickling.py
Normal file
53
tests/python-gpu/test_pickling.py
Normal file
@ -0,0 +1,53 @@
|
||||
'''Test model IO with pickle.'''
|
||||
import pickle
|
||||
import unittest
|
||||
import numpy as np
|
||||
import subprocess
|
||||
import os
|
||||
import xgboost as xgb
|
||||
|
||||
model_path = './model.pkl'
|
||||
|
||||
|
||||
def build_dataset():
|
||||
N = 10
|
||||
x = np.linspace(0, N*N, N*N)
|
||||
x = x.reshape((N, N))
|
||||
y = np.linspace(0, N, N)
|
||||
return x, y
|
||||
|
||||
|
||||
class TestPickling(unittest.TestCase):
|
||||
def test_pickling(self):
|
||||
x, y = build_dataset()
|
||||
train_x = xgb.DMatrix(x, label=y)
|
||||
param = {'tree_method': 'gpu_hist',
|
||||
'gpu_id': 0,
|
||||
'n_gpus': -1,
|
||||
'verbosity': 1}
|
||||
bst = xgb.train(param, train_x)
|
||||
|
||||
with open(model_path, 'wb') as fd:
|
||||
pickle.dump(bst, fd)
|
||||
args = ["pytest",
|
||||
"--verbose",
|
||||
"-s",
|
||||
"--fulltrace",
|
||||
"./tests/python-gpu/load_pickle.py"]
|
||||
command = ''
|
||||
for arg in args:
|
||||
command += arg
|
||||
command += ' '
|
||||
|
||||
cuda_environment = {'CUDA_VISIBLE_DEVICES': ''}
|
||||
env = os.environ
|
||||
# Passing new_environment directly to `env' argument results
|
||||
# in failure on Windows:
|
||||
# Fatal Python error: _Py_HashRandomization_Init: failed to
|
||||
# get random numbers to initialize Python
|
||||
env.update(cuda_environment)
|
||||
|
||||
# Load model in a CPU only environment.
|
||||
status = subprocess.call(command, env=env, shell=True)
|
||||
assert status == 0
|
||||
os.remove(model_path)
|
||||
Loading…
x
Reference in New Issue
Block a user