Commit d3ced331 authored by leswing's avatar leswing
Browse files

merge

parents 94e85b07 c39919e0
Loading
Loading
Loading
Loading
+282 −227

File changed.

Preview size limit exceeded, changes collapsed.

+36 −7
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ import collections
import deepchem as dc
from deepchem.nn import model_ops
from deepchem.utils.save import log
from deepchem.metrics import to_one_hot, from_one_hot
from deepchem.models.tensorflow_models import TensorflowGraph
from deepchem.models.tensorflow_models import TensorflowGraphModel
from deepchem.models.tensorflow_models import TensorflowClassifier
@@ -72,8 +73,7 @@ class TensorGraphMultiTaskClassifier(TensorGraph):
    n_classes: int
      the number of classes
    """
    super(TensorGraphMultiTaskClassifier, self).__init__(
        mode='classification', **kwargs)
    super(TensorGraphMultiTaskClassifier, self).__init__(**kwargs)
    self.n_tasks = n_tasks
    self.n_features = n_features
    self.n_classes = n_classes
@@ -150,6 +150,36 @@ class TensorGraphMultiTaskClassifier(TensorGraph):
          feed_dict[self.task_weights[0]] = w_b
        yield feed_dict

  def predict_proba(self, dataset, transformers=[], outputs=None):
    return super(TensorGraphMultiTaskClassifier, self).predict(
        dataset, transformers, outputs)

  def predict(self, dataset, transformers=[], outputs=None):
    """
    Uses self to make predictions on provided Dataset object.

    Parameters
    ----------
    dataset: dc.data.Dataset
      Dataset to make prediction on
    transformers: list
      List of dc.trans.Transformers.
    outputs: object 
      If outputs is None, then will assume outputs = self.outputs[0] (single
      output). If outputs is a Layer/Tensor, then will evaluate and return as a
      single ndarray. If outputs is a list of Layers/Tensors, will return a list
      of ndarrays.

    Returns
    -------
    y_pred: numpy ndarray or list of numpy ndarrays
    """
    # Results is of shape (n_samples, n_tasks, n_classes)
    retval = super(TensorGraphMultiTaskClassifier, self).predict(
        dataset, transformers, outputs)
    # retval is of shape (n_samples, n_tasks)
    return np.argmax(retval, axis=2)


class TensorGraphMultiTaskRegressor(TensorGraph):

@@ -197,8 +227,7 @@ class TensorGraphMultiTaskRegressor(TensorGraph):
      len(layer_sizes).  Alternatively this may be a single value instead of a list, in which case the
      same value is used for every layer.
    """
    super(TensorGraphMultiTaskRegressor, self).__init__(
        mode='regression', **kwargs)
    super(TensorGraphMultiTaskRegressor, self).__init__(**kwargs)
    self.n_tasks = n_tasks
    self.n_features = n_features
    n_layers = len(layer_sizes)
@@ -362,7 +391,7 @@ class TensorGraphMultiTaskFitTransformRegressor(TensorGraphMultiTaskRegressor):
          feed_dict[self.task_weights[0]] = w_b
        yield feed_dict

  def predict_proba_on_generator(self, generator, transformers=[]):
  def predict_on_generator(self, generator, transformers=[], outputs=None):

    def transform_generator():
      for feed_dict in generator:
@@ -375,8 +404,8 @@ class TensorGraphMultiTaskFitTransformRegressor(TensorGraphMultiTaskRegressor):
        yield feed_dict

    return super(TensorGraphMultiTaskFitTransformRegressor,
                 self).predict_proba_on_generator(transform_generator(),
                                                  transformers)
                 self).predict_on_generator(transform_generator(), transformers,
                                            outputs)


class TensorflowMultiTaskClassifier(TensorflowClassifier):
+79 −68
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ class WeaveTensorGraph(TensorGraph):
               n_pair_feat=14,
               n_hidden=50,
               n_graph_feat=128,
               mode="classification",
               **kwargs):
    """
    Parameters
@@ -41,13 +42,15 @@ class WeaveTensorGraph(TensorGraph):
      Number of units(convolution depths) in corresponding hidden layer
    n_graph_feat: int, optional
      Number of output features for each molecule(graph)

    mode: str
      Either "classification" or "regression" for type of model.
    """
    self.n_tasks = n_tasks
    self.n_atom_feat = n_atom_feat
    self.n_pair_feat = n_pair_feat
    self.n_hidden = n_hidden
    self.n_graph_feat = n_graph_feat
    self.mode = mode
    super(WeaveTensorGraph, self).__init__(**kwargs)
    self.build_graph()

