"""
input_pattern = graph_matcher.OpTypePattern('*')
weight_var_pattern = graph_matcher.OpTypePattern('Variable|VariableV2')
- weight_identity_pattern = graph_matcher.OpTypePattern(
+ weight_partition_identity_pattern = graph_matcher.OpTypePattern(
'Identity', inputs=[weight_var_pattern])
+ weight_partition_concat_pattern = graph_matcher.OpTypePattern(
+ 'ConcatV2', inputs=[weight_partition_identity_pattern, '*', '*'])
+ weight_identity_pattern = graph_matcher.OpTypePattern(
+ 'Identity',
+ inputs=[
+ graph_matcher.OneofPattern([
+ weight_partition_identity_pattern,
+ weight_partition_concat_pattern,
+ weight_var_pattern,
+ ])
+ ])
weight_resource_var_pattern = graph_matcher.OpTypePattern('ReadVariableOp')
folded_weight_pattern = graph_matcher.OpTypePattern('Mul')
from tensorflow.python.ops import init_ops
from tensorflow.python.ops import math_ops
from tensorflow.python.ops import nn_ops
+from tensorflow.python.ops import partitioned_variables
+from tensorflow.python.ops import variable_scope
from tensorflow.python.platform import googletest
conv2d = layers.conv2d
# No ops should be inserted or removed.
self.assertEqual(op_names_before_quantize, op_names_after_quantize)
+ def testSinglePartitionedVariable(self):
+ self._RunTestOverParameters(self._testSinglePartitionedVariable)
+
+ def _testSinglePartitionedVariable(self, is_training):
+ # When weights are partitioned into a single partition, the weights variable
+ # is followed by a identity -> identity (An additional identity node).
+ partitioner = partitioned_variables.fixed_size_partitioner(1)
+ graph = ops.Graph()
+ with graph.as_default():
+ with variable_scope.variable_scope('part', partitioner=partitioner):
+ batch_size, height, width, depth = 5, 128, 128, 3
+ input1 = array_ops.zeros((batch_size, height, width, depth))
+ input2 = array_ops.zeros((batch_size, height / 2, width / 2, 32))
+ conv = conv2d(
+ input1,
+ 32, [5, 5],
+ stride=2,
+ padding='SAME',
+ weights_initializer=self._WeightInit(0.09),
+ activation_fn=None,
+ scope='test/test')
+ node = math_ops.add(conv, input2, name='test/add')
+ node = nn_ops.relu6(node, name='test/relu6')
+
+ quantize.Quantize(graph, is_training, weight_bits=8, activation_bits=8)
+ # Check that the weight's quant node was added.
+ op_names = [op.name for op in graph.get_operations()]
+ self.assertTrue(
+ 'part/test/test/weights_quant/FakeQuantWithMinMaxVars' in op_names)
+
+ def testMultiplePartitionedVariables(self):
+ self._RunTestOverParameters(self._testMultiplePartitionedVariables)
+
+ def _testMultiplePartitionedVariables(self, is_training):
+ # When weights are partitioned into multiple partitions the weights variable
+ # is followed by a identity -> concat -> identity to group the partitions.
+ partitioner = partitioned_variables.fixed_size_partitioner(2)
+ graph = ops.Graph()
+ with graph.as_default():
+ with variable_scope.variable_scope('part', partitioner=partitioner):
+ batch_size, height, width, depth = 5, 128, 128, 3
+ input1 = array_ops.zeros((batch_size, height, width, depth))
+ input2 = array_ops.zeros((batch_size, height / 2, width / 2, 32))
+ conv = conv2d(
+ input1,
+ 32, [5, 5],
+ stride=2,
+ padding='SAME',
+ weights_initializer=self._WeightInit(0.09),
+ activation_fn=None,
+ scope='test/test')
+ node = math_ops.add(conv, input2, name='test/add')
+ node = nn_ops.relu6(node, name='test/relu6')
+
+ quantize.Quantize(graph, is_training, weight_bits=8, activation_bits=8)
+ # Check that the weight's quant node was added.
+ op_names = [op.name for op in graph.get_operations()]
+ self.assertTrue(
+ 'part/test/test/weights_quant/FakeQuantWithMinMaxVars' in op_names)
+
def _WeightInit(self, stddev):
"""Returns truncated normal variable initializer.