概述
之前写过一文探讨tflite模型在pc环境下的调用:
《tensorflow 21:用python转换tflite模型并在PC上调用》
我就想,能不能只量化,格式还是普通的pb格式,然后在pc环境调用。这样既享受了量化压缩带来的好处,又不受制于tflite支持的算子不全面。
结论
没啥用!
在pc环境用graph_transforms工具将inception-v2模型量化,然后PC环境下调用:
- windows-cpu环境下不支持调用量化模型,因为windows下缺少反量化的算子,会报错:No OpKernel was registered to support Op ‘Dequantize’
- Linux-cpu环境下调用量化模型,相比量化前没有速度上的收益,几乎一样。唯一的好处是模型大小变小了,但是准确率我没测,应该也有损失
- Linux-gpu环境下调用量化模型,相比量化前时间还长了一倍。
这真是一个悲伤的故事!!!
原因分析
tensorflow目前还没针对标准的模型进行量化方面的加速。tflite在手机上应该对量化模型有相应的优化。
Linux-PC环境调用量化模型,可以借助NVIDIA TensorRT或者Intel OpenVINO等框架。
调用模型的代码
我的环境:ubunutu+python3.5+tensorflow1.7
import tensorflow as tf
#import cv2
from PIL import Image
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "1"
import sys
import numpy as np
import time
import tensorflow as tf
test_image_dir = './test_images/'
graph_location = './'
pb_path = os.path.join(graph_location, 'qua_inception_v2.pb')
print('pb_path:{}'.format(pb_path))
newInput_X = tf.placeholder(tf.float32, [None, 299, 299, 3], name="X")
#drouout_ratio = tf.constant(1., name="drouout")
with open(pb_path, 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
#output = tf.import_graph_def(graph_def)
output = tf.import_graph_def(graph_def,
input_map={'Placeholder:0': newInput_X},
return_elements=['InceptionResnetV2/Logits/Predictions:0'])
with tf.Session( ) as sess:
file_list = os.listdir(test_image_dir)
# 遍历文件
for file in file_list:
full_path = os.path.join(test_image_dir, file)
print('full_path:{}'.format(full_path))
# 大小控制在(299, 299, 3)
#img = cv2.imread(full_path )
#res_img = cv2.resize(img,(299,299),interpolation=cv2.INTER_CUBIC)
image_pil = Image.open(full_path)
image_pil = image_pil.resize((299,299))
image_np = np.asarray(image_pil)
image_np.astype('float32')
res_img = image_np
# 增加一个维度,变为 [1, 299, 299, 3]
image_np_expanded = np.expand_dims(res_img, axis=0)
image_np_expanded.astype('float32') # 类型也要满足要求
print('image_np_expanded shape:{}'.format(image_np_expanded.shape))
# 注意注意,我要调用模型了
start_time = time.time()
for i in range(100):
print(i)
result = sess.run(output, feed_dict={newInput_X: image_np_expanded})
used = time.time()-start_time
print('avg-time:{}'.format(used/100))
# 出来的结果去掉没用的维度
result = np.squeeze(result)
print('result:{}'.format(result))
#print('result:{}'.format(sess.run(output, feed_dict={newInput_X: image_np_expanded})))
# 输出结果是一维数据,最大值的下标就是预测的分类
print('result:{}'.format( (np.where(result==np.max(result)))[0][0] ))