Skip to content

Commit

Permalink
[PLUGIN] Add plugin system
Browse files Browse the repository at this point in the history
  • Loading branch information
tqchen committed Jan 16, 2016
1 parent 36c389a commit 96f4542
Show file tree
Hide file tree
Showing 14 changed files with 457 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,4 @@ build
config.mk
xgboost
*.data
build_plugin
25 changes: 18 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# flags by plugin
PLUGIN_OBJS=
PLUGIN_LDFLAGS=
PLUGIN_CFLAGS=

ifndef config
ifneq ("$(wildcard ./config.mk)","")
config = config.mk
Expand Down Expand Up @@ -36,8 +41,8 @@ ifeq ($(OS), Windows_NT)
export CC = gcc -m64
endif

export LDFLAGS= -pthread -lm $(ADD_LDFLAGS) $(DMLC_LDFLAGS)
export CFLAGS= -std=c++0x -Wall -O3 -msse2 -Wno-unknown-pragmas -funroll-loops -fPIC -Iinclude $(ADD_CFLAGS)
export LDFLAGS= -pthread -lm $(ADD_LDFLAGS) $(DMLC_LDFLAGS) $(PLUGIN_LDFLAGS)
export CFLAGS= -std=c++0x -Wall -O3 -msse2 -Wno-unknown-pragmas -funroll-loops -fPIC -Iinclude $(ADD_CFLAGS) $(PLUGIN_CFLAGS)
CFLAGS += -I$(DMLC_CORE)/include -I$(RABIT)/include
#java include path
export JAVAINCFLAGS = -I${JAVA_HOME}/include -I./java
Expand Down Expand Up @@ -76,7 +81,7 @@ $(RABIT)/lib/$(LIB_RABIT):
java: java/libxgboost4j.so

SRC = $(wildcard src/*.cc src/*/*.cc)
ALL_OBJ = $(patsubst src/%.cc, build/%.o, $(SRC))
ALL_OBJ = $(patsubst src/%.cc, build/%.o, $(SRC)) $(PLUGIN_OBJS)
AMALGA_OBJ = amalgamation/xgboost-all0.o
LIB_DEP = $(DMLC_CORE)/libdmlc.a $(RABIT)/lib/$(LIB_RABIT)
ALL_DEP = $(filter-out build/cli_main.o, $(ALL_OBJ)) $(LIB_DEP)
Expand All @@ -87,6 +92,11 @@ build/%.o: src/%.cc
$(CXX) $(CFLAGS) -MM -MT build/$*.o $< >build/$*.d
$(CXX) -c $(CFLAGS) -c $< -o $@

build_plugin/%.o: plugin/%.cc
@mkdir -p $(@D)
$(CXX) $(CFLAGS) -MM -MT build_plugin/$*.o $< >build_plugin/$*.d
$(CXX) -c $(CFLAGS) -c $< -o $@

# The should be equivalent to $(ALL_OBJ) except for build/cli_main.o
amalgamation/xgboost-all0.o: amalgamation/xgboost-all0.cc
$(CXX) -c $(CFLAGS) -c $< -o $@
Expand All @@ -104,20 +114,20 @@ lib/libxgboost.so: $(ALL_DEP)
@mkdir -p $(@D)
$(CXX) $(CFLAGS) -shared -o $@ $(filter %.o %.a, $^) $(LDFLAGS)

java/libxgboost4j.so: java/xgboost4j_wrapper.cpp lib/libxgboost.a $(LIB_DEP)
java/libxgboost4j.so: java/xgboost4j_wrapper.cpp $(ALL_DEP)
$(CXX) $(CFLAGS) $(JAVAINCFLAGS) -shared -o $@ $(filter %.cpp %.o %.a, $^) $(LDFLAGS)

xgboost: $(CLI_OBJ) lib/libxgboost.a $(LIB_DEP)
xgboost: $(CLI_OBJ) $(ALL_DEP)
$(CXX) $(CFLAGS) -o $@ $(filter %.o %.a, $^) $(LDFLAGS)

rcpplint:
python2 dmlc-core/scripts/lint.py xgboost ${LINT_LANG} R-package/src

lint: rcpplint
python2 dmlc-core/scripts/lint.py xgboost ${LINT_LANG} include src
python2 dmlc-core/scripts/lint.py xgboost ${LINT_LANG} include src plugin