@@ -187,6 +190,7 @@ class DTNNTensorGraph(TensorGraph):
               distance_min=-1,
               distance_max=18,
               output_activation=True,
               mode="classification",
               **kwargs):
    """
    Parameters
@@ -204,7 +208,8 @@ class DTNNTensorGraph(TensorGraph):
      minimum distance of atom pairs, default = -1 Angstorm
    distance_max: float, optional
      maximum distance of atom pairs, default = 18 Angstorm

    mode: str
      Either "classification" or "regression" for type of model.
    """
    self.n_tasks = n_tasks
    self.n_embedding = n_embedding
@@ -217,6 +222,7 @@ class DTNNTensorGraph(TensorGraph):
        [distance_min + i * self.step_size for i in range(n_distance)])
    self.steps = np.expand_dims(self.steps, 0)
    self.output_activation = output_activation
    self.mode = mode
    super(DTNNTensorGraph, self).__init__(**kwargs)
    assert self.mode == "regression"
    self.build_graph()
@@ -335,6 +341,7 @@ class DAGTensorGraph(TensorGraph):
               n_atom_feat=75,
               n_graph_feat=30,
               n_outputs=30,
               mode="classification",
               **kwargs):
    """
    Parameters
@@ -349,13 +356,15 @@ class DAGTensorGraph(TensorGraph):
      Number of features for atom in the graph
    n_outputs: int, optional
      Number of features for each molecule

    mode: str
      Either "classification" or "regression" for type of model.
    """
    self.n_tasks = n_tasks
    self.max_atoms = max_atoms
    self.n_atom_feat = n_atom_feat
    self.n_graph_feat = n_graph_feat
    self.n_outputs = n_outputs
    self.mode = mode
    super(DAGTensorGraph, self).__init__(**kwargs)
    self.build_graph()

@@ -477,15 +486,17 @@ class DAGTensorGraph(TensorGraph):

class GraphConvTensorGraph(TensorGraph):

  def __init__(self, n_tasks, **kwargs):
  def __init__(self, n_tasks, mode="classification", **kwargs):
    """
    Parameters
    ----------
    n_tasks: int
      Number of tasks

    mode: str
      Either "classification" or "regression"
    """
    self.n_tasks = n_tasks
    self.mode = mode
    self.error_bars = True if 'error_bars' in kwargs and kwargs['error_bars'] else False
    kwargs['use_queue'] = False
    super(GraphConvTensorGraph, self).__init__(**kwargs)
+109 −91
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ import threading
import time

import networkx as nx
import collections
import numpy as np
import os
import six
@@ -28,12 +29,10 @@ class TensorGraph(Model):
               batch_size=100,
               random_seed=None,
               use_queue=True,
               mode="regression",
               graph=None,
               learning_rate=0.001,
               **kwargs):
    """
    TODO(LESWING) allow a model to change its learning rate
    Parameters
    ----------
    tensorboard: bool
@@ -48,10 +47,6 @@ class TensorGraph(Model):
      queue in batches of self.batch_size in a separate thread from the
      thread training the model.  You cannot use a queue when
      batches are not of consistent size
    mode: str
      "regression" or "classification".  "classification" models on
      predict will do an argmax(axis=2) to determine the class of the
      prediction.
    graph: tensorflow.Graph
      the Graph in which to create Tensorflow objects.  If None, a new Graph
      is created.
@@ -85,7 +80,6 @@ class TensorGraph(Model):
    self.tensorboard = tensorboard
    self.tensorboard_log_frequency = tensorboard_log_frequency
    self.tensorboard_step = 0
    self.mode = mode
    self.global_step = 0
    self.last_checkpoint = None
    self.use_queue = use_queue
@@ -185,10 +179,8 @@ class TensorGraph(Model):
                                                          avg_loss))
        saver.save(sess, self.save_file, global_step=self.global_step)
        self.last_checkpoint = saver.last_checkpoints[-1]
      ############################################################## TIMING
      time2 = time.time()
      print("TIMING: model fitting took %0.3f s" % (time2 - time1))
      ############################################################## TIMING

  def _log_tensorboard(self, summary):
    """
