Commit 38ba2870 authored by miaecle's avatar miaecle
Browse files

initialize weave build

parent 5fcb32b5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -399,7 +399,7 @@ class WeaveMol(object):

    self.nodes = nodes
    self.pairs = pairs
    self.num_atom = self.nodes.shape[0]
    self.num_atoms = self.nodes.shape[0]
    self.n_features = self.nodes.shape[1]

  def get_pair_features(self):
+33 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@ __license__ = "MIT"

import tensorflow as tf
from deepchem.nn.layers import GraphGather
from deepchem.models.tf_new_models.graph_topology import GraphTopology, DTNNGraphTopology, DAGGraphTopology
from deepchem.models.tf_new_models.graph_topology import GraphTopology, DTNNGraphTopology, DAGGraphTopology, WeaveGraphTopology


class SequentialGraph(object):
@@ -161,6 +161,38 @@ class SequentialDAGGraph(SequentialGraph):
        self.output = layer(self.output)
      self.layers.append(layer)

class SequentialWeaveGraph(SequentialGraph):
  """SequentialGraph for DAG models
  """

  def __init__(self, max_atoms=50, n_atom_feat=75, n_pair_feat=14):
    self.graph = tf.Graph()
    self.max_atoms = max_atoms
    self.n_atom_feat = n_atom_feat
    self.n_pair_feat = n_pair_feat
    with self.graph.as_default():
      self.graph_topology = WeaveGraphTopology(self.max_atoms, 
                                               self.n_atom_feat,
                                               self.n_pair_feat)
      self.output_A = self.graph_topology.get_atom_features_placeholder()
      self.output_P = self.graph_topology.get_pair_features_placeholder()
    self.layers = []

  def add(self, layer):
    """Adds a new layer to model."""
    with self.graph.as_default():
      if type(layer).__name__ in ['WeaveLayer']:
        self.output_A, self.output_P = layer([self.output_A, self.output_P] +
                            self.graph_topology.get_topology_placeholders())
      elif type(layer).__name__ in ['WeaveConcat']:
        self.output_A = layer(
            [self.output_A, self.graph_topology.atom_mask_placeholder])
      elif type(layer).__name__ in ['WeaveGather']:
        self.output_A = layer(
            [self.output_A, self.graph_topology.membership_placeholder])
      else:
        self.output_A = layer(self.output_A)
      self.layers.append(layer)
      
class SequentialSupportGraph(object):
  """An analog of Keras Sequential model for test/support models."""
+103 −0
Original line number Diff line number Diff line
@@ -392,3 +392,106 @@ class DAGGraphTopology(GraphTopology):
      else:
        output[ide] = self.batch_size * self.max_atoms
    return output

class WeaveGraphTopology(GraphTopology):
  """Manages placeholders associated with batch of graphs and their topology"""

  def __init__(self, max_atoms, n_atom_feat, n_pair_feat, name='DTNN_topology'):
    """
    Parameters
    ----------
    max_n_atoms: int
      maximum number of atoms in a molecule
    n_distance: int, optional
      granularity of distance matrix
      step size will be (distance_max-distance_min)/n_distance
    distance_min: float, optional
      minimum distance of atom pairs, default = -1 Angstorm
    distance_max: float, optional
      maximum distance of atom pairs, default = 18 Angstorm
    """

    #self.n_atoms = n_atoms
    self.name = name
    self.max_atoms = max_atoms
    self.n_atom_feat = n_atom_feat
    self.n_pair_feat = n_pair_feat

    self.atom_features_placeholder = tf.placeholder(
        dtype='float32',
        shape=(None, self.max_atoms, self.n_atom_feat),
        name=self.name + '_atom_features')
    self.atom_mask_placeholder = tf.placeholder(
        dtype='float32',
        shape=(None, self.max_atoms),
        name=self.name + '_atom_mask')
    self.pair_features_placeholder = tf.placeholder(
        dtype='float32',
        shape=(None, self.max_atoms, self.max_atoms, self.n_pair_feat),
        name=self.name + '_pair_features')
    self.pair_mask_placeholder = tf.placeholder(
        dtype='float32',
        shape=(None, self.max_atoms, self.max_atoms),
        name=self.name + '_pair_mask')
    self.membership_placeholder = tf.placeholder(
        dtype='int32',
        shape=(None,),
        name=self.name + '_membership')
    # Define the list of tensors to be used as topology
    self.topology = [self.atom_mask_placeholder, self.pair_mask_placeholder]
    self.inputs = [self.atom_features_placeholder]
    self.inputs += self.topology
    
  def get_pair_features_placeholder(self):
    return self.pair_features_placeholder

  def batch_to_feed_dict(self, batch):
    """Converts the current batch of WeaveMol into tensorflow feed_dict.

    Assigns the atom features and pair features to the
    placeholders tensors

    params
    ------
    batch : np.ndarray
      Array of WeaveMol

    returns
    -------
    feed_dict : dict
      Can be merged with other feed_dicts for input into tensorflow
    """
    # Extract atom numbers
    atom_feat = []
    pair_feat = []
    atom_mask = []
    pair_mask = []
    membership = []
    max_atoms = self.max_atoms
    for im, mol in enumerate(batch):
      n_atoms = mol.get_num_atoms()
      atom_feat.append(np.pad(mol.get_atom_features(), ((0, max_atoms - n_atoms), 
                                                        (0,0)), 
                              'constant'))
      atom_mask.append(np.array([1]*n_atoms + [0]*(max_atoms-n_atoms), dtype=float))
      pair_feat.append(np.pad(mol.get_pair_features(), ((0, max_atoms - n_atoms),
                                                        (0, max_atoms - n_atoms),
                                                        (0,0)),
                              'constant'))
      pair_mask.append(np.array([[1]*n_atoms + [0]*(max_atoms-n_atoms)]*n_atoms + \
                       [[0]*max_atoms]*(max_atoms-n_atoms), dtype=float))
      membership.extend([im]*n_atoms)
    atom_feat = np.stack(atom_feat)
    pair_feat = np.stack(pair_feat)
    atom_mask = np.stack(atom_mask)
    pair_mask = np.stack(pair_mask)
    membership = np.array(membership)
    # Generate dicts
    dict_DTNN = {
        self.atom_features_placeholder: atom_feat,
        self.pair_features_placeholder: pair_feat,
        self.atom_mask_placeholder: atom_mask,
        self.pair_mask_placeholder: pair_mask,
        self.membership_placeholder: membership
    }
    return dict_DTNN
 No newline at end of file
