{"action":"created","comment":{"url":"https://api.github.com/repos/Microsoft/LightGBM/pulls/comments/89663997","pull_request_review_id":10208428,"id":89663997,"diff_hunk":"@@ -0,0 +1,1080 @@\n+\"\"\"Wrapper c_api of LightGBM\"\"\"\n+from __future__ import absolute_import\n+\n+import sys\n+import os\n+import ctypes\n+import collections\n+import re\n+import tempfile\n+\n+import numpy as np\n+import scipy.sparse\n+\n+\n+IS_PY3 = (sys.version_info[0] == 3)\n+\n+\n+def find_lib_path():\n+    \"\"\"Find the path to LightGBM library files.\n+    Returns\n+    -------\n+    lib_path: list(string)\n+       List of all found library path to LightGBM\n+    \"\"\"\n+    curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))\n+    dll_path = [curr_path, os.path.join(curr_path, '../../lib/'),\n+        os.path.join(curr_path, '../../'),\n+        os.path.join(curr_path, './lib/'),\n+        os.path.join(sys.prefix, 'lightgbm')]\n+    if os.name == 'nt':\n+        dll_path.append(os.path.join(curr_path, '../../windows/x64/Dll/'))\n+        dll_path.append(os.path.join(curr_path, './windows/x64/Dll/'))\n+        dll_path = [os.path.join(p, 'lib_lightgbm.dll') for p in dll_path]\n+    else:\n+        dll_path = [os.path.join(p, 'lib_lightgbm.so') for p in dll_path]\n+    lib_path = [p for p in dll_path if os.path.exists(p) and os.path.isfile(p)]\n+    if not lib_path:\n+        raise Exception('Cannot find lightgbm Library')\n+    return lib_path\n+\n+def _load_lib():\n+    \"\"\"Load LightGBM Library.\"\"\"\n+    lib_path = find_lib_path()\n+    if len(lib_path) == 0:\n+        return None\n+    lib = ctypes.cdll.LoadLibrary(lib_path[0])\n+    lib.LGBM_GetLastError.restype = ctypes.c_char_p\n+    return lib\n+\n+_LIB = _load_lib()\n+\n+class LightGBMError(Exception):\n+    \"\"\"Error throwed by LightGBM\"\"\"\n+    pass\n+\n+def _safe_call(ret):\n+    \"\"\"Check the return value of C API call\n+    Parameters\n+    ----------\n+    ret : int\n+        return value from API calls\n+    \"\"\"\n+    if ret != 0:\n+        raise LightGBMError(_LIB.LGBM_GetLastError())\n+\n+def is_str(s):\n+    if IS_PY3:\n+        return isinstance(s, str)\n+    else:\n+        return isinstance(s, basestring)\n+\n+def is_numpy_object(data):\n+    return type(data).__module__ == np.__name__\n+\n+def is_numpy_1d_array(data):\n+    if isinstance(data, np.ndarray) and len(data.shape) == 1:\n+        return True\n+    else:\n+        return False\n+\n+def list_to_1d_numpy(data, dtype):\n+    if is_numpy_1d_array(data):\n+        return data\n+    elif isinstance(data, list):\n+        return np.array(data, dtype=dtype, copy=False)\n+    else:\n+        raise TypeError(\"Unknow type({})\".format(type(data).__name__))\n+\n+def cfloat32_array_to_numpy(cptr, length):\n+    \"\"\"Convert a ctypes float pointer array to a numpy array.\n+    \"\"\"\n+    if isinstance(cptr, ctypes.POINTER(ctypes.c_float)):\n+        res = np.fromiter(cptr, dtype=np.float32, count=length)\n+        return res\n+    else:\n+        raise RuntimeError('expected float pointer')\n+\n+def cint32_array_to_numpy(cptr, length):\n+    \"\"\"Convert a ctypes float pointer array to a numpy array.\n+    \"\"\"\n+    if isinstance(cptr, ctypes.POINTER(ctypes.c_int32)):\n+        res = np.fromiter(cptr, dtype=np.int32, count=length)\n+        return res\n+    else:\n+        raise RuntimeError('expected int pointer')\n+\n+def c_str(string):\n+    \"\"\"Convert a python string to cstring.\"\"\"\n+    return ctypes.c_char_p(string.encode('utf-8'))\n+\n+def c_array(ctype, values):\n+    \"\"\"Convert a python array to c array.\"\"\"\n+    return (ctype * len(values))(*values)\n+\n+def dict_to_str(data):\n+    if data is None or len(data) == 0:\n+        return \"\"\n+    pairs = []\n+    for key in data:\n+        pairs.append(str(key)+'='+str(data[key]))\n+    return ' '.join(pairs)\n+\"\"\"marco definition of data type in c_api of LightGBM\"\"\"\n+C_API_DTYPE_FLOAT32 =0\n+C_API_DTYPE_FLOAT64 =1\n+C_API_DTYPE_INT32   =2\n+C_API_DTYPE_INT64   =3\n+\"\"\"Matric is row major in python\"\"\"\n+C_API_IS_ROW_MAJOR  =1\n+\n+C_API_PREDICT_NORMAL     =0\n+C_API_PREDICT_RAW_SCORE  =1\n+C_API_PREDICT_LEAF_INDEX =2\n+\n+FIELD_TYPE_MAPPER = {\"label\":C_API_DTYPE_FLOAT32, \n+\"wegiht\":C_API_DTYPE_FLOAT32, \n+\"init_score\":C_API_DTYPE_FLOAT32,\n+\"group_id\":C_API_DTYPE_INT32,\n+\"group\":C_API_DTYPE_INT32,\n+ }\n+\n+def c_float_array(data):\n+    \"\"\"Convert numpy array / list to c float array.\"\"\"\n+    if isinstance(data, list):\n+        data = np.array(data, copy=False)\n+    if is_numpy_1d_array(data):\n+        if data.dtype == np.float32:\n+            ptr_data = data.ctypes.data_as(ctypes.POINTER(ctypes.c_float))\n+            type_data = C_API_DTYPE_FLOAT32\n+        elif data.dtype == np.float64:\n+            ptr_data = data.ctypes.data_as(ctypes.POINTER(ctypes.c_double))\n+            type_data = C_API_DTYPE_FLOAT64\n+        else:\n+            raise TypeError(\"expected np.float32 or np.float64, met type({})\".format(data.dtype))\n+    else:\n+        raise TypeError(\"Unknow type({})\".format(type(data).__name__))\n+    return (ptr_data, type_data)\n+\n+def c_int_array(data):\n+    \"\"\"Convert numpy array to c int array.\"\"\"\n+    if isinstance(data, list):\n+        data = np.array(data, copy=False)\n+    if is_numpy_1d_array(data):\n+        if data.dtype == np.int32:\n+            ptr_data = data.ctypes.data_as(ctypes.POINTER(ctypes.c_int32))\n+            type_data = C_API_DTYPE_INT32\n+        elif data.dtype == np.int64:\n+            ptr_data = data.ctypes.data_as(ctypes.POINTER(ctypes.c_int64))\n+            type_data = C_API_DTYPE_INT64\n+        else:\n+            raise TypeError(\"expected np.int32 or np.int64, met type({})\".format(data.dtype))\n+    else:\n+        raise TypeError(\"Unknow type({})\".format(type(data).__name__))\n+    return (ptr_data, type_data)\n+\n+class Predictor(object):\n+    \"\"\"\"A Predictor of LightGBM.\n+    \"\"\"\n+    def __init__(self,model_file=None, params=None, booster_handle=None, is_manage_handle=True):\n+        # pylint: disable=invalid-name\n+        \"\"\"Initialize the Booster.\n+\n+        Parameters\n+        ----------\n+        model_file : string\n+            Path to the model file. \n+        params : dict\n+            Parameters for boosters.\n+        \"\"\"\n+        self.handle = ctypes.c_void_p()\n+        self.__is_manage_handle = True\n+        if model_file is not None:\n+            \"\"\"Prediction task\"\"\"\n+            out_num_total_model = ctypes.c_int64(0)\n+            _safe_call(_LIB.LGBM_BoosterCreateFromModelfile(\n+                c_str(model_file), \n+                ctypes.byref(out_num_total_model),\n+                ctypes.byref(self.handle)))\n+            self.__num_total_model = out_num_total_model.value\n+            tmp_out_len = ctypes.c_int64(0)\n+            _safe_call(_LIB.LGBM_BoosterGetNumClasses(\n+                self.handle,\n+                ctypes.byref(tmp_out_len)))\n+            self.num_class = tmp_out_len.value\n+        elif booster_handle is not None:\n+            self.__is_manage_handle = is_manage_handle\n+            self.handle = booster_handle\n+            tmp_out_len = ctypes.c_int64(0)\n+            _safe_call(_LIB.LGBM_BoosterGetNumClasses(\n+                self.handle,\n+                ctypes.byref(tmp_out_len)))\n+            self.num_class = tmp_out_len.value\n+            _safe_call(_LIB.LGBM_BoosterGetCurrentIteration(\n+                self.handle,\n+                ctypes.byref(tmp_out_len)))\n+            self.__num_total_model = self.num_class * tmp_out_len.value\n+        else:\n+            raise TypeError('Need Model file to create a booster')\n+\n+    def __del__(self):\n+        if self.__is_manage_handle:\n+            _safe_call(_LIB.LGBM_BoosterFree(self.handle))\n+\n+\n+    def predict(self, data, num_iteration=-1, raw_score=False, pred_leaf=False, data_has_header=False, is_reshape=True):\n+        if isinstance(data, Dataset):\n+            raise TypeError(\"cannot use Dataset instance for prediction, please use raw data instead\")\n+        predict_type = C_API_PREDICT_NORMAL\n+        if raw_score:\n+            predict_type = C_API_PREDICT_RAW_SCORE\n+        if pred_leaf:\n+            predict_type = C_API_PREDICT_LEAF_INDEX\n+        int_data_has_header = 0\n+        if data_has_header:\n+            int_data_has_header = 1\n+        if is_str(data):\n+            tmp_pred_fname = tempfile.NamedTemporaryFile(prefix=\"lightgbm_tmp_pred_\").name\n+            _safe_call(_LIB.LGBM_BoosterPredictForFile(\n+                self.handle,\n+                c_str(data), \n+                int_data_has_header,\n+                predict_type,\n+                num_iteration,\n+                c_str(tmp_pred_fname)))\n+            lines = open(tmp_pred_fname,\"r\").readlines()\n+            nrow = len(lines)\n+            preds = []\n+            for line in lines:\n+                for token in line.split('\\t'):\n+                    preds.append(float(token))\n+            preds = np.array(preds, copy=False)\n+            os.remove(tmp_pred_fname)\n+        elif isinstance(data, scipy.sparse.csr_matrix):\n+            preds, nrow = self.__pred_for_csr(data, num_iteration, predict_type)\n+        elif isinstance(data, np.ndarray):\n+            preds, nrow = self.__pred_for_np2d(data, num_iteration, predict_type)\n+        else:\n+            try:\n+                csr = scipy.sparse.csr_matrix(data)\n+                res = self.__pred_for_csr(csr, num_iteration, predict_type)\n+            except:\n+                raise TypeError('can not predict data for type {}'.format(type(data).__name__))\n+        if pred_leaf:\n+            preds = preds.astype(np.int32)\n+        if preds.size != nrow and is_reshape:\n+            if preds.size % nrow == 0:\n+                ncol = int(preds.size / nrow)\n+                preds = preds.reshape(nrow, ncol)\n+            else:\n+                raise ValueError('len of predict result(%d) cannot be divide nrow(%d)' %(preds.size, nrow) )\n+        return preds\n+\n+    def __pred_for_np2d(self, mat, num_iteration, predict_type):\n+        \"\"\"\n+        Predict for a 2-D numpy matrix.\n+        \"\"\"\n+        if len(mat.shape) != 2:\n+            raise ValueError('Input numpy.ndarray must be 2 dimensional')\n+\n+        if mat.dtype == np.float32 or mat.dtype == np.float64:\n+            data = np.array(mat.reshape(mat.size), dtype=mat.dtype, copy=False)\n+        else:\n+            \"\"\"change non-float data to float data, need to copy\"\"\"\n+            data = np.array(mat.reshape(mat.size), dtype=np.float32)\n+        ptr_data, type_ptr_data = c_float_array(data)\n+        n_preds = self.num_class * mat.shape[0]\n+        if predict_type == C_API_PREDICT_LEAF_INDEX:\n+            if num_iteration > 0:\n+                n_preds *= num_iteration\n+            else:\n+                used_iteration = self.__num_total_model / self.num_class\n+                n_preds *= used_iteration\n+        preds = np.zeros(n_preds, dtype=np.float32)\n+        out_num_preds = ctypes.c_int64(0)\n+        _safe_call(_LIB.LGBM_BoosterPredictForMat(\n+            self.handle,\n+            ptr_data, \n+            type_ptr_data,\n+            mat.shape[0],\n+            mat.shape[1],\n+            C_API_IS_ROW_MAJOR,\n+            predict_type,\n+            num_iteration,\n+            ctypes.byref(out_num_preds),\n+            preds.ctypes.data_as(ctypes.POINTER(ctypes.c_float))\n+            ))\n+        if n_preds != out_num_preds.value:\n+            raise ValueError(\"incorrect number for predict result\")\n+        return preds, mat.shape[0]\n+\n+    def __pred_for_csr(self, csr, num_iteration, predict_type):\n+        \"\"\"\n+        Predict for a csr data\n+        \"\"\"\n+        nrow = len(csr.indptr) - 1\n+        n_preds = self.num_class * nrow\n+        if predict_type == C_API_PREDICT_LEAF_INDEX:\n+            if num_iteration > 0:\n+                n_preds *= num_iteration\n+            else:\n+                used_iteration = self.__num_total_model / self.num_class\n+                n_preds *= used_iteration\n+        preds = np.zeros(n_preds, dtype=np.float32)\n+        out_num_preds = ctypes.c_int64(0)\n+\n+        ptr_indptr, type_ptr_indptr = c_int_array(csr.indptr)\n+        ptr_data, type_ptr_data = c_float_array(csr.data)\n+\n+        _safe_call(_LIB.LGBM_BoosterPredictForCSR(\n+            self.handle,\n+            ptr_indptr, \n+            type_ptr_indptr,\n+            csr.indices.ctypes.data_as(ctypes.POINTER(ctypes.c_int32)),\n+            ptr_data,\n+            type_ptr_data, \n+            len(csr.indptr), \n+            len(csr.data),\n+            csr.shape[1], \n+            predict_type,\n+            num_iteration,\n+            ctypes.byref(out_num_preds),\n+            preds.ctypes.data_as(ctypes.POINTER(ctypes.c_float))\n+            ))\n+        if n_preds != out_num_preds.value:\n+            raise ValueError(\"incorrect number for predict result\")\n+        return preds, nrow\n+\n+\n+class Dataset(object):\n+    \"\"\"Dataset used in LightGBM.\n+\n+    Dataset is a internal data structure that used by LightGBM\n+    \"\"\"\n+\n+    def __init__(self, data, label=None, max_bin=255, reference=None,\n+        weight=None, group_id=None, predictor=None,\n+        silent=False, params=None):\n+        \"\"\"\n+        Dataset used in LightGBM.\n+\n+        Parameters\n+        ----------\n+        data : string/numpy array/scipy.sparse\n+            Data source of Dataset.\n+            When data is string type, it represents the path of txt file,\n+        label : list or numpy 1-D array, optional\n+            Label of the data\n+        max_bin : int, required\n+            max number of discrete bin for features \n+        reference : Other Dataset, optional\n+            If this dataset validation, need to use training data as reference\n+        weight : list or numpy 1-D array , optional\n+            Weight for each instance.\n+        group_id : list or numpy 1-D array , optional\n+            group/query id for each instance. Note: if having group/query id, data should group by this id\n+        silent : boolean, optional\n+            Whether print messages during construction\n+        params: dict, optional\n+            other parameters\n+        \"\"\"\n+        if data is None:\n+            self.handle = None\n+            return\n+        self.data_has_header = False\n+        \"\"\"process for args\"\"\"\n+        if params is None:\n+            params = {}\n+        self.max_bin = max_bin\n+        self.predictor = predictor\n+        params[\"max_bin\"] = max_bin\n+        if silent:\n+            params[\"verbose\"] = 0\n+        else:\n+            params[\"verbose\"] = 1\n+        params_str = dict_to_str(params)\n+        \"\"\"process for reference dataset\"\"\"\n+        ref_dataset = None\n+        if isinstance(reference, Dataset):\n+            ref_dataset = ctypes.byref(reference.handle)\n+        elif reference is not None:\n+            raise TypeError('Reference dataset should be None or dataset instance')\n+        \"\"\"start construct data\"\"\"\n+        if is_str(data):\n+            \"\"\"check data has header or not\"\"\"\n+            if \"has_header\" in params or \"header\" in params:\n+                if params[\"has_header\"].lower() == \"true\" or params[\"header\"].lower() == \"true\":\n+                    self.data_has_header = True\n+            self.handle = ctypes.c_void_p()\n+            _safe_call(_LIB.LGBM_CreateDatasetFromFile(\n+                c_str(data), \n+                c_str(params_str), \n+                ref_dataset,\n+                ctypes.byref(self.handle)))\n+        elif isinstance(data, scipy.sparse.csr_matrix):\n+            self.__init_from_csr(data, params_str, ref_dataset)\n+        elif isinstance(data, np.ndarray):\n+            self.__init_from_np2d(data, params_str, ref_dataset)\n+        else:\n+            try:\n+                csr = scipy.sparse.csr_matrix(data)\n+                self.__init_from_csr(csr)\n+            except:\n+                raise TypeError('can not initialize Dataset from {}'.format(type(data).__name__))\n+        self.__label = None\n+        self.__weight = None\n+        self.__init_score = None\n+        self.__group = None\n+        if label is not None:\n+            self.set_label(label)\n+        if self.get_label() is None:\n+            raise ValueError(\"label should not be None\")\n+        if weight is not None:\n+            self.set_weight(weight)\n+        if group_id is not None:\n+            self.set_group_id(group_id)\n+        # load init score\n+        if self.predictor is not None and isinstance(self.predictor, Predictor):\n+            init_score = self.predictor.predict(data, \n+                raw_score=True, \n+                data_has_header=self.data_has_header, \n+                is_reshape=False)\n+            if self.predictor.num_class > 1:\n+                # need re group init score\n+                new_init_score = np.zeros(init_score.size(), dtype=np.float32)\n+                num_data = self.num_data()\n+                for i in range(num_data):\n+                    for j in range(self.predictor.num_class):\n+                        new_init_score[j * num_data + i] = init_score[i * self.predictor.num_class + j]\n+                init_score = new_init_score\n+            self.set_init_score(init_score)\n+\n+    def create_valid(self, data, label=None, weight=None, group_id=None, \n+        silent=False, params=None):\n+        \"\"\"\n+        Create validation data align with current dataset\n+\n+        Parameters\n+        ----------\n+        data : string/numpy array/scipy.sparse\n+            Data source of Dataset.\n+            When data is string type, it represents the path of txt file,\n+        label : list or numpy 1-D array, optional\n+            Label of the training data.\n+        weight : list or numpy 1-D array , optional\n+            Weight for each instance.\n+        group_id : list or numpy 1-D array , optional\n+            group/query id for each instance. Note: if having group/query id, data should group by this id\n+        silent : boolean, optional\n+            Whether print messages during construction\n+        other_params: dict, optional\n+            other parameters\n+        \"\"\"\n+        return Dataset(data, label=label, max_bin=self.max_bin, reference=self,\n+            weight=weight, group_id=group_id, predictor=self.predictor, \n+            silent=silent, params=params)\n+\n+    def __init_from_np2d(self, mat, params_str, ref_dataset):\n+        \"\"\"\n+        Initialize data from a 2-D numpy matrix.\n+        \"\"\"\n+        if len(mat.shape) != 2:\n+            raise ValueError('Input numpy.ndarray must be 2 dimensional')\n+\n+        self.handle = ctypes.c_void_p()\n+        if mat.dtype == np.float32 or mat.dtype == np.float64:\n+            data = np.array(mat.reshape(mat.size), dtype=mat.dtype, copy=False)\n+        else:\n+            \"\"\"change non-float data to float data, need to copy\"\"\"\n+            data = np.array(mat.reshape(mat.size), dtype=np.float32)\n+\n+        ptr_data, type_ptr_data = c_float_array(data)\n+        _safe_call(_LIB.LGBM_CreateDatasetFromMat(\n+            ptr_data, \n+            type_ptr_data,\n+            mat.shape[0],\n+            mat.shape[1],\n+            C_API_IS_ROW_MAJOR,\n+            c_str(params_str), \n+            ref_dataset, \n+            ctypes.byref(self.handle)))\n+\n+    def __init_from_csr(self, csr, params_str, ref_dataset):\n+        \"\"\"\n+        Initialize data from a CSR matrix.\n+        \"\"\"\n+        if len(csr.indices) != len(csr.data):\n+            raise ValueError('length mismatch: {} vs {}'.format(len(csr.indices), len(csr.data)))\n+        self.handle = ctypes.c_void_p()\n+\n+        ptr_indptr, type_ptr_indptr = c_int_array(csr.indptr)\n+        ptr_data, type_ptr_data = c_float_array(csr.data)\n+\n+        _safe_call(_LIB.LGBM_CreateDatasetFromCSR(\n+            ptr_indptr, \n+            type_ptr_indptr,\n+            csr.indices.ctypes.data_as(ctypes.POINTER(ctypes.c_int32)),\n+            ptr_data,\n+            type_ptr_data, \n+            len(csr.indptr), \n+            len(csr.data),\n+            csr.shape[1], \n+            c_str(params_str), \n+            ref_dataset, \n+            ctypes.byref(self.handle)))\n+\n+    def __del__(self):\n+        _safe_call(_LIB.LGBM_DatasetFree(self.handle))\n+\n+    def get_field(self, field_name):\n+        \"\"\"Get property from the Dataset.\n+\n+        Parameters\n+        ----------\n+        field_name: str\n+            The field name of the information\n+\n+        Returns\n+        -------\n+        info : array\n+            a numpy array of information of the data\n+        \"\"\"\n+        tmp_out_len = ctypes.c_int64()\n+        out_type = ctypes.c_int32()\n+        ret = ctypes.POINTER(ctypes.c_void_p)()\n+        _safe_call(_LIB.LGBM_DatasetGetField(\n+            self.handle,\n+            c_str(field_name),\n+            ctypes.byref(tmp_out_len),\n+            ctypes.byref(ret),\n+            ctypes.byref(out_type)))\n+        if out_type.value != FIELD_TYPE_MAPPER[field_name]:\n+            raise TypeError(\"Return type error for get_field\")\n+        if tmp_out_len.value == 0:\n+            return None\n+        if out_type.value == C_API_DTYPE_INT32:\n+            return cint32_array_to_numpy(ctypes.cast(ret, ctypes.POINTER(ctypes.c_int32)), tmp_out_len.value)\n+        elif out_type.value == C_API_DTYPE_FLOAT32:\n+            return cfloat32_array_to_numpy(ctypes.cast(ret, ctypes.POINTER(ctypes.c_float)), tmp_out_len.value)\n+        else:\n+            raise TypeError(\"unknow type\")\n+\n+    def set_field(self, field_name, data):\n+        \"\"\"Set property into the Dataset.\n+\n+        Parameters\n+        ----------\n+        field_name: str\n+            The field name of the information\n+\n+        data: numpy array or list or None\n+            The array ofdata to be set\n+        \"\"\"\n+        if data is None:\n+            _safe_call(_LIB.LGBM_DatasetSetField(\n+                self.handle,\n+                c_str(field_name),\n+                None,\n+                0,\n+                FIELD_TYPE_MAPPER[field_name]))\n+            return\n+        if not is_numpy_1d_array(data):\n+            raise TypeError(\"Unknow type({})\".format(type(data).__name__))\n+        if data.dtype == np.float32:\n+            ptr_data = data.ctypes.data_as(ctypes.POINTER(ctypes.c_float))\n+            type_data = C_API_DTYPE_FLOAT32\n+        elif data.dtype == np.int32:\n+            ptr_data = data.ctypes.data_as(ctypes.POINTER(ctypes.c_int32))\n+            type_data = C_API_DTYPE_INT32\n+        else:\n+            raise TypeError(\"excepted np.float32 or np.int32, met type({})\".format(data.dtype))\n+        if type_data != FIELD_TYPE_MAPPER[field_name]:\n+            raise TypeError(\"type error for set_field\")\n+        _safe_call(_LIB.LGBM_DatasetSetField(\n+            self.handle,\n+            c_str(field_name),\n+            ptr_data,\n+            len(data),\n+            type_data))\n+\n+\n+    def save_binary(self, filename):\n+        \"\"\"Save Dataset to binary file\n+\n+        Parameters\n+        ----------\n+        filename : string\n+            Name of the output file.\n+        \"\"\"\n+        _safe_call(_LIB.LGBM_DatasetSaveBinary(\n+            self.handle,\n+            c_str(filename)))\n+\n+    def set_label(self, label):\n+        \"\"\"Set label of Dataset\n+\n+        Parameters\n+        ----------\n+        label: array like\n+            The label information to be set into Dataset\n+        \"\"\"\n+        label = list_to_1d_numpy(label, np.float32)\n+        if label.dtype != np.float32:\n+            label = label.astype(np.float32, copy=False)\n+        self.__label = label\n+        self.set_field('label', label)\n+\n+    def set_weight(self, weight):\n+        \"\"\" Set weight of each instance.\n+\n+        Parameters\n+        ----------\n+        weight : array like\n+            Weight for each data point\n+        \"\"\"\n+        if weight is not None:\n+            weight = list_to_1d_numpy(weight, np.float32)\n+            if weight.dtype != np.float32:\n+                weight = weight.astype(np.float32, copy=False)\n+        self.__weight = weight\n+        self.set_field('weight', weight)\n+\n+    def set_init_score(self, score):\n+        \"\"\" Set init score of booster to start from.\n+        Parameters\n+        ----------\n+        score: array like\n+\n+        \"\"\"\n+        if score is not None:\n+            score = list_to_1d_numpy(score, np.float32)\n+            if score.dtype != np.float32:\n+                score = score.astype(np.float32, copy=False)\n+        self.__init_score = score\n+        self.set_field('init_score', score)\n+\n+    def set_group(self, group):\n+        \"\"\"Set group size of Dataset (used for ranking).\n+\n+        Parameters\n+        ----------\n+        group : array like\n+            Group size of each group\n+        \"\"\"\n+        if group is not None:\n+            group = list_to_1d_numpy(group, np.int32)\n+            if group.dtype != np.int32:\n+                group = group.astype(np.int32, copy=False)\n+        self.__group = group\n+        self.set_field('group', group)\n+\n+    def set_group_id(self, group_id):\n+\n+        \"\"\"Set group_id of Dataset (used for ranking).\n+\n+        Parameters\n+        ----------\n+        group : array like\n+            group_id of Dataset (used for ranking).\n+        \"\"\"\n+        if group_id is not None:\n+            group_id = list_to_1d_numpy(group_id, np.int32)\n+            if group_id.dtype != np.int32:\n+                group_id = group_id.astype(np.int32, copy=False)\n+        self.set_field('group_id', group_id)\n+\n+    def get_label(self):\n+        \"\"\"Get the label of the Dataset.\n+\n+        Returns\n+        -------\n+        label : array\n+        \"\"\"\n+        if self.__label is None:\n+            self.__label = self.get_field('label')\n+        if self.__label is None:\n+            raise TypeError(\"label should not be None\")\n+        return self.__label\n+\n+    def get_weight(self):\n+        \"\"\"Get the weight of the Dataset.\n+\n+        Returns\n+        -------\n+        weight : array\n+        \"\"\"\n+        if self.__weight is None:\n+            self.__weight = self.get_field('weight')\n+        return self.__weight\n+\n+    def get_init_score(self):\n+        \"\"\"Get the initial score of the Dataset.\n+\n+        Returns\n+        -------\n+        init_score : array\n+        \"\"\"\n+        if self.__init_score is None:\n+            self.__init_score = self.get_field('init_score')\n+        return self.__init_score\n+\n+    def get_group(self):\n+        \"\"\"Get the initial score of the Dataset.\n+\n+        Returns\n+        -------\n+        init_score : array\n+        \"\"\"\n+        if self.__group is None:\n+            self.__group = self.get_field('group')\n+        return self.__group\n+\n+    def num_data(self):\n+        \"\"\"Get the number of rows in the Dataset.\n+\n+        Returns\n+        -------\n+        number of rows : int\n+        \"\"\"\n+        ret = ctypes.c_int64()\n+        _safe_call(_LIB.LGBM_DatasetGetNumData(self.handle,\n+                                         ctypes.byref(ret)))\n+        return ret.value\n+\n+    def num_feature(self):\n+        \"\"\"Get the number of columns (features) in the Dataset.\n+\n+        Returns\n+        -------\n+        number of columns : int\n+        \"\"\"\n+        ret = ctypes.c_int64()\n+        _safe_call(_LIB.LGBM_DatasetGetNumFeature(self.handle,\n+                                         ctypes.byref(ret)))\n+        return ret.value\n+\n+\n+class Booster(object):\n+    \"\"\"\"A Booster of of LightGBM.\n+    \"\"\"\n+    def __init__(self, params=None, train_set=None, model_file=None, silent=False):\n+        # pylint: disable=invalid-name\n+        \"\"\"Initialize the Booster.\n+\n+        Parameters\n+        ----------\n+        params : dict\n+            Parameters for boosters.\n+        train_set : Dataset\n+            training dataset\n+        model_file : string\n+            Path to the model file. \n+        \"\"\"\n+        self.handle = ctypes.c_void_p()\n+        self.__need_reload_eval_info = True\n+        self.__is_manage_handle = True\n+        if params is None:\n+            params = {}\n+        if silent:\n+            params[\"verbose\"] = 0\n+        else:\n+            params[\"verbose\"] = 1\n+        if train_set is not None:\n+            \"\"\"Training task\"\"\"\n+            if not isinstance(train_set, Dataset):\n+                raise TypeError('training data should be Dataset instance, met{}'.format(type(train_set).__name__))\n+            params_str = dict_to_str(params)\n+            \"\"\"construct booster object\"\"\"\n+            _safe_call(_LIB.LGBM_BoosterCreate(\n+                train_set.handle, \n+                c_str(params_str),\n+                ctypes.byref(self.handle)))\n+            \"\"\"save reference to data\"\"\"\n+            self.train_set = train_set\n+            self.valid_sets = []\n+            self.name_valid_sets = []\n+            self.__num_dataset = 1\n+            self.init_predictor = train_set.predictor\n+            if self.init_predictor is not None:\n+                _safe_call(_LIB.LGBM_BoosterMerge(\n+                    self.handle,\n+                    self.init_predictor.handle))\n+            out_num_class = ctypes.c_int64(0)\n+            _safe_call(_LIB.LGBM_BoosterGetNumClasses(\n+                self.handle,\n+                ctypes.byref(out_num_class)))\n+            self.__num_class = out_num_class.value\n+            \"\"\"buffer for inner predict\"\"\"\n+            self.__inner_predict_buffer = [None]\n+            self.__get_eval_info()\n+        elif model_file is not None:\n+            \"\"\"Prediction task\"\"\"\n+            out_num_total_model = ctypes.c_int64(0)\n+            _safe_call(_LIB.LGBM_BoosterCreateFromModelfile(\n+                c_str(model_file), \n+                ctypes.byref(out_num_total_model),\n+                ctypes.byref(self.handle)))\n+            self.__num_total_model = out_num_total_model.value\n+            out_num_class = ctypes.c_int64(0)\n+            _safe_call(_LIB.LGBM_BoosterGetNumClasses(\n+                self.handle,\n+                ctypes.byref(out_num_class)))\n+            self.__num_class = out_num_class.value\n+        else:\n+            raise TypeError('At least need training dataset or model file to create booster instance')\n+\n+    def __del__(self):\n+        if self.handle is not None and self.__is_manage_handle:\n+            _safe_call(_LIB.LGBM_BoosterFree(self.handle))\n+\n+    def add_valid(self, data, name):\n+        if data.predictor is not self.init_predictor:\n+            raise Exception(\"Add validation data failed, you should use same predictor for these data\")\n+        _safe_call(_LIB.LGBM_BoosterAddValidData(\n+            self.handle,\n+            data.handle))\n+        self.valid_sets.append(data)\n+        self.name_valid_sets.append(name)\n+        self.__num_dataset += 1\n+\n+    def reset_parameter(self, params, silent=False):\n+        self.__need_reload_eval_info = True\n+        if silent:\n+            params[\"verbose\"] = 0\n+        else:\n+            params[\"verbose\"] = 1\n+        params_str = dict_to_str(params)\n+        _safe_call(_LIB.LGBM_BoosterResetParameter(\n+            self.handle,\n+            c_str(params_str)))\n+\n+    def update(self, train_set=None, fobj=None):\n+        \"\"\"\n+        Update for one iteration\n+        Note: for multi-class task, the score is group by class_id first, then group by row_id\n+              if you want to get i-th row score in j-th class, the access way is score[j*num_data+i]\n+              and you should group grad and hess in this way as well\n+        Parameters\n+        ----------\n+        train_set : training data, None means use last training data\n+        fobj : function\n+            Customized objective function.\n+\n+        Returns\n+        -------\n+        is_finished, bool\n+        \"\"\"\n+        \"\"\"need reset training data\"\"\"\n+        if train_set is not None and train_set is not self.train_set:\n+            if train_set.predictor is not self.init_predictor:\n+                raise Exception(\"Replace training data failed, you should use same predictor for these data\")\n+            self.train_set = train_set\n+            _safe_call(_LIB.LGBM_BoosterResetTrainingData(\n+                self.handle, \n+                self.train_set.handle))\n+            self.__inner_predict_buffer[0] = None\n+        is_finished = ctypes.c_int(0)\n+        if fobj is None:\n+            _safe_call(_LIB.LGBM_BoosterUpdateOneIter(\n+                self.handle, \n+                ctypes.byref(is_finished)))\n+            return is_finished.value == 1\n+        else:\n+            grad, hess = fobj(self.__inner_predict(0), self.train_set)\n+            return self.__boost(grad, hess)","path":"python-package/lightgbm/basic.py","position":884,"original_position":883,"commit_id":"f059d0fe0f9616d9dc2f91f459880b01f8cbf7f9","original_commit_id":"9006d3f2b57b2218110a324d209cb047777e7e81","user":{"login":"guolinke","id":16040950,"avatar_url":"https://avatars.githubusercontent.com/u/16040950?v=3","gravatar_id":"","url":"https://api.github.com/users/guolinke","html_url":"https://github.com/guolinke","followers_url":"https://api.github.com/users/guolinke/followers","following_url":"https://api.github.com/users/guolinke/following{/other_user}","gists_url":"https://api.github.com/users/guolinke/gists{/gist_id}","starred_url":"https://api.github.com/users/guolinke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/guolinke/subscriptions","organizations_url":"https://api.github.com/users/guolinke/orgs","repos_url":"https://api.github.com/users/guolinke/repos","events_url":"https://api.github.com/users/guolinke/events{/privacy}","received_events_url":"https://api.github.com/users/guolinke/received_events","type":"User","site_admin":false},"body":"fixed","created_at":"2016-11-26T02:11:47Z","updated_at":"2016-11-26T02:11:47Z","html_url":"https://github.com/Microsoft/LightGBM/pull/94#discussion_r89663997","pull_request_url":"https://api.github.com/repos/Microsoft/LightGBM/pulls/94","_links":{"self":{"href":"https://api.github.com/repos/Microsoft/LightGBM/pulls/comments/89663997"},"html":{"href":"https://github.com/Microsoft/LightGBM/pull/94#discussion_r89663997"},"pull_request":{"href":"https://api.github.com/repos/Microsoft/LightGBM/pulls/94"}}},"pull_request":{"url":"https://api.github.com/repos/Microsoft/LightGBM/pulls/94","id":95141220,"html_url":"https://github.com/Microsoft/LightGBM/pull/94","diff_url":"https://github.com/Microsoft/LightGBM/pull/94.diff","patch_url":"https://github.com/Microsoft/LightGBM/pull/94.patch","issue_url":"https://api.github.com/repos/Microsoft/LightGBM/issues/94","number":94,"state":"open","locked":false,"title":"Python package (#11)","user":{"login":"guolinke","id":16040950,"avatar_url":"https://avatars.githubusercontent.com/u/16040950?v=3","gravatar_id":"","url":"https://api.github.com/users/guolinke","html_url":"https://github.com/guolinke","followers_url":"https://api.github.com/users/guolinke/followers","following_url":"https://api.github.com/users/guolinke/following{/other_user}","gists_url":"https://api.github.com/users/guolinke/gists{/gist_id}","starred_url":"https://api.github.com/users/guolinke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/guolinke/subscriptions","organizations_url":"https://api.github.com/users/guolinke/orgs","repos_url":"https://api.github.com/users/guolinke/repos","events_url":"https://api.github.com/users/guolinke/events{/privacy}","received_events_url":"https://api.github.com/users/guolinke/received_events","type":"User","site_admin":false},"body":"refer to #11 \r\n\r\nI finish the basic wrapper class for c_api . \r\nNow will start some tests and collect some feedback.","created_at":"2016-11-24T09:17:29Z","updated_at":"2016-11-26T02:11:47Z","closed_at":null,"merged_at":null,"merge_commit_sha":"68c8eb594e0d4e68f16350305dc304a42c8333ac","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/Microsoft/LightGBM/pulls/94/commits","review_comments_url":"https://api.github.com/repos/Microsoft/LightGBM/pulls/94/comments","review_comment_url":"https://api.github.com/repos/Microsoft/LightGBM/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Microsoft/LightGBM/issues/94/comments","statuses_url":"https://api.github.com/repos/Microsoft/LightGBM/statuses/f059d0fe0f9616d9dc2f91f459880b01f8cbf7f9","head":{"label":"Microsoft:python-package","ref":"python-package","sha":"f059d0fe0f9616d9dc2f91f459880b01f8cbf7f9","user":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars.githubusercontent.com/u/6154722?v=3","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"repo":{"id":64991887,"name":"LightGBM","full_name":"Microsoft/LightGBM","owner":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars.githubusercontent.com/u/6154722?v=3","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Microsoft/LightGBM","description":"A fast, distributed, high performance gradient boosting (GBDT, GBRT, GBM or MART) framework based on decision tree algorithms, used for ranking, classification and many other machine learning tasks. It is under the umbrella of the DMTK(http://github.com/microsoft/dmtk) project of Microsoft.","fork":false,"url":"https://api.github.com/repos/Microsoft/LightGBM","forks_url":"https://api.github.com/repos/Microsoft/LightGBM/forks","keys_url":"https://api.github.com/repos/Microsoft/LightGBM/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Microsoft/LightGBM/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Microsoft/LightGBM/teams","hooks_url":"https://api.github.com/repos/Microsoft/LightGBM/hooks","issue_events_url":"https://api.github.com/repos/Microsoft/LightGBM/issues/events{/number}","events_url":"https://api.github.com/repos/Microsoft/LightGBM/events","assignees_url":"https://api.github.com/repos/Microsoft/LightGBM/assignees{/user}","branches_url":"https://api.github.com/repos/Microsoft/LightGBM/branches{/branch}","tags_url":"https://api.github.com/repos/Microsoft/LightGBM/tags","blobs_url":"https://api.github.com/repos/Microsoft/LightGBM/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Microsoft/LightGBM/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Microsoft/LightGBM/git/refs{/sha}","trees_url":"https://api.github.com/repos/Microsoft/LightGBM/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Microsoft/LightGBM/statuses/{sha}","languages_url":"https://api.github.com/repos/Microsoft/LightGBM/languages","stargazers_url":"https://api.github.com/repos/Microsoft/LightGBM/stargazers","contributors_url":"https://api.github.com/repos/Microsoft/LightGBM/contributors","subscribers_url":"https://api.github.com/repos/Microsoft/LightGBM/subscribers","subscription_url":"https://api.github.com/repos/Microsoft/LightGBM/subscription","commits_url":"https://api.github.com/repos/Microsoft/LightGBM/commits{/sha}","git_commits_url":"https://api.github.com/repos/Microsoft/LightGBM/git/commits{/sha}","comments_url":"https://api.github.com/repos/Microsoft/LightGBM/comments{/number}","issue_comment_url":"https://api.github.com/repos/Microsoft/LightGBM/issues/comments{/number}","contents_url":"https://api.github.com/repos/Microsoft/LightGBM/contents/{+path}","compare_url":"https://api.github.com/repos/Microsoft/LightGBM/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Microsoft/LightGBM/merges","archive_url":"https://api.github.com/repos/Microsoft/LightGBM/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Microsoft/LightGBM/downloads","issues_url":"https://api.github.com/repos/Microsoft/LightGBM/issues{/number}","pulls_url":"https://api.github.com/repos/Microsoft/LightGBM/pulls{/number}","milestones_url":"https://api.github.com/repos/Microsoft/LightGBM/milestones{/number}","notifications_url":"https://api.github.com/repos/Microsoft/LightGBM/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Microsoft/LightGBM/labels{/name}","releases_url":"https://api.github.com/repos/Microsoft/LightGBM/releases{/id}","deployments_url":"https://api.github.com/repos/Microsoft/LightGBM/deployments","created_at":"2016-08-05T05:45:50Z","updated_at":"2016-11-25T12:41:01Z","pushed_at":"2016-11-26T02:11:10Z","git_url":"git://github.com/Microsoft/LightGBM.git","ssh_url":"git@github.com:Microsoft/LightGBM.git","clone_url":"https://github.com/Microsoft/LightGBM.git","svn_url":"https://github.com/Microsoft/LightGBM","homepage":"","size":3185,"stargazers_count":1588,"watchers_count":1588,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":251,"mirror_url":null,"open_issues_count":11,"forks":251,"open_issues":11,"watchers":1588,"default_branch":"master"}},"base":{"label":"Microsoft:master","ref":"master","sha":"65e711a285b212d4bfbdf3b0a3d1921b41df0f6e","user":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars.githubusercontent.com/u/6154722?v=3","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"repo":{"id":64991887,"name":"LightGBM","full_name":"Microsoft/LightGBM","owner":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars.githubusercontent.com/u/6154722?v=3","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Microsoft/LightGBM","description":"A fast, distributed, high performance gradient boosting (GBDT, GBRT, GBM or MART) framework based on decision tree algorithms, used for ranking, classification and many other machine learning tasks. It is under the umbrella of the DMTK(http://github.com/microsoft/dmtk) project of Microsoft.","fork":false,"url":"https://api.github.com/repos/Microsoft/LightGBM","forks_url":"https://api.github.com/repos/Microsoft/LightGBM/forks","keys_url":"https://api.github.com/repos/Microsoft/LightGBM/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Microsoft/LightGBM/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Microsoft/LightGBM/teams","hooks_url":"https://api.github.com/repos/Microsoft/LightGBM/hooks","issue_events_url":"https://api.github.com/repos/Microsoft/LightGBM/issues/events{/number}","events_url":"https://api.github.com/repos/Microsoft/LightGBM/events","assignees_url":"https://api.github.com/repos/Microsoft/LightGBM/assignees{/user}","branches_url":"https://api.github.com/repos/Microsoft/LightGBM/branches{/branch}","tags_url":"https://api.github.com/repos/Microsoft/LightGBM/tags","blobs_url":"https://api.github.com/repos/Microsoft/LightGBM/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Microsoft/LightGBM/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Microsoft/LightGBM/git/refs{/sha}","trees_url":"https://api.github.com/repos/Microsoft/LightGBM/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Microsoft/LightGBM/statuses/{sha}","languages_url":"https://api.github.com/repos/Microsoft/LightGBM/languages","stargazers_url":"https://api.github.com/repos/Microsoft/LightGBM/stargazers","contributors_url":"https://api.github.com/repos/Microsoft/LightGBM/contributors","subscribers_url":"https://api.github.com/repos/Microsoft/LightGBM/subscribers","subscription_url":"https://api.github.com/repos/Microsoft/LightGBM/subscription","commits_url":"https://api.github.com/repos/Microsoft/LightGBM/commits{/sha}","git_commits_url":"https://api.github.com/repos/Microsoft/LightGBM/git/commits{/sha}","comments_url":"https://api.github.com/repos/Microsoft/LightGBM/comments{/number}","issue_comment_url":"https://api.github.com/repos/Microsoft/LightGBM/issues/comments{/number}","contents_url":"https://api.github.com/repos/Microsoft/LightGBM/contents/{+path}","compare_url":"https://api.github.com/repos/Microsoft/LightGBM/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Microsoft/LightGBM/merges","archive_url":"https://api.github.com/repos/Microsoft/LightGBM/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Microsoft/LightGBM/downloads","issues_url":"https://api.github.com/repos/Microsoft/LightGBM/issues{/number}","pulls_url":"https://api.github.com/repos/Microsoft/LightGBM/pulls{/number}","milestones_url":"https://api.github.com/repos/Microsoft/LightGBM/milestones{/number}","notifications_url":"https://api.github.com/repos/Microsoft/LightGBM/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Microsoft/LightGBM/labels{/name}","releases_url":"https://api.github.com/repos/Microsoft/LightGBM/releases{/id}","deployments_url":"https://api.github.com/repos/Microsoft/LightGBM/deployments","created_at":"2016-08-05T05:45:50Z","updated_at":"2016-11-25T12:41:01Z","pushed_at":"2016-11-26T02:11:10Z","git_url":"git://github.com/Microsoft/LightGBM.git","ssh_url":"git@github.com:Microsoft/LightGBM.git","clone_url":"https://github.com/Microsoft/LightGBM.git","svn_url":"https://github.com/Microsoft/LightGBM","homepage":"","size":3185,"stargazers_count":1588,"watchers_count":1588,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":251,"mirror_url":null,"open_issues_count":11,"forks":251,"open_issues":11,"watchers":1588,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Microsoft/LightGBM/pulls/94"},"html":{"href":"https://github.com/Microsoft/LightGBM/pull/94"},"issue":{"href":"https://api.github.com/repos/Microsoft/LightGBM/issues/94"},"comments":{"href":"https://api.github.com/repos/Microsoft/LightGBM/issues/94/comments"},"review_comments":{"href":"https://api.github.com/repos/Microsoft/LightGBM/pulls/94/comments"},"review_comment":{"href":"https://api.github.com/repos/Microsoft/LightGBM/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Microsoft/LightGBM/pulls/94/commits"},"statuses":{"href":"https://api.github.com/repos/Microsoft/LightGBM/statuses/f059d0fe0f9616d9dc2f91f459880b01f8cbf7f9"}}}}
{"actor":{"display_login":"guolinke"}}