@@ -238,123 +230,146 @@ class TensorGraph(Model):
          feed_dict[initial_state] = zero_state
        yield feed_dict

  def predict_on_generator(self, generator, transformers=[]):
    """Generates output predictions for the input samples,
      processing the samples in a batched way.

    # Arguments
        x: the input data, as a Numpy array.
        batch_size: integer.
        verbose: verbosity mode, 0 or 1.

    # Returns
        A Numpy array of predictions.
    """
    retval = self.predict_proba_on_generator(generator, transformers)
    if self.mode == 'classification':
      retval = np.expand_dims(from_one_hot(retval, axis=2), axis=1)
    return retval

  def predict_proba_on_generator(self, generator, transformers=[]):
  def predict_on_generator(self, generator, transformers=[], outputs=None):
    """
    Parameters
    ----------
    generator: Generator
      Generator that constructs feed dictionaries for TensorGraph.
    transformers: list
      List of dc.trans.Transformers.
    outputs: object
      If outputs is None, then will assume outputs = self.outputs.
      If outputs is a Layer/Tensor, then will evaluate and return as a
      single ndarray. If outputs is a list of Layers/Tensors, will return a list
      of ndarrays.
    Returns:
      y_pred: numpy ndarray of shape (n_samples, n_classes*n_tasks)
    """
    if not self.built:
      self.build()
    if outputs is None:
      outputs = self.outputs
    elif not isinstance(outputs, collections.Sequence):
      outputs = [outputs]
    with self._get_tf("Graph").as_default():
      with tf.Session() as sess:
        saver = tf.train.Saver()
        self._initialize_weights(sess, saver)
        out_tensors = [x.out_tensor for x in self.outputs]
        results = []
        # Gather results for each output
        results = [[] for out in out_tensors]
        for feed_dict in generator:
          feed_dict = {
              self.layers[k.name].out_tensor: v
              for k, v in six.iteritems(feed_dict)
          }
          feed_dict[self._training_placeholder] = 0.0
          result = np.array(sess.run(out_tensors, feed_dict=feed_dict))
          if len(result.shape) == 3:
            result = np.transpose(result, axes=[1, 0, 2])
          result = undo_transforms(result, transformers)
          results.append(result)
        return np.concatenate(results, axis=0)

  def bayesian_predict_on_batch(self, X, transformers=[], n_passes=4):
          feed_results = sess.run(out_tensors, feed_dict=feed_dict)
          if len(feed_results) > 1:
            if len(transformers):
              raise ValueError("Does not support transformations "
                               "for multiple outputs.")
          elif len(feed_results) == 1:
            result = undo_transforms(feed_results[0], transformers)
            feed_results = [result]
          for ind, result in enumerate(feed_results):
            results[ind].append(result)

        final_results = []
        for result_list in results:
          final_results.append(np.concatenate(result_list, axis=0))
        # If only one output, just return array
        if len(final_results) == 1:
          return final_results[0]
        else:
          return final_results

  def predict_proba_on_generator(self, generator, transformers=[],
                                 outputs=None):
    """
    Returns:
      mu: numpy ndarray of shape (n_samples, n_tasks)
      sigma: numpy ndarray of shape (n_samples, n_tasks)
    """
    dataset = NumpyDataset(X=X, y=None, n_tasks=len(self.outputs))
    y_ = []
    for i in range(n_passes):
      generator = self.default_generator(
          dataset, predict=True, pad_batches=True)
      y_.append(self.predict_on_generator(generator, transformers))

    y_ = np.concatenate(y_, axis=2)
    mu = np.mean(y_, axis=2)
    sigma = np.std(y_, axis=2)

    return mu, sigma

  def predict_on_smiles_batch(self,
                              smiles,
                              featurizer,
                              n_tasks,
                              transformers=[]):
    """
    # Returns:
      A numpy ndarray of shape (n_samples, n_tasks)
      y_pred: numpy ndarray of shape (n_samples, n_classes*n_tasks)
    """
    convmols = featurize_smiles_np(smiles, featurizer)

    dataset = NumpyDataset(X=convmols, y=None, n_tasks=len(self.outputs))
    generator = self.default_generator(dataset, predict=True, pad_batches=True)
    return self.predict_on_generator(generator, transformers)
    return self.predict_on_generator(generator, transformers, outputs)

  def predict_on_batch(self, X, sess=None, transformers=[]):
    """Generates output predictions for the input samples,
      processing the samples in a batched way.
  def predict_on_batch(self, X, transformers=[]):
    """Generates predictions for input samples, processing samples in a batch.

    # Arguments
        x: the input data, as a Numpy array.
        batch_size: integer.
        verbose: verbosity mode, 0 or 1.
    Parameters
    ---------- 
    X: ndarray
      the input data, as a Numpy array.
    transformers: List
      List of dc.trans.Transformers 

    # Returns
    Returns
    -------
    A Numpy array of predictions.
    """
    dataset = NumpyDataset(X=X, y=None)
    generator = self.default_generator(dataset, predict=True, pad_batches=False)
    return self.predict_on_generator(generator, transformers)

  def predict_proba_on_batch(self, X, sess=None, transformers=[]):
    dataset = NumpyDataset(X=X, y=None)
    generator = self.default_generator(dataset, predict=True, pad_batches=False)
    return self.predict_proba_on_generator(generator, transformers)
  def predict_proba_on_batch(self, X, transformers=[]):
    """Generates predictions for input samples, processing samples in a batch.

    Parameters
    ---------- 
    X: ndarray
      the input data, as a Numpy array.
    transformers: List
      List of dc.trans.Transformers 

    Returns
    -------
    A Numpy array of predictions.
    """
    return self.predict_on_batch(X, transformers)

  def predict(self, dataset, transformers=[], batch_size=None):
  def predict(self, dataset, transformers=[], outputs=None):
    """
    Uses self to make predictions on provided Dataset object.

    Returns:
      y_pred: numpy ndarray of shape (n_samples,)
    Parameters
    ----------
    dataset: dc.data.Dataset
      Dataset to make prediction on
    transformers: list
      List of dc.trans.Transformers.
    outputs: object 
      If outputs is None, then will assume outputs = self.outputs[0] (single
      output). If outputs is a Layer/Tensor, then will evaluate and return as a
      single ndarray. If outputs is a list of Layers/Tensors, will return a list
      of ndarrays.

    Returns
    -------
    results: numpy ndarray or list of numpy ndarrays
    """
    generator = self.default_generator(dataset, predict=True, pad_batches=False)
    return self.predict_on_generator(generator, transformers)
    return self.predict_on_generator(generator, transformers, outputs)

  def predict_proba(self, dataset, transformers=[], batch_size=None):
  def predict_proba(self, dataset, transformers=[], outputs=None):
    """
    TODO: Do transformers even make sense here?
    Parameters
    ----------
    dataset: dc.data.Dataset
      Dataset to make prediction on
    transformers: list
      List of dc.trans.Transformers.
    outputs: object 
      If outputs is None, then will assume outputs = self.outputs[0] (single
      output). If outputs is a Layer/Tensor, then will evaluate and return as a
      single ndarray. If outputs is a list of Layers/Tensors, will return a list
      of ndarrays.

    Returns:
      y_pred: numpy ndarray of shape (n_samples, n_classes*n_tasks)
    Returns
    -------
    y_pred: numpy ndarray or list of numpy ndarrays
    """
    generator = self.default_generator(dataset, predict=True, pad_batches=False)
    return self.predict_proba_on_generator(generator, transformers)
    return self.predict_proba_on_generator(generator, transformers, outputs)

  def topsort(self):
    return nx.topological_sort(self.nxgraph)
@@ -550,12 +565,15 @@ class TensorGraph(Model):
    return self._get_tf("GlobalStep")

  def _get_tf(self, obj):
    """
    TODO(LESWING) REALLY NEED TO DOCUMENT THIS
    """Fetches underlying TensorFlow primitives.

    Parameters
    ----------
    obj

    obj: str
      If "Graph", returns tf.Graph instance. If "FileWriter", returns
      tf.summary.FileWriter. If "Optimizer", returns the optimizer. If
      "train_op", returns the train operation. If "summary_op", returns the
      merged summary. If "GlobalStep" returns the global step.
    Returns
    -------
    TensorFlow Object
+13 −14
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ class TestTensorGraph(unittest.TestCase):
    tg.add_output(output)
    tg.set_loss(loss)
    tg.fit(dataset, nb_epoch=1000)
    prediction = np.squeeze(tg.predict_proba_on_batch(X))
    prediction = np.squeeze(tg.predict_on_batch(X))
    assert_true(np.all(np.isclose(prediction, y, atol=0.4)))

  @flaky
@@ -78,10 +78,10 @@ class TestTensorGraph(unittest.TestCase):
    tg.fit_generator(
        databag.iterbatches(
            epochs=1000, batch_size=tg.batch_size, pad_batches=True))
    prediction = tg.predict_proba_on_generator(databag.iterbatches())
    predictions = tg.predict_on_generator(databag.iterbatches())
    for i in range(2):
      y_real = ys[i].X
      y_pred = prediction[:, i, :]
      y_pred = predictions[i]
      assert_true(np.all(np.isclose(y_pred, y_real, atol=0.6)))

  def test_single_task_regressor(self):
@@ -98,7 +98,7 @@ class TestTensorGraph(unittest.TestCase):
    tg.add_output(dense)
    tg.set_loss(loss)
    tg.fit(dataset, nb_epoch=1000)
    prediction = np.squeeze(tg.predict_proba_on_batch(X))
    prediction = np.squeeze(tg.predict_on_batch(X))
    assert_true(np.all(np.isclose(prediction, y, atol=3.0)))

  def test_multi_task_regressor(self):
@@ -137,10 +137,10 @@ class TestTensorGraph(unittest.TestCase):
    tg.fit_generator(
        databag.iterbatches(
            epochs=1000, batch_size=tg.batch_size, pad_batches=True))
    prediction = tg.predict_proba_on_generator(databag.iterbatches())
    predictions = tg.predict_on_generator(databag.iterbatches())
    for i in range(2):
      y_real = ys[i].X
      y_pred = prediction[:, i, :]
      y_pred = predictions[i]
      assert_true(np.all(np.isclose(y_pred, y_real, atol=1.5)))

  @flaky
@@ -160,7 +160,7 @@ class TestTensorGraph(unittest.TestCase):
    tg.add_output(output)
    tg.set_loss(loss)
    tg.fit(dataset, nb_epoch=1000)
    prediction = np.squeeze(tg.predict_proba_on_batch(X))
    prediction = np.squeeze(tg.predict_on_batch(X))
    assert_true(np.all(np.isclose(prediction, y, atol=0.4)))

  @flaky
@@ -184,11 +184,11 @@ class TestTensorGraph(unittest.TestCase):
        initial_rate=0.1, decay_rate=0.96, decay_steps=100000)
    tg.set_optimizer(GradientDescent(learning_rate=learning_rate))
    tg.fit(dataset, nb_epoch=1000)
    prediction = np.squeeze(tg.predict_proba_on_batch(X))
    prediction = np.squeeze(tg.predict_on_batch(X))
    tg.save()

    tg1 = TensorGraph.load_from_dir(tg.model_dir)
    prediction2 = np.squeeze(tg1.predict_proba_on_batch(X))
    prediction2 = np.squeeze(tg1.predict_on_batch(X))
    assert_true(np.all(np.isclose(prediction, prediction2, atol=0.01)))

  @nottest
@@ -235,11 +235,11 @@ class TestTensorGraph(unittest.TestCase):
    tg.add_output(output)
    tg.set_loss(loss)
    tg.fit(dataset, nb_epoch=1)
    prediction = np.squeeze(tg.predict_proba_on_batch(X))
    prediction = np.squeeze(tg.predict_on_batch(X))
    tg.save()

    tg1 = TensorGraph.load_from_dir(tg.model_dir)
    prediction2 = np.squeeze(tg1.predict_proba_on_batch(X))
    prediction2 = np.squeeze(tg1.predict_on_batch(X))
    assert_true(np.all(np.isclose(prediction, prediction2, atol=0.01)))

  def test_shared_layer(self):
@@ -279,6 +279,5 @@ class TestTensorGraph(unittest.TestCase):
    tg.fit_generator(
        databag.iterbatches(
            epochs=1, batch_size=tg.batch_size, pad_batches=True))
    prediction = tg.predict_proba_on_generator(databag.iterbatches())
    assert_true(
        np.all(np.isclose(prediction[:, 0], prediction[:, 1], atol=0.01)))
    prediction = tg.predict_on_generator(databag.iterbatches())
    assert_true(np.all(np.isclose(prediction[0], prediction[1], atol=0.01)))
Loading