在工程上应用LightGBM

介绍

LightGBM 是微软提供的GBDT模型的一种高效实现。使用LightGBM解决问题的通用方式是首先使用python进行模型训练,完成训练后构建C++工程加载模型,实现回归分类或排序。
但目前微软开源的LightGBM实现中开放的Predict接口只支持从文件读取样本并把结果输出到文件的形式。这种形式直接部署到线上服务时需要将样本写入文件,开启LightGBM子进程,读取结果文件这三个流程。
为了解决以上问题,我对LightGBM的文件结构进行了调整,提供了直接接收一个样本或批量样本进行预测的接口。并把整个工程编译为静态库,线上服务只需要引入静态库以及头文件就可以将LightGBM集成。

代码调整及接口

代码主要调整包括将predictor.hpp移动到include/LightGBM下,在application.h中提供以下预测接口


std::string Predict(const char* sample, const char sep);

std::string Predict(const std::vector<std::pair<int, double>>& indexed_features);

std::string Predict(const std::vector<double>& features);

std::vector<std::string> BatchPredict(const std::vector<std::vector<double>>& batch_features);

在配置中新增online_predict任务类型。
具体实现见https://github.com/ce39906/LightGBM

应用示例

获取代码以及编译


git clone https://github.com/ce39906/LightGBM.git
cd LightGBM
mkdir -p build && cd build
cmake ..
make

应用静态库及头文件

我们以https://github.com/ce39906/LightGBM/tree/master/examples/regression 提供的回归问题为例,说明如何使用编译好的静态库进行预测。
首先我们在工程目录下新建third_party/lightgbm/bin以及third_party/lightgbm/include目录分别存放静态库文件以及头文件。
将编译好的liblgbm.a 拷贝到third_party/lightgbm/bin下,将源代码include目录下的LightGBM目录拷贝到third_party/lightgbm/bin 下。
编写test.cpp 测试预测接口,测试代码如下


/*************************************************************************
    > File Name: test.cpp
    > Author: ce39906
    > Mail: ce39906@163.com
    > Created Time: 2018-12-25 10:42:45
 ************************************************************************/
#include <iostream>
#include <LightGBM/application.h>

int main(int argc, char** argv)
{
    LightGBM::Application app(argc, argv);
    app.InitPredict();
    const char* sample = "0.644,0.247,-0.447,0.862,0.374,0.854,-1.126,-0.790,"
                         "2.173,1.015,-0.201,1.400,0.000,1.575,1.807,1.607,"
                         "0.000,1.585,-0.190,-0.744,3.102,0.958,1.061,0.980,"
                         "0.875,0.581,0.905,0.796";
    std::string result;
    result = app.Predict(sample, ',');
    std::cout << result << std::endl;

    return 0;
}

CMakeLists.txt 如下


cmake_minimum_required(VERSION 2.6)

PROJECT(lgbm_client C CXX)
OPTION(USE_OPENMP "Enable OpenMP" ON)

find_package(OpenMP REQUIRED)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -g -w -O3 --std=c++11")

SET(LIGHTGBM_LIB ${CMAKE_CURRENT_SOURCE_DIR}/third_party/lightgbm/bin/liblgbm.a)
MESSAGE(STATUS "SYSTEM_INCLUDE_PATH ${SYSTEM_INCLUDE_PATH}")

SET(SYSTEM_INCLUDE_PATH /usr/include/)
INCLUDE_DIRECTORIES(SYSTEM ${SYSTEM_INCLUDE_PATH})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/third_party/lightgbm/include)

ADD_EXECUTABLE(lgbm_client test.cpp)
TARGET_LINK_LIBRARIES(lgbm_client ${LIGHTGBM_LIB})

编译好之后运行

./lgbm_client config=online.conf

online.conf 内容如下

task = online
input_model= LightGBM_model.txt

运行结果如下
pic