blob: 2032f52c4d1bdcb87cbe0abf8c5599b12f88782a [file] [log] [blame]
# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Tests for model_coverage_lib.py."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import tempfile
import numpy as np
from tensorflow import keras
from tensorflow.lite.python import lite
from tensorflow.lite.testing.model_coverage import model_coverage_lib as model_coverage
from tensorflow.python.client import session
from tensorflow.python.eager import def_function
from tensorflow.python.framework import constant_op
from tensorflow.python.framework import dtypes
from tensorflow.python.framework import ops
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import math_ops
from tensorflow.python.platform import test
from tensorflow.python.saved_model import saved_model
from tensorflow.python.training.training_util import write_graph
class EvaluateFrozenGraph(test.TestCase):
def _saveFrozenGraph(self, sess):
graph_def_file = os.path.join(self.get_temp_dir(), 'model.pb')
write_graph(sess.graph_def, '', graph_def_file, False)
return graph_def_file
def testFloat(self):
with ops.Graph().as_default():
with session.Session().as_default() as sess:
in_tensor = array_ops.placeholder(
shape=[1, 16, 16, 3], dtype=dtypes.float32)
_ = in_tensor + in_tensor
filename = self._saveFrozenGraph(sess)
model_coverage.test_frozen_graph(filename, ['Placeholder'], ['add'])
def testInputWithRange(self):
with ops.Graph().as_default():
with session.Session().as_default() as sess:
in_tensor = array_ops.placeholder(
shape=[1, 16, 16, 3], dtype=dtypes.float32)
_ = in_tensor + in_tensor
filename = self._saveFrozenGraph(sess)
model_coverage.test_frozen_graph(
filename, ['Placeholder'], ['add'],
input_data_range={'Placeholder': (0, 10)})
def testMultipleOutputs(self):
with ops.Graph().as_default():
with session.Session().as_default() as sess:
in_tensor_1 = array_ops.placeholder(
shape=[1, 16], dtype=dtypes.float32, name='inputA')
in_tensor_2 = array_ops.placeholder(
shape=[1, 16], dtype=dtypes.float32, name='inputB')
weight = constant_op.constant(-1.0, shape=[16, 16])
bias = constant_op.constant(-1.0, shape=[16])
layer = math_ops.matmul(in_tensor_1, weight) + bias
_ = math_ops.reduce_mean(math_ops.square(layer - in_tensor_2))
filename = self._saveFrozenGraph(sess)
model_coverage.test_frozen_graph(filename, ['inputA', 'inputB'],
['add', 'Mean'])
def testFunctions(self):
"""Tests functions."""
@def_function.function
def plus_placeholder(x, placeholder):
return x + placeholder
with ops.Graph().as_default():
placeholder = array_ops.placeholder(
dtype=dtypes.float32, shape=[1], name='input')
variable_node = constant_op.constant(1.0, name='variable_node')
defun_node = plus_placeholder(variable_node, placeholder)
_ = math_ops.multiply(defun_node, 2.0, name='output_node')
# Initialize variables in the model.
sess = session.Session()
filename = self._saveFrozenGraph(sess)
model_coverage.test_frozen_graph(filename, ['input'], ['output_node'])
def _getQuantizedModel(self):
np.random.seed(0)
with ops.Graph().as_default():
with session.Session().as_default() as sess:
# The tensor needs to have more than 1024 elements for quantize_weights
# to kick in. Thus, the [33, 33] shape.
in_tensor_1 = array_ops.placeholder(
shape=[33, 33], dtype=dtypes.float32, name='inputA')
in_tensor_2 = constant_op.constant(
np.random.uniform(low=-10., high=10., size=(33, 33)),
shape=[33, 33],
dtype=dtypes.float32,
name='inputB')
_ = math_ops.matmul(in_tensor_1, in_tensor_2, name='output')
filename = self._saveFrozenGraph(sess)
return filename
def testQuantized(self):
filename = self._getQuantizedModel()
model_coverage.test_frozen_graph_quant(filename, ['inputA'], ['output'])
def testQuantizedInputShapes(self):
filename = self._getQuantizedModel()
model_coverage.test_frozen_graph_quant(
filename, ['inputA'], ['output'], input_shapes={'inputA': [33, 33]})
def testQuantizedFlexAll(self):
filename = self._getQuantizedModel()
model_coverage.test_frozen_graph_quant(
filename, ['inputA'], ['output'],
target_ops=set([lite.OpsSet.SELECT_TF_OPS]))
class EvaluateSavedModel(test.TestCase):
def testFloat(self):
saved_model_dir = os.path.join(self.get_temp_dir(), 'simple_savedmodel')
with ops.Graph().as_default():
with session.Session().as_default() as sess:
in_tensor_1 = array_ops.placeholder(
shape=[1, 16, 16, 3], dtype=dtypes.float32, name='inputB')
in_tensor_2 = array_ops.placeholder(
shape=[1, 16, 16, 3], dtype=dtypes.float32, name='inputA')
out_tensor = in_tensor_1 + in_tensor_2
inputs = {'x': in_tensor_1, 'y': in_tensor_2}
outputs = {'z': out_tensor}
saved_model.simple_save(sess, saved_model_dir, inputs, outputs)
model_coverage.test_saved_model(saved_model_dir)
def testPostTrainingQuantize16x8(self):
"""Test for post-training quantization mode: activations/weights - int16/int8."""
saved_model_dir = os.path.join(self.get_temp_dir(), 'simple_savedmodel')
input_size = [5, 5, 3]
kernel_size = [3, 3, 1]
layer_name = 'test_conv2d'
input_0 = keras.layers.Input(shape=input_size)
layer_0 = keras.layers.Conv2D(
filters=kernel_size[-1],
kernel_size=kernel_size[0:2],
use_bias=False,
name=layer_name)(
input_0)
model = keras.models.Model(inputs=[input_0], outputs=[layer_0])
keras_layer = [layer for layer in model.layers if layer.name == layer_name
][0]
keras_layer.set_weights([
np.random.rand(
input_size[-1],
kernel_size[0],
kernel_size[1],
kernel_size[2],
).astype(np.float32)
])
saved_model.save(model, saved_model_dir)
model_coverage.test_saved_model(
saved_model_dir,
post_training_quantize_16x8=True,
model_input_size=input_size)
class EvaluateKerasModel(test.TestCase):
def _getSingleInputKerasModel(self):
"""Returns single input Sequential tf.keras model."""
keras.backend.clear_session()
xs = np.array([-1, 0, 1, 2, 3, 4])
ys = np.array([-3, -1, 1, 3, 5, 7])
model = keras.Sequential([keras.layers.Dense(units=1, input_shape=[1])])
model.compile(optimizer='sgd', loss='mean_squared_error')
model.train_on_batch(xs, ys)
return model
def _saveKerasModel(self, model):
try:
fd, keras_file = tempfile.mkstemp('.h5')
model.save(keras_file)
finally:
os.close(fd)
return keras_file
def testFloat(self):
model = self._getSingleInputKerasModel()
keras_file = self._saveKerasModel(model)
model_coverage.test_keras_model(keras_file)
def testPostTrainingQuantize(self):
model = self._getSingleInputKerasModel()
keras_file = self._saveKerasModel(model)
model_coverage.test_keras_model(keras_file, post_training_quantize=True)
def testTargetOps(self):
model = self._getSingleInputKerasModel()
keras_file = self._saveKerasModel(model)
model_coverage.test_keras_model(
keras_file,
target_ops=set([lite.OpsSet.TFLITE_BUILTINS,
lite.OpsSet.SELECT_TF_OPS]))
if __name__ == '__main__':
test.main()