Home | History | Annotate | Download | only in training
      1 # Copyright 2015 The TensorFlow Authors. All Rights Reserved.
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #     http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 # ==============================================================================
     15 """Functional test for optimizer."""
     16 
     17 from __future__ import absolute_import
     18 from __future__ import division
     19 from __future__ import print_function
     20 
     21 from tensorflow.python.framework import constant_op
     22 from tensorflow.python.framework import dtypes
     23 from tensorflow.python.framework import ops
     24 from tensorflow.python.framework import test_util
     25 from tensorflow.python.ops import array_ops
     26 from tensorflow.python.ops import clip_ops
     27 from tensorflow.python.ops import gradients_impl
     28 from tensorflow.python.ops import resource_variable_ops
     29 from tensorflow.python.ops import state_ops
     30 from tensorflow.python.ops import variables
     31 from tensorflow.python.platform import test
     32 from tensorflow.python.training import gradient_descent
     33 
     34 
     35 class OptimizerTest(test.TestCase):
     36 
     37   @test_util.run_in_graph_and_eager_modes()
     38   def testBasic(self):
     39     for i, dtype in enumerate([dtypes.half, dtypes.float32, dtypes.float64]):
     40       # Note that we name the variables uniquely here since the variables don't
     41       # seem to be getting deleted at the end of the loop.
     42       var0 = resource_variable_ops.ResourceVariable([1.0, 2.0], dtype=dtype,
     43                                                     name='a_%d' % i)
     44       var1 = resource_variable_ops.ResourceVariable([3.0, 4.0], dtype=dtype,
     45                                                     name='b_%d' % i)
     46       def loss():
     47         return 5 * var0 + 3 * var1  # pylint: disable=cell-var-from-loop
     48       # Note that for eager execution, minimize expects a function instead of a
     49       # Tensor.
     50       global_step = resource_variable_ops.ResourceVariable(
     51           array_ops.zeros([], dtypes.int64), name='global_step_%d' % i)
     52       sgd_op = gradient_descent.GradientDescentOptimizer(3.0)
     53 
     54       self.evaluate(variables.global_variables_initializer())
     55       # Fetch params to validate initial values
     56       self.assertAllClose([1.0, 2.0], self.evaluate(var0))
     57       self.assertAllClose([3.0, 4.0], self.evaluate(var1))
     58       # Run 1 step of sgd through optimizer
     59       opt_op = sgd_op.minimize(loss, global_step, [var0, var1])
     60       self.evaluate(opt_op)
     61       # Validate updated params
     62       self.assertAllClose([-14., -13.], self.evaluate(var0))
     63       self.assertAllClose([-6., -5.], self.evaluate(var1))
     64 
     65   def testAggregationMethod(self):
     66     for dtype in [dtypes.half, dtypes.float32, dtypes.float64]:
     67       with self.test_session():
     68         var0 = variables.Variable([1.0, 2.0], dtype=dtype)
     69         var1 = variables.Variable([3.0, 4.0], dtype=dtype)
     70         cost = 5 * var0 + 3 * var1
     71         global_step = variables.Variable(
     72             array_ops.zeros([], dtypes.int64), name='global_step')
     73         sgd_op = gradient_descent.GradientDescentOptimizer(3.0)
     74         opt_op = sgd_op.minimize(
     75             cost,
     76             global_step, [var0, var1],
     77             aggregation_method=gradients_impl.AggregationMethod.
     78             EXPERIMENTAL_ACCUMULATE_N)
     79 
     80         variables.global_variables_initializer().run()
     81         # Fetch params to validate initial values
     82         self.assertAllClose([1.0, 2.0], var0.eval())
     83         self.assertAllClose([3.0, 4.0], var1.eval())
     84         # Run 1 step of sgd through optimizer
     85         opt_op.run()
     86         # Validate updated params
     87         self.assertAllClose([-14., -13.], var0.eval())
     88         self.assertAllClose([-6., -5.], var1.eval())
     89 
     90   def testPrecomputedGradient(self):
     91     for dtype in [dtypes.half, dtypes.float32, dtypes.float64]:
     92       with self.test_session():
     93         var0 = variables.Variable([1.0, 2.0], dtype=dtype)
     94         var1 = variables.Variable([3.0, 4.0], dtype=dtype)
     95         cost = 5 * var0 + 3 * var1
     96         grad_loss = constant_op.constant([42, -42], dtype=dtype)
     97         global_step = variables.Variable(
     98             array_ops.zeros([], dtypes.int64), name='global_step')
     99         sgd_op = gradient_descent.GradientDescentOptimizer(3.0)
    100         opt_op = sgd_op.minimize(
    101             cost, global_step, [var0, var1], grad_loss=grad_loss)
    102 
    103         variables.global_variables_initializer().run()
    104         # Fetch params to validate initial values
    105         self.assertAllClose([1.0, 2.0], var0.eval())
    106         self.assertAllClose([3.0, 4.0], var1.eval())
    107         # Run 1 step of sgd through optimizer
    108         opt_op.run()
    109         # Validate updated params
    110         self.assertAllClose([1.0 - 3 * 5 * 42.0, 2.0 - 3 * 5 * (-42.0)],
    111                             var0.eval())
    112         self.assertAllClose([3.0 - 3 * 3 * 42.0, 4.0 - 3 * 3 * (-42.0)],
    113                             var1.eval())
    114 
    115   @test_util.run_in_graph_and_eager_modes()
    116   def testNoVariables(self):
    117     for dtype in [dtypes.half, dtypes.float32, dtypes.float64]:
    118       # pylint: disable=cell-var-from-loop
    119       def loss():
    120         var0 = resource_variable_ops.ResourceVariable(
    121             [1.0, 2.0], dtype=dtype, trainable=False, name='a')
    122         var1 = resource_variable_ops.ResourceVariable(
    123             [3.0, 4.0], dtype=dtype, trainable=False, name='b')
    124         return 5 * var0 + var1
    125       # pylint: enable=cell-var-from-loop
    126       sgd_op = gradient_descent.GradientDescentOptimizer(3.0)
    127       with self.assertRaisesRegexp(ValueError, 'No.*variables'):
    128         sgd_op.minimize(loss)
    129 
    130   @test_util.run_in_graph_and_eager_modes()
    131   def testNoGradients(self):
    132     for i, dtype in enumerate([dtypes.half, dtypes.float32, dtypes.float64]):
    133       # Note that we name the variables uniquely here since the variables don't
    134       # seem to be getting deleted at the end of the loop.
    135       var0 = resource_variable_ops.ResourceVariable([1.0, 2.0], dtype=dtype,
    136                                                     name='a%d' % i)
    137       var1 = resource_variable_ops.ResourceVariable([3.0, 4.0], dtype=dtype,
    138                                                     name='b%d' % i)
    139       # pylint: disable=cell-var-from-loop
    140       def loss():
    141         return 5 * var0
    142       # pylint: enable=cell-var-from-loop
    143       sgd_op = gradient_descent.GradientDescentOptimizer(3.0)
    144       with self.assertRaisesRegexp(ValueError, 'No gradients'):
    145         # var1 has no gradient
    146         sgd_op.minimize(loss, var_list=[var1])
    147 
    148   @test_util.run_in_graph_and_eager_modes()
    149   def testNoGradientsForAnyVariables_Minimize(self):
    150     for i, dtype in enumerate([dtypes.half, dtypes.float32, dtypes.float64]):
    151       # Note that we name the variables uniquely here since the variables don't
    152       # seem to be getting deleted at the end of the loop.
    153       var0 = resource_variable_ops.ResourceVariable([1.0, 2.0], dtype=dtype,
    154                                                     name='a_%d' % i)
    155       var1 = resource_variable_ops.ResourceVariable([3.0, 4.0], dtype=dtype,
    156                                                     name='b_%d' % i)
    157       def loss():
    158         return constant_op.constant(5.0)
    159       sgd_op = gradient_descent.GradientDescentOptimizer(3.0)
    160       with self.assertRaisesRegexp(ValueError,
    161                                    'No gradients provided for any variable'):
    162         sgd_op.minimize(loss, var_list=[var0, var1])
    163 
    164   @test_util.run_in_graph_and_eager_modes()
    165   def testNoGradientsForAnyVariables_ApplyGradients(self):
    166     for i, dtype in enumerate([dtypes.half, dtypes.float32, dtypes.float64]):
    167       # Note that we name the variables uniquely here since the variables don't
    168       # seem to be getting deleted at the end of the loop.
    169       var0 = resource_variable_ops.ResourceVariable([1.0, 2.0], dtype=dtype,
    170                                                     name='a_%d' % i)
    171       var1 = resource_variable_ops.ResourceVariable([3.0, 4.0], dtype=dtype,
    172                                                     name='b_%d' % i)
    173       sgd_op = gradient_descent.GradientDescentOptimizer(3.0)
    174       with self.assertRaisesRegexp(ValueError,
    175                                    'No gradients provided for any variable'):
    176         sgd_op.apply_gradients([(None, var0), (None, var1)])
    177 
    178   @test_util.run_in_graph_and_eager_modes()
    179   def testGradientsAsVariables(self):
    180     for i, dtype in enumerate([dtypes.half, dtypes.float32, dtypes.float64]):
    181       # Note that we name the variables uniquely here since the variables don't
    182       # seem to be getting deleted at the end of the loop.
    183       var0 = resource_variable_ops.ResourceVariable([1.0, 2.0], dtype=dtype,
    184                                                     name='a%d' % i)
    185       var1 = resource_variable_ops.ResourceVariable([3.0, 4.0], dtype=dtype,
    186                                                     name='b%d' % i)
    187       def loss():
    188         return 5 * var0 + 3 * var1  # pylint: disable=cell-var-from-loop
    189       sgd_op = gradient_descent.GradientDescentOptimizer(3.0)
    190       grads_and_vars = sgd_op.compute_gradients(loss, [var0, var1])
    191       # Convert gradients to tf.Variables
    192       converted_grads = [
    193           resource_variable_ops.ResourceVariable(array_ops.zeros([2], dtype),
    194                                                  name='c_%d_%d' % (i, j))
    195           for j, gv in enumerate(grads_and_vars)
    196       ]
    197       convert_ops = [
    198           state_ops.assign(converted_grads[j], gv[0])
    199           for j, gv in enumerate(grads_and_vars)
    200       ]
    201 
    202       self.evaluate(variables.global_variables_initializer())
    203       # Run convert_ops to achieve the gradietns converting
    204       self.evaluate(convert_ops)
    205       # Fetch params to validate initial values
    206       self.assertAllClose([1.0, 2.0], self.evaluate(var0))
    207       self.assertAllClose([3.0, 4.0], self.evaluate(var1))
    208 
    209       # Run 1 step of sgd through optimizer
    210       converted_grads_and_vars = list(zip(converted_grads, [var0, var1]))
    211       opt_op = sgd_op.apply_gradients(converted_grads_and_vars)
    212       self.evaluate(opt_op)
    213 
    214       # Validate updated params
    215       self.assertAllClose([-14., -13.], self.evaluate(var0))
    216       self.assertAllClose([-6., -5.], self.evaluate(var1))
    217 
    218   @test_util.run_in_graph_and_eager_modes()
    219   def testComputeGradientsWithTensors(self):
    220     x = ops.convert_to_tensor(1.0)
    221     def f():
    222       return x * x
    223     sgd_op = gradient_descent.GradientDescentOptimizer(3.0)
    224     grads_and_vars = sgd_op.compute_gradients(f, [x])
    225     self.assertEqual(1, len(grads_and_vars))
    226     grad, x_as_var = grads_and_vars[0]
    227     self.assertIs(x, x_as_var)
    228     self.assertEqual(2.0, self.evaluate(grad))
    229 
    230     with self.assertRaises(NotImplementedError):
    231       sgd_op.apply_gradients(grads_and_vars)
    232 
    233   def testTrainOp(self):
    234     with self.test_session():
    235       var0 = variables.Variable([1.0, 2.0])
    236       var1 = variables.Variable([3.0, 4.0])
    237       cost = 5 * var0 + 3 * var1
    238       global_step = variables.Variable(
    239           array_ops.zeros([], dtypes.int64), name='global_step')
    240       sgd_op = gradient_descent.GradientDescentOptimizer(3.0)
    241       opt_op = sgd_op.minimize(cost, global_step, [var0, var1])
    242       self.assertTrue(opt_op in ops.get_collection(ops.GraphKeys.TRAIN_OP))
    243 
    244   def testConstraint(self):
    245     constraint_01 = lambda x: clip_ops.clip_by_value(x, -0.1, 0.)
    246     constraint_0 = lambda x: clip_ops.clip_by_value(x, 0., 1.)
    247     with self.test_session():
    248       var0 = variables.Variable([1.0, 2.0],
    249                                 constraint=constraint_01)
    250       var1 = variables.Variable([3.0, 4.0],
    251                                 constraint=constraint_0)
    252       cost = 5 * var0 + 3 * var1
    253       global_step = variables.Variable(
    254           array_ops.zeros([], dtypes.int64), name='global_step')
    255       sgd_op = gradient_descent.GradientDescentOptimizer(3.0)
    256       opt_op = sgd_op.minimize(cost, global_step, [var0, var1])
    257 
    258       variables.global_variables_initializer().run()
    259       # Fetch params to validate initial values
    260       self.assertAllClose([1.0, 2.0], var0.eval())
    261       self.assertAllClose([3.0, 4.0], var1.eval())
    262       # Run 1 step of sgd through optimizer
    263       opt_op.run()
    264       # Validate updated params
    265       self.assertAllClose([-0.1, -0.1], var0.eval())
    266       self.assertAllClose([0., 0.], var1.eval())
    267 
    268 
    269 if __name__ == '__main__':
    270   test.main()
    271