153 lines
5.7 KiB
Python
153 lines
5.7 KiB
Python
#!/usr/bin/python
|
|
import os
|
|
import sys
|
|
import numpy as np
|
|
import tensorflow as tf
|
|
import flatbuffers
|
|
|
|
def makeDirForPath(filename):
|
|
if filename.find('/') < 0:
|
|
return
|
|
names = filename.split('/')
|
|
dirname = ""
|
|
for l in range(0, len(names)-1):
|
|
dirname = dirname + names[l] + '/'
|
|
if os.path.exists(dirname):
|
|
return
|
|
os.makedirs(dirname)
|
|
|
|
def OutputsOffset(subgraph, j):
|
|
o = flatbuffers.number_types.UOffsetTFlags.py_type(subgraph._tab.Offset(8))
|
|
if o != 0:
|
|
a = subgraph._tab.Vector(o)
|
|
return a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4)
|
|
return 0
|
|
|
|
#ref: https://github.com/raymond-li/tflite_tensor_outputter/blob/master/tflite_tensor_outputter.py
|
|
def buffer_change_output_tensor_to(model_buffer, new_tensor_i):
|
|
from tensorflow.lite.python import schema_py_generated as schema_fb
|
|
root = schema_fb.Model.GetRootAsModel(model_buffer, 0)
|
|
output_tensor_index_offset = OutputsOffset(root.Subgraphs(0), 0)
|
|
# Flatbuffer scalars are stored in little-endian.
|
|
new_tensor_i_bytes = bytes([
|
|
new_tensor_i & 0x000000FF, \
|
|
(new_tensor_i & 0x0000FF00) >> 8, \
|
|
(new_tensor_i & 0x00FF0000) >> 16, \
|
|
(new_tensor_i & 0xFF000000) >> 24 \
|
|
])
|
|
# Replace the 4 bytes corresponding to the first output tensor index
|
|
return model_buffer[:output_tensor_index_offset] + new_tensor_i_bytes + model_buffer[output_tensor_index_offset + 4:]
|
|
|
|
class TestModel():
|
|
def __copy_to_here(self, modelName):
|
|
newModel = 'tflite/test.tflite'
|
|
print(os.popen("mkdir tflite").read())
|
|
print(os.popen("cp " + modelName + ' ' + newModel).read())
|
|
self.modelName = newModel
|
|
self.model = self.__load_graph(self.modelName)
|
|
self.inputOps, self.outputOps = self.__analyze_inputs_outputs(self.model)
|
|
self.outputs = [output['name'] for output in self.outputOps]
|
|
def __init__(self, modelName):
|
|
self.__copy_to_here(modelName)
|
|
def __run_mnn(self):
|
|
mnnconvert_name = 'MNNConvert.exe' if os.name == 'nt' else './MNNConvert'
|
|
if not os.path.exists(mnnconvert_name):
|
|
print("./MNNConvert not exist in this path. Use pymnn instead of C++ to test")
|
|
mnnconvert_name = 'mnnconvert'
|
|
convert = mnnconvert_name + ' -f TFLITE --bizCode MNN --modelFile tflite/test.tflite --MNNModel convert_cache.mnn --keepInputFormat=1 --testdir tflite'
|
|
result = os.popen(convert).read()
|
|
print(result)
|
|
return result
|
|
def __load_graph(self, filename):
|
|
interpreter = tf.lite.Interpreter(model_path=filename)
|
|
interpreter.allocate_tensors()
|
|
return interpreter
|
|
def __analyze_inputs_outputs(self, graph):
|
|
inputs = graph.get_input_details()
|
|
outputs = graph.get_output_details()
|
|
return (inputs, outputs)
|
|
def __get_shape(self, op):
|
|
shape = list(op['shape'])
|
|
for i in range(len(shape)):
|
|
if shape[i] == None or shape[i] < 0:
|
|
shape[i] = 1
|
|
else:
|
|
shape[i] = int(shape[i])
|
|
return shape
|
|
def __run_tflite(self):
|
|
jsonDict = {}
|
|
jsonDict['inputs'] = []
|
|
jsonDict['outputs'] = []
|
|
inputs = {}
|
|
print(self.modelName)
|
|
for inputVar in self.inputOps:
|
|
inp = {}
|
|
inp['name'] = inputVar['name']
|
|
inp['shape'] = self.__get_shape(inputVar)
|
|
inputs[inp['name']] = np.random.uniform(0.1, 1.2, inputVar['shape']).astype(inputVar['dtype'])
|
|
jsonDict['inputs'].append(inp)
|
|
print([output['name'] for output in self.outputOps])
|
|
for output in self.outputs:
|
|
jsonDict['outputs'].append(output)
|
|
|
|
import json
|
|
jsonString = json.dumps(jsonDict, indent=4)
|
|
with open('tflite/input.json', 'w') as f:
|
|
f.write(jsonString)
|
|
|
|
print('inputs:')
|
|
for key in inputs:
|
|
print(key)
|
|
name = "tflite/" + key + '.txt'
|
|
makeDirForPath(name)
|
|
f = open(name, 'w')
|
|
np.savetxt(f, inputs[key].flatten())
|
|
f.close()
|
|
for inp in self.inputOps:
|
|
self.model.set_tensor(inp['index'], inputs[inp['name']])
|
|
self.model.invoke()
|
|
outputs = []
|
|
for outp in self.outputOps:
|
|
outputs.append(self.model.get_tensor(outp['index']))
|
|
print('outputs:')
|
|
for i in range(len(self.outputs)):
|
|
outputName = self.outputs[i]
|
|
name = 'tflite/' + outputName + '.txt'
|
|
print(name)
|
|
makeDirForPath(name)
|
|
# print(name, outputs[i].shape)
|
|
f = open(name, 'w')
|
|
np.savetxt(f, outputs[i].flatten())
|
|
f.close()
|
|
def __test_specify_output(self, specify_output_name):
|
|
idx = -1
|
|
for tensor in self.model.get_tensor_details():
|
|
if tensor['name'] == specify_output_name:
|
|
idx = tensor['index']
|
|
if idx == -1:
|
|
print('No tensor name is %s.' % specify_output_name)
|
|
self.Test()
|
|
return
|
|
modelBuffer = open(self.modelName, 'rb').read()
|
|
modelBuffer = buffer_change_output_tensor_to(modelBuffer, idx)
|
|
interpreter = tf.lite.Interpreter(model_content=modelBuffer)
|
|
interpreter.allocate_tensors()
|
|
self.model = interpreter
|
|
self.inputOps, self.outputOps = self.__analyze_inputs_outputs(self.model)
|
|
self.outputs = [specify_output_name]
|
|
self.Test()
|
|
def TestName(self, name):
|
|
self.__test_specify_output(name)
|
|
def Test(self):
|
|
self.__run_tflite()
|
|
res = self.__run_mnn()
|
|
return res
|
|
|
|
if __name__ == '__main__':
|
|
modelName = sys.argv[1]
|
|
t = TestModel(modelName)
|
|
if len(sys.argv) > 2:
|
|
t.TestName(sys.argv[2])
|
|
else:
|
|
t.Test()
|