Commit 5e47d6d7 authored by Bharath Ramsundar's avatar Bharath Ramsundar
Browse files

Added classifiers to BACE notebook.

parent 84ea2a9b
Loading
Loading
Loading
Loading
+22 −37
Original line number Diff line number Diff line
"""
Contains basic hyperparameter optimizations.
"""
import numpy as np
import itertools
import tempfile
import shutil
import collections
from operator import mul
from deepchem.utils.evaluate import Evaluator

model_params = {"activation": "relu",
                "momentum": .9,
                "batch_size": 50,
                "init": "glorot_uniform",
                "data_shape": train_dataset.get_data_shape()}
lr_list = np.power(10., np.random.uniform(-5, -2, size=5))
decay_list = np.power(10, np.random.uniform(-6, -4, size=5))
nb_hidden_list = [500, 1000]
nb_epoch_list = [40]
nesterov_list = [False]
dropout_list = [0, .5]
nb_layers_list = [1]
batchnorm_list = [False]

#hyperparameters = [lr_list, decay_list, nb_layers_list,
#                   nb_hidden_list, nb_epoch_list, nesterov_list,
#                   dropout_list, batchnorm_list]
#    model_params["learning_rate"] = lr
#    model_params["decay"] = decay
#    model_params["nb_layers"] = nb_layers
#    model_params["nb_hidden"] = nb_hidden
#    model_params["nb_epoch"] = nb_epoch
#    model_params["nesterov"] = nesterov
#    model_params["dropout"] = dropout
#    model_params["batchnorm"] = batchnorm

class HyperparameterOpt(object):
class HyperparamOpt(object):
  """
  Provides simple hyperparameter search capabilities.
  """

  def __init__(model_class, task_types):
  def __init__(self, model_class, task_types):
    self.model_class = model_class
    self.task_types = task_types

  def hyperparam_search(params_dict, train_dataset, validation_dataset,
                        metric="r2_score"):
  def hyperparam_search(self, params_dict, train_dataset, valid_dataset,
                        output_transformers, metric):
    """Perform hyperparams search according to params_dict.
    
    Each key to hyperparams_dict is a model_param. The values should be a list
    of potential values for that hyperparam. 
    """
    hyperparams = params_dict.keys()
    hyperparam_vals = [params_dict[hyperparam] for hyperparam in hyperparams]
    for hyperparam_list in hyperparams:
      assert isinstance(hyperparam_list, list)
    hyperparam_vals = params_dict.values() 
    for hyperparam_list in params_dict.itervalues():
      assert isinstance(hyperparam_list, collections.Iterable)

    number_combinations = reduce(mul, [len(vals) for vals in hyperparam_vals])

    valid_csv_out = tempfile.NamedTemporaryFile()
    valid_stats_out = tempfile.NamedTemporaryFile()
    best_validation_score = -np.inf
    best_hyperparams = None
    best_model, best_model_dir = None, None
    all_scores = {}
    for ind, hyperparameter_tuple in enumerate(itertools.product(*hyperparameters)):
    for ind, hyperparameter_tuple in enumerate(itertools.product(*hyperparam_vals)):
      model_params = {}
      for hyperparam, hyperparam_val in zip(hyperparams, hyperparameter_tuple):
        model_params[hyperparam] = hyperparam_val

      model_dir = tempfile.mkdtemp()
      model = self.model_class(task_types, model_params, verbosity=None)
      model = self.model_class(self.task_types, model_params, verbosity=None)
      model.fit(train_dataset)
      model.save(model_dir)
    
@@ -68,7 +52,8 @@ class HyperparameterOpt(object):
      df, score = evaluator.compute_model_performance(
          valid_csv_out, valid_stats_out)
      valid_score = score.iloc[0][metric]
      print("Model %d, Validation set %s: %f" % (metric, ind, valid_score))
      print("Model %d/%d, Metric %s, Validation set %s: %f" %
            (ind, number_combinations, metric, ind, valid_score))
      all_scores[hyperparameter_tuple] = valid_score
    
      if valid_score > best_validation_score:
@@ -81,6 +66,6 @@ class HyperparameterOpt(object):
      else:
        shutil.rmtree(model_dir)

    print("Best hyperparameters: %s" % str(best_hyperparams))
    print("Best hyperparameters: %s" % str(zip(hyperparams, best_hyperparams)))
    print("best_validation_score: %f" % best_validation_score)
    return best_model, best_hyperparams, all_scores
