Commit 12d9a22d authored by haozhenWu's avatar haozhenWu
Browse files

add xgboost models

parent e58ddeb8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ from __future__ import unicode_literals

from deepchem.models.models import Model
from deepchem.models.sklearn_models import SklearnModel
from deepchem.models.xgboost_models import XGBoostModel
from deepchem.models.tf_new_models.multitask_classifier import MultitaskGraphClassifier
from deepchem.models.tf_new_models.multitask_regressor import MultitaskGraphRegressor
from deepchem.models.tf_new_models.support_classifier import SupportGraphClassifier
+114 −0
Original line number Diff line number Diff line
"""
Scikit-learn wrapper interface of xgboost
"""

import xgboost as xgb
import numpy as np
from deepchem.models import Model
from deepchem.models.sklearn_models import SklearnModel
from deepchem.utils.save import load_from_disk
from deepchem.utils.save import save_to_disk
from sklearn.cross_validation import train_test_split
from sklearn.grid_search import GridSearchCV

class XGBoostModel(SklearnModel):
  """
  Abstract base class for XGBoost model.
  """
  def __init__(self, model_instance=None, model_dir=None,
               verbose=True, **kwargs):
    """Abstract class for XGBoost models.
    Parameters:
    -----------
    model_instance: object
      Scikit-learn wrapper interface of xgboost
    model_dir: str
      Path to directory where model will be stored.
    """
    if model_dir is not None:
      if not os.path.exists(model_dir):
        os.makedirs(model_dir)
    else:
      model_dir = tempfile.mkdtemp()
    self.model_dir = model_dir
    self.model_instance = model_instance
    self.model_class = model_instance.__class__

    self.verbose = verbose
    if 'early_stopping_rounds' in kwargs:
       	self.early_stopping_rounds = kwargs['early_stopping_rounds']
    else:
        self.early_stopping_rounds = 50


  def fit(self, dataset, **kwargs):
    """
    Fits XGBoost model to data.
    """
    X = dataset.X
    y = np.squeeze(dataset.y)
    w = np.squeeze(dataset.w)
    seed = self.model_instance.seed
    if isinstance(self.model_instance,xgb.XGBClassifier):
        xgb_metric = "auc"
        sklearn_metric = "roc_auc"
    elif isinstance(self.model_instance,xgb.XGBRegressor):
        xgb_metric = "mae"
        sklearn_metric = "neg_mean_absolute_error"

    best_param = self._search_param(sklearn_metric)
    # update model with best param
    self.model_instance = self.model_class(**best_param)

    # Find optimal n_estimators based on original learning_rate
    # and early_stopping_rounds
    X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                        test_size = 0.2,
                                                        random_state=seed,
                                                        stratify=y)

    self.model_instance.fit(X_train, y_train,
			                early_stopping_rounds=self.early_stopping_rounds,
                            eval_metric=xgb_metric,eval_set=[(X_test, y_test)],
                            verbose=self.verbose)
    # Since test size is 20%, when retrain model to whole data, expect
    # n_estimator increased to 1/0.8 = 1.25 time.
    estimated_best_round = np.round(self.model_instance.best_ntree_limit * 1.25)
    self.model_instance.n_estimators = np.int64(estimated_best_round)
    self.model_instance.fit(X_train, y_train, eval_metric=xgb_metric,
			    verbose=self.verbose)

  def _search_param(self,metric):
    '''
    Find best potential parameters set using few n_estimators
    '''
    # Make sure user specified params are in the grid.
    max_depth_grid = list(np.unique([self.model_instance.max_depth,5,7]))
    colsample_bytree_grid = list(np.unique(
                                [self.model_instance.colsample_tree,0.66,0.9]))
    reg_lambda_grid = list(np.unique(
                                [self.model_instance.reg_lambda,1,5]))
    param_grid = {
                  'max_depth': max_depth_grid,
                  'learning_rate': [max(self.model_instance.learning_rate,0.3)],
                  'n_estimators': [min(self.model_instance.n_estimators,60)],
                  'gamma': [self.model_instance.gamma],
                  'min_child_weight': [self.model_instance.min_child_weight],
                  'max_delta_step': [self.model_instance.max_delta_step],
                  'subsample': [self.model_instance.subsample],
                  'colsample_bytree': colsample_bytree_grid,
                  'colsample_bylevel': [self.model_instance.colsample_bylevel],
                  'reg_alpha': [self.model_instance.reg_alpha],
                  'reg_lambda': reg_lambda_grid,
                  'scale_pos_weight': [self.model_instance.scale_pos_weight],
                  'base_score': [self.model_instance.base_score],
                  'seed': [self.model_instance.seed]
    }
    grid_search = GridSearchCV(self.model_instance, param_grid, cv=2,
                                refit=False, scoring=metric)
    grid_search.fit(X,y)
    best_params = grid_search.best_params_
    # Change params back original params
    best_params['learning_rate'] = self.model_instance.learning_rate
    best_params['n_estimators'] = self.model_instance.n_estimators
    return best_params
