Commit aa77fac9 authored by Bharath Ramsundar's avatar Bharath Ramsundar
Browse files

Added SingletaskToMultitask

parent d5170c26
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ class HyperparamOpt(object):
    assert verbosity in [None, "low", "high"]
    self.verbosity = verbosity

  # TODO(rbharath): This function is complicated and monolithic. Is there a nice
  # way to refactor this?
  def hyperparam_search(self, params_dict, train_dataset, valid_dataset,
                        output_transformers, metric, use_max=True,
                        logdir=None):
+34 −1
Original line number Diff line number Diff line
@@ -20,7 +20,8 @@ from deepchem.featurizers.fingerprints import CircularFingerprint
from deepchem.transformers import NormalizationTransformer
from deepchem import metrics
from deepchem.metrics import Metric
from sklearn.ensemble import RandomForestRegressor
from deepchem.models.multitask import SingletaskToMultitask 
from sklearn.linear_model import LogisticRegression

def rf_model_builder(task_types, params_dict, logdir=None, verbosity=None):
    """Builds random forests given hyperparameters.
@@ -63,6 +64,38 @@ class TestHyperparamOptAPI(TestAPI):
                         valid_dataset, output_transformers, task_types,
                         metric)

  def test_singletask_to_multitask_sklearn_hyperparam_opt(self):
    """Test of hyperparam_opt with singletask_to_multitask."""
    splittype = "scaffold"
    compound_featurizers = [CircularFingerprint(size=1024)]
    complex_featurizers = []
    output_transformer_classes = []
    input_transformer_classes = []
    tasks = ["task0", "task1", "task2", "task3", "task4", "task5", "task6",
             "task7", "task8", "task9", "task10", "task11", "task12",
             "task13", "task14", "task15", "task16"]
    task_types = {task: "classification" for task in tasks}
    input_file = "multitask_example.csv"
    train_dataset, valid_dataset, _, output_transformers, = \
        self._featurize_train_test_split(
            splittype, compound_featurizers, 
            complex_featurizers, input_transformer_classes,
            output_transformer_classes, input_file, task_types.keys())
    params_dict = {
        "batch_size": [32],
        "data_shape": [train_dataset.get_data_shape()],
    }
    classification_metric = Metric(metrics.matthews_corrcoef, np.mean)
    def model_builder(task_types, model_params, verbosity=None):
      return SklearnModel(task_types, model_params,
                          model_instance=LogisticRegression())
    def multitask_model_builder(task_types, params_dict, logdir=None,
                                verbosity=None):
      return SingletaskToMultitask(task_types, params_dict, model_builder)
    self._hyperparam_opt(multitask_model_builder, params_dict, train_dataset,
                         valid_dataset, output_transformers, task_types,
                         classification_metric)

  def test_multitask_keras_mlp_ECFP_classification_hyperparam_opt(self):
    """Straightforward test of Keras multitask deepchem classification API."""
    from deepchem.models.keras_models.fcnet import MultiTaskDNN
+0 −1
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ class Model(object):
  """
  Abstract base class for different ML models.
  """
  non_sklearn_models = ["SingleTaskDNN", "MultiTaskDNN", "DockingDNN"]
  def __init__(self, task_types, model_params, fit_transformers=None,
               model_instance=None, initialize_raw_model=True, 
               verbosity=None, **kwargs):
+47 −0
Original line number Diff line number Diff line
"""
Convenience class that lets singletask models fit on multitask data.
"""
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals

import numpy as np
from deepchem.models import Model


class SingletaskToMultitask(Model):
  """
  Convenience class to let singletask models be fit on multitask data.

  Warning: This current implementation is only functional for sklearn models. 
  """
  def __init__(self, task_types, model_params, model_builder, verbosity=None):
    self.task_types = task_types
    self.model_params = model_params
    self.models = {}
    self.fit_transformers = False
    for task, task_type in self.task_types.iteritems():
      self.models[task] = model_builder(task_types, model_params,
                                        verbosity=verbosity)
      
  def fit(self, dataset):
    """
    Updates all singletask models with new information.

    Warning: This current implementation is only functional for sklearn models. 
    """
    X, y, _, _ = dataset.to_numpy()
    for ind, task in enumerate(self.task_types.keys()):
      y_task = y[:, ind]
      self.models[task].raw_model.fit(X, y_task)

  def predict_on_batch(self, X):
    """
    Concatenates results from all singletask models.
    """
    N_tasks = len(self.task_types.keys())
    N_samples = X.shape[0]
    y_pred = np.zeros((N_samples, N_tasks))
    for ind, task in enumerate(self.task_types.keys()):
      y_pred[:, ind] = self.models[task].predict_on_batch(X)
    return y_pred
+50 −0
Original line number Diff line number Diff line
"""
Testing singletask-to-multitask.
"""
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals

__author__ = "Bharath Ramsundar"
__copyright__ = "Copyright 2016, Stanford University"
__license__ = "LGPL"

from deepchem.models.test import TestAPI
from deepchem import metrics
from deepchem.metrics import Metric
from deepchem.featurizers.fingerprints import CircularFingerprint
from deepchem.models.multitask import SingletaskToMultitask 
from deepchem.models.sklearn_models import SklearnModel
from sklearn.linear_model import LogisticRegression

class TestSingletasktoMultitaskAPI(TestAPI):
  """
  Test top-level API for singletask_to_multitask ML models.
  """
  def test_singletask_to_multitask_classification(self):
    splittype = "scaffold"
    compound_featurizers = [CircularFingerprint(size=1024)]
    complex_featurizers = []
    output_transformer_classes = []
    input_transformer_classes = []
    tasks = ["task0", "task1", "task2", "task3", "task4", "task5", "task6",
             "task7", "task8", "task9", "task10", "task11", "task12",
             "task13", "task14", "task15", "task16"]
    task_types = {task: "classification" for task in tasks}
    input_file = "multitask_example.csv"
    train_dataset, test_dataset, _, output_transformers, = \
        self._featurize_train_test_split(
            splittype, compound_featurizers, 
            complex_featurizers, input_transformer_classes,
            output_transformer_classes, input_file, task_types.keys())
    params_dict = {
        "batch_size": 32,
        "data_shape": train_dataset.get_data_shape()
    }
    classification_metrics = [Metric(metrics.roc_auc_score)]
    def model_builder(task_types, model_params, verbosity=None):
      return SklearnModel(task_types, model_params,
                          model_instance=LogisticRegression())
    multitask_model = SingletaskToMultitask(task_types, params_dict, model_builder)
    self._create_model(train_dataset, test_dataset, multitask_model,
                       output_transformers, classification_metrics)