forpy
2
|
Elegant Decision Forests in Python. Fast, clean and clear C++14 implementation with no dependencies and with an easy to use interface in Python and C++.
fit
and predict
methods.We use modern C++14 to create highly flexible, highly efficient data structures and algorithm implementations. Core building blocks are:
variant
implementation for high efficiency w.r.t. datatype dependent storage and processing while maintaining an uncluttered interface and implementation. glog
and gperftools
integration is used for easy debugging and optimization. All dependency libraries don't need to be installed but are part of the repository and completely integrated into the build.cotire
is used for automatic fast pre-compiled header builds. The whole package is automatically pip
installable even without an installed CMake thanks to scikit-build
.Eigen
datastructures wrapped in variant
to provide an easy-to-use C++ interface. We create a small and sleek Python interface thanks to pybind11.If you want to use it from python, a simple python setup.py install
should do. If you want to use it from C++, you can rely on CMake and do mkdir build; cd build; cmake ..; cmake --build . -- -j
for an out-of-source build.
The code is formatted with clang-format according to the google C++ style guidelines (a .clang-format
file is provided on project level). We use abbreviated CamCase class names. For library internal functions, assertions must be done using the FASSERT
macro to selectively enable it, but should be disabled for performance reasons for release builds.
Error messages must be meaningful and provide additional information on what caused the error.
Design decisions are made according to the following priorities:: correctness & numerical stability >> speed >> in-memory efficiency >> storage efficiency.
Raw pointer variable names end with _p
, indicating (1) high performance element access and (2) special care. In performance relevant loops, only _p
variables should be used. Variant variable names end with _v
.
Lock-free parallelism:
Memory is allocated for the tree and leaf storage structures in before entering parallel regions in a pessimistic way. Since it is linear in the number of samples, this is not too much of an overhead. The pointer to where next nodes/leafs can be created is an std::atomic<size_t>
. After training, the datastructures are resized to their proper size.
The Desk classes: this is a helper concept to simplify safe parallelism. A 'desk' contains all thread-local variables and pointers to the shared storage. Each thread has its own desk with sub-objects containing thread-local storage for the corresponding sub-functions. It is constructed with pointers to the memory for storing the results of the training.
The library itself is available under the 2-clause BSD license. All libraries used are also available under open source licenses, for details see build_support/external
.