I would like to know which operations I need to perform on a TF Lite model to achieve the class activation maps for a given image during classification. I have a separate classify.py file that loads my functions for TF Lite model inference.

import collections
import operator
import numpy as np

Class = collections.namedtuple('Class', ['id', 'score'])


def input_details(interpreter, key):
  return interpreter.get_input_details()[0][key]


def input_size(interpreter):
  _, height, width, _ = input_details(interpreter, 'shape')
  return width, height


def input_tensor(interpreter):
  tensor_index = input_details(interpreter, 'index')
  return interpreter.tensor(tensor_index)()[0]


def output_tensor(interpreter, dequantize=True):
  output_details = interpreter.get_output_details()[0]
  output_data = np.squeeze(interpreter.tensor(output_details['index'])())

  if dequantize and np.issubdtype(output_details['dtype'], np.integer):
    scale, zero_point = output_details['quantization']
    return scale * (output_data - zero_point)

  return output_data

def set_input(interpreter, data):
  input_tensor(interpreter)[:, :] = data

def get_output(interpreter, top_k=1, score_threshold=0.0):
  scores = output_tensor(interpreter)
  classes = [
      Class(i, scores[i])
      for i in np.argpartition(scores, -top_k)[-top_k:]
      if scores[i] >= score_threshold
  ]
  return sorted(classes, key=operator.itemgetter(1), reverse=True)


Then, my image_classify.py performs the model inference for the given image as input to the tensor.

import argparse
import time
from PIL import Image
import classify
import tflite_runtime.interpreter as tflite
import platform
EDGETPU_SHARED_LIB = {
‘Linux’: ‘libedgetpu.so.1’,
‘Darwin’: ‘libedgetpu.1.dylib’,
‘Windows’: ‘edgetpu.dll’
}[platform.system()]
def load_labels(path, encoding=‘utf-8’):
with open(path, ‘r’, encoding=encoding) as f:
lines = f.readlines()
if not lines:
return {}
if lines[0].split(' ', maxsplit=1)[0].isdigit():
  pairs = [line.split(' ', maxsplit=1) for line in lines]
  return {int(index): label.strip() for index, label in pairs}
else:
  return {index: line.strip() for index, line in enumerate(lines)}

def make_interpreter(model_file):
model_file, *device = model_file.split(’@’)
return tflite.Interpreter(
model_path=model_file,
experimental_delegates=[
tflite.load_delegate(EDGETPU_SHARED_LIB,
{‘device’: device[0]} if device else {})
])


def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument(
‘-m’, ‘–model’, required=True, help=‘File path of .tflite file.’)
parser.add_argument(
‘-i’, ‘–input’, required=True, help=‘Image to be classified.’)
parser.add_argument(
‘-l’, ‘–labels’, help=‘File path of labels file.’)
parser.add_argument(
‘-k’, ‘–top_k’, type=int, default=1,
help=‘Max number of classification results’)
parser.add_argument(
‘-t’, ‘–threshold’, type=float, default=0.0,
help=‘Classification score threshold’)
parser.add_argument(
‘-c’, ‘–count’, type=int, default=5,
help=‘Number of times to run inference’)
args = parser.parse_args()
labels = load_labels(args.labels) if args.labels else {}
interpreter = make_interpreter(args.model)
interpreter.allocate_tensors()
size = classify.input_size(interpreter)
image = Image.open(args.input).convert(‘RGB’).resize(size, Image.ANTIALIAS)
classify.set_input(interpreter, image)
for _ in range(args.count):
start = time.perf_counter()
interpreter.invoke()
inference_time = time.perf_counter() - start
classes = classify.get_output(interpreter, args.top_k, args.threshold)
print(’%.1fms’ % (inference_time * 1000))
for klass in classes:
print(’%s: %.5f’ % (labels.get(klass.id, klass.id), klass.score))

What I would like to do is to perform the same operations such as retrieving the layers, computing the gradients, performing the channel multiplications that are usually done for a standard tensorflow model, but instead, for a tensorflow lite model and show the grad-cam  heat map for the image input