clean:
$(RM) -rf build lib bin *~ */*~ */*/*~ */*/*/*~ amalgamation/*.o xgboost
$(RM) -rf build build_plugin lib bin *~ */*~ */*/*~ */*/*/*~ amalgamation/*.o xgboost

clean_all: clean
cd $(DMLC_CORE); make clean; cd -
Expand Down Expand Up @@ -157,3 +167,4 @@ Rcheck:

-include build/*.d
-include build/*/*.d
-include build_plugin/*/*.d
6 changes: 6 additions & 0 deletions make/config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,9 @@ LIB_RABIT = librabit.a

# path to libjvm.so
LIBJVM=$(JAVA_HOME)/jre/lib/amd64/server

# List of additional plugins, checkout plugin folder.
# uncomment the following lines to include these plugins
# you can also add your own plugin like this

# include plugin/example/plugin.mk
32 changes: 32 additions & 0 deletions plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
XGBoost Plugins Modules
=======================
This folder contains plugin modules to xgboost that can be optionally installed.
The plugin system helps us to extend xgboost with additional features,
and add experimental features that may not yet ready to be included in main project.

To include a certain plugin, say ```plugin_a```, you only need to add the following line to the config.mk.

```makefile
# Add plugin by include the plugin in config
include plugin/plugin_a/plugin.mk
```

Then rebuild libxgboost by typing make, you can get a new library with the plugin enabled.

Link Static XGBoost Library with Plugins
----------------------------------------
This problem only happens when you link ```libxgboost.a```.
If you only use ```libxgboost.so```(this include python and other bindings),
you can ignore this section.

When you want to link ```libxgboost.a``` with additional plugins included,
you will need to enabled whole archeive via The following option.
```bash
--whole-archive libxgboost.a --no-whole-archive
```

Write Your Own Plugin
---------------------
You can plugin your own modules to xgboost by adding code to this folder,
without modification to the main code repo.
The [example](example) folder provides an example to write a plugin.
21 changes: 21 additions & 0 deletions plugin/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
XGBoost Plugin Example
======================
This folder provides an example of xgboost plugin.

There are three steps you need to to do to add plugin to xgboost
- Create your source .cc file, implement a new extension
- In this example [custom_obj.cc](custom_obj.cc)
- Register this extension to xgboost via registration macr
- In this example ```XGBOOST_REGISTER_OBJECTIVE``` in [this line](custom_obj.cc#L75)
- Create a [plugin.mk](plugin.mk) on this folder

To add this plugin, add the following line to ```config.mk```(template in make/config.mk).
```makefile
# Add plugin by include the plugin in config
include plugin/example/plugin.mk
```

Then you can test this plugin by using ```objective=mylogistic``` parameter.



80 changes: 80 additions & 0 deletions plugin/example/custom_obj.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*!
* Copyright 2015 by Contributors
* \file custom_metric.cc
* \brief This is an example to define plugin of xgboost.
* This plugin defines the additional metric function.
*/
#include <xgboost/base.h>
#include <dmlc/parameter.h>
#include <xgboost/objective.h>

namespace xgboost {
namespace obj {

// This is a helpful data structure to define parameters
// You do not have to use it.
// see http://dmlc-core.readthedocs.org/en/latest/parameter.html
// for introduction of this module.
struct MyLogisticParam : public dmlc::Parameter<MyLogisticParam> {
float scale_neg_weight;
// declare parameters
DMLC_DECLARE_PARAMETER(MyLogisticParam) {
DMLC_DECLARE_FIELD(scale_neg_weight).set_default(1.0f).set_lower_bound(0.0f)
.describe("Scale the weight of negative examples by this factor");
}
};

DMLC_REGISTER_PARAMETER(MyLogisticParam);

// Define a customized logistic regression objective in C++.
// Implement the interface.
class MyLogistic : public ObjFunction {
public:
void Configure(const std::vector<std::pair<std::string, std::string> >& args) override {
param_.InitAllowUnknown(args);
}
void GetGradient(const std::vector<float> &preds,
const MetaInfo &info,
int iter,
std::vector<bst_gpair> *out_gpair) override {
out_gpair->resize(preds.size());
for (size_t i = 0; i < preds.size(); ++i) {
float w = info.GetWeight(i);
// scale the negative examples!
if (info.labels[i] == 0.0f) w *= param_.scale_neg_weight;
// logistic transoformation
float p = 1.0f / (1.0f + expf(-preds[i]));
// this is the gradient
float grad = (p - info.labels[i]) * w;
// this is the second order gradient
float hess = p * (1.0f - p) * w;
out_gpair->at(i) = bst_gpair(grad, hess);
}
}
const char* DefaultEvalMetric() const override {
return "error";
}
void PredTransform(std::vector<float> *io_preds) override {
// transform margin value to probability.
std::vector<float> &preds = *io_preds;
for (size_t i = 0; i < preds.size(); ++i) {
preds[i] = 1.0f / (1.0f + expf(-preds[i]));
}
}
float ProbToMargin(float base_score) const override {
// transform probability to margin value
return -std::log(1.0f / base_score - 1.0f);
}

private:
MyLogisticParam param_;
};

// Finally register the objective function.
// After it succeeds you can try use xgboost with objective=mylogistic
XGBOOST_REGISTER_OBJECTIVE(MyLogistic, "mylogistic")
.describe("User defined logistic regression plugin")
.set_body([]() { return new MyLogistic(); });

} // namespace obj
} // namespace xgboost
4 changes: 4 additions & 0 deletions plugin/example/plugin.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Add the object files you like to include in this plugin.
PLUGIN_OBJS += build_plugin/example/custom_obj.o
# Add additional dependent libraries this plugin might have
PLUGIN_LDFLAGS +=
2 changes: 2 additions & 0 deletions plugin/lz4/plugin.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PLUGIN_OBJS += build_plugin/lz4/sparse_page_lz4_format.o
PLUGIN_LDFLAGS += -llz4
Loading

0 comments on commit 96f4542

Please sign in to comment.