+6 −0
Original line number Diff line number Diff line
@@ -20,6 +20,10 @@ from deepchem.nn.layers import DTNNGather
from deepchem.nn.layers import DAGLayer
from deepchem.nn.layers import DAGGather

from deepchem.nn.weave_layers import WeaveLayer
from deepchem.nn.weave_layers import WeaveConcat
from deepchem.nn.weave_layers import WeaveGather

from deepchem.nn.model_ops import weight_decay
from deepchem.nn.model_ops import optimizer
from deepchem.nn.model_ops import add_bias
@@ -31,7 +35,9 @@ from deepchem.nn.objectives import mean_squared_error
from deepchem.models.tf_new_models.graph_topology import GraphTopology
from deepchem.models.tf_new_models.graph_topology import DTNNGraphTopology
from deepchem.models.tf_new_models.graph_topology import DAGGraphTopology
from deepchem.models.tf_new_models.graph_topology import WeaveGraphTopology
from deepchem.models.tf_new_models.graph_models import SequentialGraph
from deepchem.models.tf_new_models.graph_models import SequentialDTNNGraph
from deepchem.models.tf_new_models.graph_models import SequentialDAGGraph
from deepchem.models.tf_new_models.graph_models import SequentialWeaveGraph
from deepchem.models.tf_new_models.graph_models import SequentialSupportGraph
+19 −14
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ from deepchem.nn import activations
from deepchem.nn import initializations
from deepchem.nn import model_ops
from deepchem.nn.copy import Layer

from deepchem.nn import GraphGather

class WeaveLayer(Layer):
  """" Main layer of Weave model
@@ -108,9 +108,9 @@ class WeaveLayer(Layer):
        self.n_pair_output_feat,
    ])

    self.trainable_weights = self.W_AA + self.b_AA + self.W_PA + self.b_PA + \
        self.W_A + self.b_A + self.W_AP + self.b_AP + self.W_PP + self.b_PP + \
        self.W_P + self.b_P
    self.trainable_weights = [self.W_AA, self.b_AA, self.W_PA, self.b_PA,
        self.W_A, self.b_A, self.W_AP, self.b_AP, self.W_PP, self.b_PP,
        self.W_P, self.b_P]

  def call(self, x, mask=None):
    """Execute this layer on input tensors.
@@ -163,11 +163,11 @@ class WeaveConcat(Layer):
  """" Concat a batch of molecules into a batch of atoms
  """

  def __init__(self,
               **kwargs):
  def __init__(self, batch_size, **kwargs):
    self.batch_size = batch_size
    super(WeaveConcat, self).__init__(**kwargs)

  def build(self, shape):
  def build(self):
    pass

  def call(self, x, mask=None):
@@ -188,8 +188,8 @@ class WeaveConcat(Layer):
    self.build()
    atom_features = x[0]
    atom_masks = x[1]
    A = tf.unstack(atom_features, axis=0)
    A_mask = tf.unstack(tf.cast(atom_masks, dtype=tf.bool), axis=0)
    A = tf.split(atom_features, self.batch_size, axis=0)
    A_mask = tf.unstack(tf.cast(atom_masks, dtype=tf.bool), self.batch_size, axis=0)
    outputs = tf.concat([tf.boolean_mask(A[i], A_mask[i]) for i in range(len(A))], axis=0)
    return outputs

@@ -200,6 +200,7 @@ class WeaveGather(Layer):
  """

  def __init__(self,
               batch_size,
               n_atom_input_feat=50,
               n_hidden=128,
               init='glorot_uniform',
@@ -232,8 +233,9 @@ class WeaveGather(Layer):
      Whether to expand each dimension of atomic features by gaussian histogram

    """
    super(WeaveLayer, self).__init__(**kwargs)
    super(WeaveGather, self).__init__(**kwargs)

    self.batch_size = batch_size
    self.init = initializations.get(init)  # Set weight initialization
    self.activation = activations.get(activation)  # Get activations
    self.n_hidden = n_hidden
@@ -273,14 +275,17 @@ class WeaveGather(Layer):
    # Add trainable weights
    self.build()
    atom_features = x[0]
    atom_masks = x[1]
    membership = x[1]
    outputs = tf.matmul(atom_features, self.W) + self.b
    if self.gaussian_expand:
      outputs = self.gaussian_histogram(outputs)
    
    outputs = tf.reduce_sum(outputs, axis=1)
    outputs = tf.dynamic_partition(outputs, membership, self.batch_size)

    output_molecules = [tf.reduce_sum(molecule, 0) for molecule in outputs]

    output_molecules =  tf.stack(output_molecules)
    return outputs

  def gaussian_histogram(x):
      
    return x
Loading