model_test.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. # -*- coding: UTF-8 -*-
  2. import os
  3. import sys
  4. import MNN
  5. import numpy as np
  6. total_num = 0
  7. wrongs = []
  8. def parseConfig(root_dir):
  9. configName = os.path.join(root_dir, 'config.txt')
  10. if not os.path.exists(configName):
  11. return False
  12. try:
  13. config = open(configName, 'rt', encoding='utf-8')
  14. except:
  15. import io
  16. config = io.open(configName, 'rt', encoding='utf-8')
  17. res = {}
  18. res['model_name'] = os.path.join(root_dir, 'temp.bin')
  19. for line in config.readlines():
  20. if line[0] == '#':
  21. continue
  22. value = line[line.find(' = ') + 3:].strip()
  23. if 'input_size' in line:
  24. res['input_size'] = int(value)
  25. elif 'input_names' in line:
  26. input_names = value.split(',')
  27. res['input_names'] = input_names
  28. res['given_names'] = [ os.path.join(root_dir, x + '.txt') for x in input_names]
  29. elif 'input_dims' in line:
  30. res['input_dims'] = []
  31. for val in value.split(','):
  32. res['input_dims'].append([int(x) for x in val.split('x')])
  33. elif 'output_size' in line:
  34. res['output_size'] = int(value)
  35. elif 'output_names' in line:
  36. output_names = value.split(',')
  37. res['output_names'] = output_names
  38. res['expect_names'] = []
  39. for i in range(len(output_names)):
  40. expect_name = os.path.join(root_dir, output_names[i] + '.txt')
  41. if os.path.exists(expect_name):
  42. res['expect_names'].append(expect_name)
  43. else:
  44. res['expect_names'].append(os.path.join(root_dir, str(i) + '.txt'))
  45. return res
  46. def loadtxt(file, shape, dtype=np.float32):
  47. size = np.prod(shape)
  48. try:
  49. data = np.loadtxt(fname=file, dtype=dtype).flatten()
  50. except:
  51. data = []
  52. data_file = open(file, 'rt')
  53. for line in data_file.readlines():
  54. for x in line.strip().split(' '):
  55. try:
  56. a = float(x)
  57. data.append(a)
  58. except:
  59. pass
  60. data = np.asarray(data)
  61. if data.size >= size:
  62. data = data[:size].reshape(shape)
  63. else:
  64. data = np.pad(data, (0, size - data.size), 'constant').reshape(shape)
  65. return data
  66. def MNNDataType2NumpyDataType(data_type):
  67. if data_type == MNN.Halide_Type_Uint8:
  68. return np.uint8
  69. elif data_type == MNN.Halide_Type_Double:
  70. return np.float64
  71. elif data_type == MNN.Halide_Type_Int:
  72. return np.int32
  73. elif data_type == MNN.Halide_Type_Int64:
  74. return np.int64
  75. else:
  76. return np.float32
  77. def createTensor(tensor, file='', empty=False):
  78. shape = tensor.getShape()
  79. data_type = tensor.getDataType()
  80. dtype = MNNDataType2NumpyDataType(data_type)
  81. if file == '':
  82. if empty:
  83. data = np.zeros(shape, dtype=dtype)
  84. else:
  85. data = np.ones(shape, dtype=dtype)
  86. else:
  87. data = loadtxt(file, shape, dtype)
  88. return MNN.Tensor(shape, tensor.getDataType(), data.copy(), tensor.getDimensionType())
  89. def compareTensor(tensor, file, tolerance=5e-2):
  90. outputNumpyData = tensor.getNumpyData().copy()
  91. expectNumpyData = loadtxt(file, tensor.getShape())
  92. max_abs_dif = np.abs(outputNumpyData - expectNumpyData).max()
  93. max_exp_val = np.abs(expectNumpyData).max()
  94. diff_rate = max_abs_dif / max_exp_val
  95. if diff_rate > tolerance:
  96. print(f'# Error: max_abs_dif: {max_abs_dif}, max_exp_val: {max_exp_val}, diff_rate: {diff_rate}')
  97. return False
  98. return True
  99. def log_result(success, model):
  100. global total_num
  101. global wrongs
  102. total_num += 1
  103. if success:
  104. print('Test %s Correct!\n'%model)
  105. else:
  106. wrongs.append(model)
  107. print('Test Failed %s!\n'%model)
  108. def modelTest(modelPath, givenName, expectName):
  109. print("Testing model %s, input: %s, output: %s" % (modelPath, givenName, expectName))
  110. net = MNN.Interpreter(modelPath)
  111. session = net.createSession()
  112. allInput = net.getSessionInputAll(session)
  113. # zero for all inputs
  114. for name in allInput:
  115. inputTensor = allInput[name]
  116. inputHost = createTensor(inputTensor, givenName, True)
  117. inputTensor.copyFrom(inputHost)
  118. # input
  119. inputTensor = net.getSessionInput(session)
  120. inputHost = createTensor(inputTensor, givenName)
  121. inputTensor.copyFrom(inputHost)
  122. # infer
  123. net.runSession(session)
  124. outputTensor = net.getSessionOutput(session)
  125. # output
  126. outputShape = outputTensor.getShape()
  127. outputHost = createTensor(outputTensor)
  128. outputTensor.copyToHostTensor(outputHost)
  129. # compare
  130. success = compareTensor(outputHost, expectName)
  131. log_result(success, modelPath)
  132. def modelTestWithConfig(config):
  133. model = config['model_name']
  134. inputs = config['input_names']
  135. shapes = config['input_dims']
  136. givens = config['given_names']
  137. outputs = config['output_names']
  138. expects = config['expect_names']
  139. print("Testing model %s, input: %s, output: %s" % (model, givens, expects))
  140. net = MNN.Interpreter(config['model_name'])
  141. session = net.createSession()
  142. all_input = net.getSessionInputAll(session)
  143. # resize
  144. for i in range(len(inputs)):
  145. input = inputs[i]
  146. shape = shapes[i]
  147. net.resizeTensor(all_input[input], tuple(shape))
  148. net.resizeSession(session)
  149. # input
  150. all_input = net.getSessionInputAll(session)
  151. for i in range(len(inputs)):
  152. input = inputs[i]
  153. given = givens[i]
  154. input_tensor = all_input[input]
  155. input_host = createTensor(input_tensor, given)
  156. input_tensor.copyFrom(input_host)
  157. # infer
  158. net.runSession(session)
  159. all_output = net.getSessionOutputAll(session)
  160. # output & compare
  161. success = True
  162. for i in range(len(outputs)):
  163. output = outputs[i]
  164. expect = expects[i]
  165. output_tensor = all_output[output]
  166. output_host = createTensor(output_tensor)
  167. output_tensor.copyToHostTensor(output_host)
  168. success &= compareTensor(output_host, expect)
  169. # res
  170. log_result(success, model)
  171. def testSessionConfig(modelPath, givenName, expectName, session_config, outputTensorName):
  172. print("Testing model %s, input: %s, output: %s" % (modelPath, givenName, expectName))
  173. print("with session config:", session_config)
  174. net = MNN.Interpreter(modelPath)
  175. session = net.createSession(session_config)
  176. allInput = net.getSessionInputAll(session)
  177. # input
  178. inputTensor = net.getSessionInput(session)
  179. inputHost = createTensor(inputTensor, givenName)
  180. inputTensor.copyFrom(inputHost)
  181. # infer
  182. net.runSession(session)
  183. allOutput = net.getSessionOutputAll(session)
  184. print("output shapes:")
  185. for key in allOutput.keys():
  186. print(key, "shape:", allOutput[key].getShape())
  187. outputTensor = net.getSessionOutput(session, outputTensorName)
  188. outputHost = createTensor(outputTensor)
  189. outputTensor.copyToHostTensor(outputHost)
  190. # compare
  191. success = compareTensor(outputHost, expectName)
  192. log_result(success, modelPath)
  193. def testResource(model_root_dir, name):
  194. root_dir = os.path.join(model_root_dir, 'TestResource')
  195. print('root: ' + root_dir + '\n')
  196. for name in os.listdir(root_dir):
  197. if name == '.DS_Store':
  198. continue
  199. modelName = os.path.join(root_dir, name, 'temp.bin')
  200. inputName = os.path.join(root_dir, name, 'input_0.txt')
  201. outputName = os.path.join(root_dir, name, 'output.txt')
  202. modelTest(modelName, inputName, outputName)
  203. def testTestWithDescribe(model_root_dir):
  204. root_dir = os.path.join(model_root_dir, 'TestWithDescribe')
  205. print('root: ' + root_dir + '\n')
  206. for name in os.listdir(root_dir):
  207. if name == '.DS_Store':
  208. continue
  209. config = parseConfig(os.path.join(root_dir, name))
  210. if config:
  211. modelTestWithConfig(config)
  212. def testPymnnConfig(model_root_dir):
  213. root_dir = os.path.join(model_root_dir, "TestResource")
  214. print("\ntest pymnn session config")
  215. print('root: ' + root_dir + '\n')
  216. name = "ocr-single"
  217. modelName = os.path.join(root_dir, name, 'temp.bin')
  218. inputName = os.path.join(root_dir, name, 'input_0.txt')
  219. expectName = os.path.join(root_dir, name, 'output.txt')
  220. outputTensorName = "topk"
  221. session_config = {"saveTensors":("conv1", "pool1", outputTensorName)}
  222. testSessionConfig(modelName, inputName, expectName, session_config, outputTensorName)
  223. if __name__ == '__main__':
  224. model_root_dir = sys.argv[1]
  225. testResource(model_root_dir, 'TestResource')
  226. testResource(model_root_dir, 'OpTestResource')
  227. testTestWithDescribe(model_root_dir)
  228. testPymnnConfig(model_root_dir)
  229. if len(wrongs) > 0:
  230. print('Wrong: ', len(wrongs))
  231. for wrong in wrongs:
  232. print(wrong)
  233. print('TEST_NAME_PYMNN_MODEL: Pymnn模型测试\nTEST_CASE_AMOUNT_PYMNN_MODEL: {\"blocked\":0,\"failed\":%d,\"passed\":%d,\"skipped\":0}\n'%(len(wrongs), total_num - len(wrongs)))
  234. print('TEST_CASE={\"name\":\"Pymnn模型测试\",\"failed\":%d,\"passed\":%d}\n'%(len(wrongs), total_num - len(wrongs)))
  235. if len(wrongs) > 0:
  236. exit(1)