+12 −1
Original line number Diff line number Diff line
@@ -14,6 +14,13 @@ from deepchem.utils.dataset import load_from_disk
from deepchem.utils.dataset import save_to_disk
from deepchem.utils.save import log

def undo_transforms(y, transformers):
  """Undoes all transformations applied."""
  # Note that transformers have to be undone in reversed order
  for transformer in reversed(transformers):
    y = transformer.untransform(y)
  return y

class Model(object):
  """
  Abstract base class for different ML models.
@@ -113,7 +120,7 @@ class Model(object):

  # TODO(rbharath): The structure of the produced df might be
  # complicated. Better way to model?
  def predict(self, dataset):
  def predict(self, dataset, transformers):
    """
    Uses self to make predictions on provided Dataset object.
    """
@@ -139,6 +146,10 @@ class Model(object):
      y_pred = np.concatenate(y_preds)
      y_pred = np.reshape(y_pred, np.shape(y))

      # Now undo transformations on y, y_pred
      y = undo_transforms(y, transformers)
      y_pred = undo_transforms(y_pred, transformers)

      shard_df = pd.DataFrame(columns=column_names)
      shard_df['ids'] = ids
      shard_df[task_names] = y
+0 −4
Original line number Diff line number Diff line
@@ -171,8 +171,6 @@ class MultiTaskDNN(KerasModel):
    y_pred = np.squeeze(y_pred)
    return y_pred

Model.register_model_type(MultiTaskDNN)

class SingleTaskDNN(MultiTaskDNN):
  """
  Abstract base class for different ML models.
@@ -182,8 +180,6 @@ class SingleTaskDNN(MultiTaskDNN):
                                        initialize_raw_model=initialize_raw_model,
                                        verbosity=verbosity)

Model.register_model_type(SingleTaskDNN)

def to_one_hot(y):
  """Transforms label vector into one-hot encoding.

+2 −2
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ class SklearnModel(Model):
    """
    return self.raw_model.predict(X)

  def predict(self, X):
  def predict(self, X, transformers):
    """
    Makes predictions on dataset.
    """
@@ -56,7 +56,7 @@ class SklearnModel(Model):
    #TODO(enf/rbharath): This is kludgy. Fix later.
    if "batch_size" not in self.model_params.keys():
      self.model_params["batch_size"] = 32
    return super(SklearnModel, self).predict(X)
    return super(SklearnModel, self).predict(X, transformers)

  def save(self, out_dir):
    """Saves sklearn model to disk using joblib."""
+3 −12
Original line number Diff line number Diff line
@@ -20,13 +20,6 @@ __author__ = "Bharath Ramsundar"
__copyright__ = "Copyright 2015, Stanford University"
__license__ = "LGPL"

def undo_transforms(y, transformers):
  """Undoes all transformations applied."""
  # Note that transformers have to be undone in reversed order
  for transformer in reversed(transformers):
    y = transformer.untransform(y)
  return y

def compute_roc_auc_scores(y, y_pred):
  """Transforms the results dict into roc-auc-scores and prints scores.

@@ -61,9 +54,7 @@ class Evaluator(object):
    """
    Computes statistics of model on test data and saves results to csv.
    """
    pred_y_df = self.model.predict(self.dataset)
    log("Saving predictions to %s" % csv_out, self.verbose)
    pred_y_df.to_csv(csv_out)
    pred_y_df = self.model.predict(self.dataset, self.transformers)

    if self.task_type == "classification":
      colnames = ["task_name", "roc_auc_score", "matthews_corrcoef",
@@ -79,8 +70,6 @@ class Evaluator(object):
      y = pred_y_df[task_name].values
      y_pred = pred_y_df["%s_pred" % task_name].values
      w = pred_y_df["%s_weight" % task_name].values
      y = undo_transforms(y, self.transformers)
      y_pred = undo_transforms(y_pred, self.transformers)

      if self.task_type == "classification":
        y, y_pred = y[w.nonzero()].astype(int), y_pred[w.nonzero()].astype(int)
@@ -102,6 +91,8 @@ class Evaluator(object):
          rms = np.nan
        performance_df.loc[i] = [task_name, r2s, rms]

    log("Saving predictions to %s" % csv_out, self.verbose)
    pred_y_df.to_csv(csv_out)
    log("Saving model performance scores to %s" % stats_file, self.verbose)
    performance_df.to_csv(stats_file)

Loading