Commit 8a8a1348 authored by peastman's avatar peastman
Browse files

Beginning to convert layers to support eager mode

parent 7342aa8c
Loading
Loading
Loading
Loading
+33 −15
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ import tensorflow as tf
import numpy as np

from deepchem.models.tensorgraph import model_ops, initializations, regularizers, activations
import tensorflow.contrib.eager as tfe
import math


@@ -25,7 +26,6 @@ class Layer(object):
      in_layers = [in_layers]
    self.in_layers = in_layers
    self.op_type = "gpu"
    self.variable_scope = ''
    self.variable_values = None
    self.out_tensor = None
    self.rnn_initial_states = []
@@ -33,6 +33,10 @@ class Layer(object):
    self.rnn_zero_states = []
    self.tensorboard = False
    self.tb_input = None
    if tfe.in_eager_mode():
      self.variables = []
    else:
      self.variable_scope = ''

  def _get_layer_number(self):
    class_name = self.__class__.__name__
@@ -83,8 +87,8 @@ class Layer(object):
      return self.clone(in_layers)
    raise ValueError('%s does not implement shared()' % self.__class__.__name__)

  def __call__(self, *in_layers):
    return self.create_tensor(in_layers=in_layers, set_tensors=False)
  def __call__(self, *in_layers, training=False):
    return self.create_tensor(in_layers=in_layers, set_tensors=False, training=training)

  @property
  def shape(self):
@@ -106,6 +110,8 @@ class Layer(object):
      if True, try to reshape the inputs to all have the same shape
    """
    if in_layers is None:
      if tfe.in_eager_mode():
        raise ValueError('in_layers must be specified in eager mode')
      in_layers = self.in_layers
    if not isinstance(in_layers, Sequence):
      in_layers = [in_layers]
@@ -241,6 +247,8 @@ class Layer(object):
      This means the newly created layers will share variables with the original
      ones.
    """
    if tfe.in_eager_mode():
      raise ValueError('copy() is not supported in eager mode')
    if self in replacements:
      return replacements[self]
    copied_inputs = [
@@ -328,7 +336,7 @@ class TensorWrapper(Layer):

  def create_tensor(self, in_layers=None, **kwargs):
    """Take no actions."""
    pass
    return self.out_tensor


def convert_to_layers(in_layers):
@@ -466,17 +474,12 @@ class Conv1D(Layer):
    self.kernel_constraint = kernel_constraint
    self.bias_constraint = bias_constraint
    super(Conv1D, self).__init__(in_layers, **kwargs)
    if tfe.in_eager_mode():
      self._layer = self._build_layer()
      self.variables = self._layer.variables

  def create_tensor(self, in_layers=None, set_tensors=True, **kwargs):
    inputs = self._get_input_tensors(in_layers)
    if len(inputs) != 1:
      raise ValueError("Conv1D layer must have exactly one parent")
    parent = inputs[0]
    if len(parent.get_shape()) == 2:
      parent = tf.expand_dims(parent, 2)
    elif len(parent.get_shape()) != 3:
      raise ValueError("Parent tensor must be (batch, width, channel)")
    out_tensor = tf.keras.layers.Conv1D(
  def _build_layer(self):
    return tf.keras.layers.Conv1D(
        filters=self.filters,
        kernel_size=self.kernel_size,
        strides=self.strides,
@@ -490,7 +493,22 @@ class Conv1D(Layer):
        bias_regularizer=self.bias_regularizer,
        activity_regularizer=self.activity_regularizer,
        kernel_constraint=self.kernel_constraint,
        bias_constraint=self.bias_constraint)(parent)
        bias_constraint=self.bias_constraint)

  def create_tensor(self, in_layers=None, set_tensors=True, **kwargs):
    inputs = self._get_input_tensors(in_layers)
    if len(inputs) != 1:
      raise ValueError("Conv1D layer must have exactly one parent")
    parent = inputs[0]
    if len(parent.get_shape()) == 2:
      parent = tf.expand_dims(parent, 2)
    elif len(parent.get_shape()) != 3:
      raise ValueError("Parent tensor must be (batch, width, channel)")
    if tfe.in_eager_mode():
      layer = self._layer
    else:
      layer = self._build_layer()
    out_tensor = layer(parent)
    if set_tensors:
      self._record_variable_scope(self.name)
      self.out_tensor = out_tensor
+74 −0
Original line number Diff line number Diff line
import numpy as np
import tensorflow as tf
import deepchem.models.tensorgraph.layers as layers
import tensorflow.contrib.eager as tfe
from tensorflow.python.eager import context
from tensorflow.python.framework import test_util

class TestLayersEager(test_util.TensorFlowTestCase):
  """
  Test that layers function in eager mode.
  """

  def test_conv_1d(self):
    """Test invoking Conv1D in eager mode."""
    with context.eager_mode():
      with tfe.IsolateTest():
        width = 5
        in_channels = 2
        filters = 3
        kernel_size = 2
        batch_size = 10
        input = np.random.rand(batch_size, width, in_channels).astype(np.float32)
        layer = layers.Conv1D(filters, kernel_size)
        result = layer(input)
        self.assertEqual(result.shape[0], batch_size)
        self.assertEqual(result.shape[2], filters)

        # Creating a second layer should produce different results, since it has
        # different random weights.

        layer2 = layers.Conv1D(filters, kernel_size)
        result2 = layer2(input)
        assert not np.allclose(result, result2)

        # But evaluating the first layer again should produce the same result as before.

        result3 = layer(input)
        assert np.allclose(result, result3)


  def test_add(self):
    """Test invoking Add in eager mode."""
    with context.eager_mode():
      with tfe.IsolateTest():
        result = layers.Add()([1,2], [3,4])
        assert np.array_equal(result, [4,6])

  def test_multiply(self):
    """Test invoking Multiply in eager mode."""
    with context.eager_mode():
      with tfe.IsolateTest():
        result = layers.Multiply()([1,2], [3,4])
        assert np.array_equal(result, [3,8])

  def test_divide(self):
    """Test invoking Divide in eager mode."""
    with context.eager_mode():
      with tfe.IsolateTest():
        result = layers.Divide()([1,2], [2,5])
        assert np.array_equal(result, [0.5,0.4])

  def test_log(self):
    """Test invoking Log in eager mode."""
    with context.eager_mode():
      with tfe.IsolateTest():
        result = layers.Log()(2.5)
        assert np.allclose(result, np.log(2.5))

  def test_exp(self):
    """Test invoking Exp in eager mode."""
    with context.eager_mode():
      with tfe.IsolateTest():
        result = layers.Exp()(2.5)
        assert np.allclose(result, np.exp(2.5))