Unverified Commit b1383f67 authored by Bharath Ramsundar's avatar Bharath Ramsundar Committed by GitHub
Browse files

Merge pull request #970 from peastman/lstm

Created LSTM layer
parents f51c17e6 ec2c93c1
Loading
Loading
Loading
Loading
+71 −1
Original line number Diff line number Diff line
@@ -820,7 +820,7 @@ class GRU(Layer):
  """A Gated Recurrent Unit.

  This layer expects its input to be of shape (batch_size, sequence_length, ...).
  It consists of a set of independent sequence (one for each element in the batch),
  It consists of a set of independent sequences (one for each element in the batch),
  that are each propagated independently through the GRU.
  """

@@ -879,6 +879,76 @@ class GRU(Layer):
    self.out_tensor, self.rnn_initial_states, self.rnn_final_states, self.rnn_zero_states = tensor


class LSTM(Layer):
  """A Long Short Term Memory.

  This layer expects its input to be of shape (batch_size, sequence_length, ...).
  It consists of a set of independent sequences (one for each element in the batch),
  that are each propagated independently through the LSTM.
  """

  def __init__(self, n_hidden, batch_size, **kwargs):
    """Create a Long Short Term Memory.

    Parameters
    ----------
    n_hidden: int
      the size of the LSTM's hidden state, which also determines the size of its output
    batch_size: int
      the batch size that will be used with this layer
    """
    self.n_hidden = n_hidden
    self.batch_size = batch_size
    super(LSTM, self).__init__(**kwargs)
    try:
      parent_shape = self.in_layers[0].shape
      self._shape = (batch_size, parent_shape[1], n_hidden)
    except:
      pass

  def create_tensor(self, in_layers=None, set_tensors=True, **kwargs):
    inputs = self._get_input_tensors(in_layers)
    if len(inputs) != 1:
      raise ValueError("Must have one parent")
    parent_tensor = inputs[0]
    lstm_cell = tf.contrib.rnn.LSTMCell(self.n_hidden)
    zero_state = lstm_cell.zero_state(self.batch_size, tf.float32)
    if set_tensors:
      initial_state = tf.contrib.rnn.LSTMStateTuple(
          tf.placeholder(tf.float32, zero_state.c.get_shape()),
          tf.placeholder(tf.float32, zero_state.h.get_shape()))
    else:
      initial_state = zero_state
    out_tensor, final_state = tf.nn.dynamic_rnn(
        lstm_cell, parent_tensor, initial_state=initial_state, scope=self.name)
    if set_tensors:
      self._record_variable_scope(self.name)
      self.out_tensor = out_tensor
      self.rnn_initial_states.append(initial_state.c)
      self.rnn_initial_states.append(initial_state.h)
      self.rnn_final_states.append(final_state.c)
      self.rnn_final_states.append(final_state.h)
      self.rnn_zero_states.append(
          np.zeros(zero_state.c.get_shape(), np.float32))
      self.rnn_zero_states.append(
          np.zeros(zero_state.h.get_shape(), np.float32))
    return out_tensor

  def none_tensors(self):
    saved_tensors = [
        self.out_tensor, self.rnn_initial_states, self.rnn_final_states,
        self.rnn_zero_states
    ]
    self.out_tensor = None
    self.rnn_initial_states = []
    self.rnn_final_states = []
    self.rnn_zero_states = []
    return saved_tensors

  def set_tensors(self, tensor):
    self.out_tensor, self.rnn_initial_states, self.rnn_final_states, self.rnn_zero_states = tensor


class TimeSeriesDense(Layer):

  def __init__(self, out_channels, **kwargs):
+16 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ from deepchem.models.tensorgraph.layers import InputFifoQueue
from deepchem.models.tensorgraph.layers import InteratomicL2Distances
from deepchem.models.tensorgraph.layers import IterRefLSTMEmbedding
from deepchem.models.tensorgraph.layers import L2Loss
from deepchem.models.tensorgraph.layers import LSTM
from deepchem.models.tensorgraph.layers import LSTMStep
from deepchem.models.tensorgraph.layers import Log
from deepchem.models.tensorgraph.layers import Multiply
@@ -172,6 +173,21 @@ class TestLayers(test_util.TensorFlowTestCase):
      out_tensor = out_tensor.eval()
      assert out_tensor.shape == (batch_size, n_steps, n_hidden)

  def test_lstm(self):
    """Test that LSTM can be invoked."""
    batch_size = 10
    n_hidden = 7
    in_channels = 4
    n_repeat = 2
    n_steps = 6
    in_tensor = np.random.rand(batch_size, n_steps, in_channels)
    with self.test_session() as sess:
      in_tensor = tf.convert_to_tensor(in_tensor, dtype=tf.float32)
      out_tensor = LSTM(n_hidden, batch_size)(in_tensor)
      sess.run(tf.global_variables_initializer())
      out_tensor = out_tensor.eval()
      assert out_tensor.shape == (batch_size, n_steps, n_hidden)

  def test_time_series_dense(self):
    """Test that TimeSeriesDense can be invoked."""
    batch_size = 10
+11 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ from deepchem.models import TensorGraph
from deepchem.models.tensorgraph.graph_layers import WeaveLayer, WeaveGather, DTNNEmbedding, DTNNGather, DTNNStep, \
  DTNNExtract, DAGLayer, DAGGather, MessagePassing, SetGather
from deepchem.models.tensorgraph.layers import Feature, Conv1D, Dense, Flatten, Reshape, Squeeze, Transpose, \
  CombineMeanStd, Repeat, Gather, GRU, L2Loss, Concat, SoftMax, \
  CombineMeanStd, Repeat, Gather, GRU, LSTM, L2Loss, Concat, SoftMax, \
  Constant, Variable, StopGradient, Add, Multiply, Log, Exp, InteratomicL2Distances, \
  SoftMaxCrossEntropy, ReduceMean, ToFloat, ReduceSquareDifference, Conv2D, MaxPool2D, ReduceSum, GraphConv, GraphPool, \
  GraphGather, BatchNorm, WeightedError, \
@@ -114,6 +114,16 @@ def test_GRU_pickle():
  tg.save()


def test_LSTM_pickle():
  tg = TensorGraph()
  feature = Feature(shape=(tg.batch_size, 10, 10))
  layer = LSTM(n_hidden=10, batch_size=tg.batch_size, in_layers=feature)
  tg.add_output(layer)
  tg.set_loss(layer)
  tg.build()
  tg.save()


def test_L2loss_pickle():
  tg = TensorGraph()
  feature = Feature(shape=(tg.batch_size, 1))