+158 −6
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ from qm9.qm9_datasets import load_qm9
from sampl.sampl_datasets import load_sampl
from clintox.clintox_datasets import load_clintox
from hiv.hiv_datasets import load_hiv

import xgboost

def benchmark_loading_datasets(hyper_parameters,
                               dataset='tox21',
@@ -313,7 +313,8 @@ def benchmark_classification(train_dataset,
  if metric == 'auc':
    classification_metric = dc.metrics.Metric(dc.metrics.roc_auc_score, np.mean)

  assert model in ['rf', 'tf', 'tf_robust', 'logreg', 'irv', 'graphconv']
  assert model in ['rf', 'tf', 'tf_robust', 'logreg', 'irv', 'graphconv',
                   'xgb_classifier']

  if model == 'tf':
    # Loading hyper parameters
@@ -564,6 +565,62 @@ def benchmark_classification(train_dataset,
      test_scores['rf'] = model_rf.evaluate(
          test_dataset, [classification_metric], transformers)

  if model == 'xgb_classifier':
    # Loading hyper parameters
    max_depth = hyper_parameters['max_depth']
    learning_rate = hyper_parameters['learning_rate']
    n_estimators = hyper_parameters['n_estimators']
    gamma = hyper_parameters['gamma']
    min_child_weight = hyper_parameters['min_child_weight']
    max_delta_step = hyper_parameters['max_delta_step']
    subsample = hyper_parameters['subsample']
    colsample_bytree = hyper_parameters['colsample_bytree']
    colsample_bylevel = hyper_parameters['colsample_bylevel']
    reg_alpha = hyper_parameters['reg_alpha']
    reg_lambda = hyper_parameters['reg_lambda']
    scale_pos_weight = hyper_parameters['scale_pos_weight']
    base_score = hyper_parameters['base_score']
    seed = hyper_parameters['seed']
    early_stopping_rounds = hyper_parameters['early_stopping_rounds']

    esr = {'early_stopping_rounds' : early_stopping_rounds}
    # Building xgboost classification model
    def model_builder(model_dir_xgb):
        xgboost_model = xgboost.XGBClassifier(
            max_depth=max_depth,
            learning_rate=learning_rate,
            n_estimators=n_estimators,
            gamma=gamma,
            min_child_weight=min_child_weight,
            max_delta_step=max_delta_step,
            subsample=subsample,
            colsample_bytree=colsample_bytree,
            colsample_bylevel=colsample_bylevel,
            reg_alpha=reg_alpha,
            reg_lambda=reg_lambda,
            scale_pos_weight=scale_pos_weight,
            base_score=base_score,
            seed=seed)
        return dc.models.xgboost_models.XGBoostModel(xgboost_model,
                                                            model_dir_xgb,
                                                            **esr)
    model_xgb = dc.models.multitask.SingletaskToMultitask(tasks, model_builder)

    print('-------------------------------------')
    print('Start fitting by xgoost')
    model_xgb.fit(train_dataset)

    # Evaluating xgboost classification model
    train_scores['xgb_classifier'] = model_xgb.evaluate(
        train_dataset, [classification_metric], transformers)

    valid_scores['xgb_classifier'] = model_xgb.evaluate(
       valid_dataset, [classification_metric], transformers)

    if test:
      test_scores['xgb_classifier'] = model_xgb.evaluate(
          test_dataset, [classification_metric], transformers)

  return train_scores, valid_scores, test_scores


@@ -623,7 +680,8 @@ def benchmark_regression(train_dataset,
    regression_metric = dc.metrics.Metric(dc.metrics.mean_absolute_error,
                                          np.mean)

  assert model in ['tf_regression', 'rf_regression', 'graphconvreg']
  assert model in ['tf_regression', 'rf_regression', 'graphconvreg',
                   'xgb_regression']

  if model == 'tf_regression':
    # Loading hyper parameters
@@ -766,6 +824,62 @@ def benchmark_regression(train_dataset,
      test_scores['rf_regression'] = model_rf_regression.evaluate(
          test_dataset, [regression_metric], transformers)

  if model == 'xgb_regression':
    # Loading hyper parameters
    max_depth = hyper_parameters['max_depth']
    learning_rate = hyper_parameters['learning_rate']
    n_estimators = hyper_parameters['n_estimators']
    gamma = hyper_parameters['gamma']
    min_child_weight = hyper_parameters['min_child_weight']
    max_delta_step = hyper_parameters['max_delta_step']
    subsample = hyper_parameters['subsample']
    colsample_bytree = hyper_parameters['colsample_bytree']
    colsample_bylevel = hyper_parameters['colsample_bylevel']
    reg_alpha = hyper_parameters['reg_alpha']
    reg_lambda = hyper_parameters['reg_lambda']
    scale_pos_weight = hyper_parameters['scale_pos_weight']
    base_score = hyper_parameters['base_score']
    seed = hyper_parameters['seed']
    early_stopping_rounds = hyper_parameters['early_stopping_rounds']

    esr = {'early_stopping_rounds' : early_stopping_rounds}
    # Building xgboost classification model
    def model_builder(model_dir_xgb):
        xgboost_model = xgboost.XGBRegressor(
            max_depth=max_depth,
            learning_rate=learning_rate,
            n_estimators=n_estimators,
            gamma=gamma,
            min_child_weight=min_child_weight,
            max_delta_step=max_delta_step,
            subsample=subsample,
            colsample_bytree=colsample_bytree,
            colsample_bylevel=colsample_bylevel,
            reg_alpha=reg_alpha,
            reg_lambda=reg_lambda,
            scale_pos_weight=scale_pos_weight,
            base_score=base_score,
            seed=seed)
        return dc.models.xgboost_models.XGBoostModel(xgboost_model,
                                                            model_dir_xgb,
                                                            **esr)
    model_xgb = dc.models.multitask.SingletaskToMultitask(tasks, model_builder)

    print('-------------------------------------')
    print('Start fitting by xgoost')
    model_xgb.fit(train_dataset)

    # Evaluating xgboost classification model
    train_scores['xgb_regression'] = model_xgb.evaluate(
        train_dataset, [regression_metric], transformers)

    valid_scores['xgb_regression'] = model_xgb.evaluate(
       valid_dataset, [regression_metric], transformers)

    if test:
      test_scores['xgb_regression'] = model_xgb.evaluate(
          test_dataset, [regression_metric], transformers)

  return train_scores, valid_scores, test_scores


@@ -788,7 +902,7 @@ if __name__ == '__main__':
      dest='model_args',
      default=[],
      help='Choice of model: tf, tf_robust, logreg, rf, irv, graphconv, ' +
      'tf_regression, rf_regression, graphconvreg')
      'tf_regression, rf_regression, graphconvreg, xgb_classifier, xgb_regression')
  parser.add_argument(
      '-d',
      action='append',
@@ -906,13 +1020,50 @@ if __name__ == '__main__':
      'seed': 123
  }]

  hps['xgb_classifier'] = [{
      'max_depth': 5,
      'learning_rate': 0.05,
      'n_estimators': 3000,
      'gamma': 0,
      'min_child_weight': 5,
      'max_delta_step': 1,
      'subsample': 0.53,
      'colsample_bytree': 0.66,
      'colsample_bylevel': 1,
      'reg_alpha': 0,
      'reg_lambda': 1,
      'scale_pos_weight': 1,
      'base_score': 0.5,
      'seed': 2016,
      'early_stopping_rounds': 100
  }]

  hps['xgb_regression'] = [{
      'max_depth': 5,
      'learning_rate': 0.05,
      'n_estimators': 3000,
      'gamma': 0,
      'min_child_weight': 5,
      'max_delta_step': 1,
      'subsample': 0.53,
      'colsample_bytree': 0.66,
      'colsample_bylevel': 1,
      'reg_alpha': 0,
      'reg_lambda': 1,
      'scale_pos_weight': 1,
      'base_score': 0.5,
      'seed': 2016,
      'early_stopping_rounds': 100
  }]

  for split in splitters:
    for dataset in datasets:
      if dataset in [
          'tox21', 'sider', 'muv', 'toxcast', 'pcba', 'clintox', 'hiv'
      ]:
        for model in models:
          if model in ['tf', 'tf_robust', 'logreg', 'graphconv', 'rf', 'irv']:
          if model in ['tf', 'tf_robust', 'logreg', 'graphconv', 'rf', 'irv',
                        'xgb_classifier']:
            benchmark_loading_datasets(
                hps,
                dataset=dataset,
@@ -922,7 +1073,8 @@ if __name__ == '__main__':
                test=test)
      else:
        for model in models:
          if model in ['tf_regression', 'rf_regression', 'graphconvreg']:
          if model in ['tf_regression', 'rf_regression', 'graphconvreg',
                        'xgb_regression']:
            benchmark_loading_datasets(
                hps,
                dataset=dataset,