为了使用tensorflow和pytorch的原始方法,进行量化把得到caffe模型需要进行转换。
量化
1. caffe to caffe2
对于caffe的模型,需要把caffe转成caffe2的模型
安装pytorch之后,已经安装了caffe2.使用内置的方法直接caffe转caffe2.
转化方法在这
转化方法在这2
python -m caffe2.python.caffe_translator TestModel.prototxt TestModel.caffemodel
得到caffe2 pb等文件。
predict_net.pb
predict_net.pb
predict_net.pbtxt
2. caffe2 to onnx
使用中间转化工具onnx
import onnx
import caffe2.python.onnx.frontend
from caffe2.proto import caffe2_pb2
# We need to provide type and shape of the model inputs,
# see above Note section for explanation
data_type = onnx.TensorProto.FLOAT
data_shape = (1, 3, 128, 128)
value_info = {
'data': (data_type, data_shape)
}
predict_net = caffe2_pb2.NetDef()
with open('predict_net.pb', 'rb') as f:
predict_net.ParseFromString(f.read())
init_net = caffe2_pb2.NetDef()
with open('init_net.pb', 'rb') as f:
init_net.ParseFromString(f.read())
onnx_model = caffe2.python.onnx.frontend.caffe2_net_to_onnx_model(
predict_net,
init_net,
value_info,
)
onnx.save_model(onnx_model, 'TestModel.onnx')
#onnx.checker.check_model(onnx_model)
3. onnx to caffe2
方法在这
import onnx
import caffe2.python.onnx.backend
from caffe2.python.onnx.backend import Caffe2Backend as c2
from onnx import helper
# Load the ONNX GraphProto object. Graph is a standard Python protobuf object
model = onnx.load("net.onnx")
init_net, predict_net = c2.onnx_graph_to_caffe2_net(model)
with open("net_init_net.pb", "wb") as f:
f.write(init_net.SerializeToString())
with open("net_init_net_predict_net.pb", "wb") as f:
f.write(predict_net.SerializeToString())
4. caffe to pytorch
使用中间转换工具MMdnn,https://github.com/Microsoft/MMdnn
- caffe to pb
得到 TestModel.pb
方法
mmtoir -f caffe -n TestModel.prototxt -w TestModel.caffemodel -o TestModel
- TestModel.pb to pytorch
方法
首先转换为 npy
mmtocode -f pytorch -n TestModel.pb --IRWeightPath TestModel.npy --dstModelPath TestModel.py -dw TestModel.npy
再转换为 pth
mmtomodel -f pytorch -in TestModel.py -iw TestModel.npy -o TestModel.pth
使用pth
import numpy as np
import os
import torch
import cv2
from torch.autograd import Variable
from PIL import Image
import imp
MainModel = imp.load_source('MainModel', "TestModel.py")
net = torch.load("pytorch_vgg19.pth")
my_project_root = "/home/yanghe/Desktop/model/"
imglist = os.listdir(my_project_root + 'model/JPEGImages/')
for img in imglist:
img = my_project_root + 'model/JPEGImages/' + img
img = Image.open(img)
width, height = img.size
#img = cv2.resize(img, (128, 128))
img = np.asarray(img)
image = img.transpose((2, 0, 1))
image = torch.from_numpy(image)
if isinstance(image, torch.ByteTensor):
image = image.float().div(255)
for t, m, s in zip(image, (0.499, 0.523, 0.532), (0.200, 0.202, 0.224)):
t.sub_(m).div_(s)
net.eval()
image = Variable(image.resize_(1, 3, 128, 128))
loc_pred = net(image)
print(loc_pred.size())
pytorch to onnx
dummy_input = torch.randn(1, 3, 128, 128)
net = torch.load("TestModel.pth")
torch.onnx.export(net, dummy_input, "TestModel.onnx")
使用pytorch进行推断
import numpy as np
import os
import torch
import cv2
from torch.autograd import Variable
from PIL import Image
import imp
import torch.onnx
import torchvision
from pytorch_vgg19 import KitModel
import parser
import distiller.quantization as quantization
import time
def read_file(file_paht):
imgsdata=[]
with open(file_paht) as f:
for img in f.readlines():
data = img.split()
data = [float(da) for da in data[1].split(',')]
imgsdata.append(data)
return imgsdata
def normal_ou(data1, data2):
data1 = np.array(data1)
data2 = np.array(data2)
result = np.sqrt(np.square(data1-data2).sum(1)).mean()
return result
def normal_cos(data1, data2):
data1 = np.array(data1)
data2 = np.array(data2)
results = []
for vector1, vector2 in zip(data1, data2):
result = np.dot(vector1, vector2) / (np.linalg.norm(vector1) * (np.linalg.norm(vector2)))
results.append(result)
return np.array(results).mean()
def sorce(time=0,cos=0):
print(time, cos)
if time < 56. and cos > 0.90: # 1= 135, 56
return ((1.19-time)/1.19*80)*cos
return 0
# Standard ImageNet input - 3 channels, 224x224,
# values don't matter as we care about network structure.
# But they can also be real inputs.
# dummy_input = torch.randn(1, 3, 128, 128)
# # Obtain your model, it can be also constructed in your script explicitly
# #model = torchvision.models.alexnet(pretrained=True)
# # Invoke export
#
#
MainModel = imp.load_source('MainModel', "TestModel.py")
args = parser.get_parser().parse_args()
net = torch.load("TestModel.pth", map_location='cpu')
# quantizer = quantization.PostTrainLinearQuantizer.from_args(model, args)
# #quantizer.prepare_model()
# # model.to(args.device)
# torch.save(model, os.path.join('./', str('asdf') + '_ckpt.pth'))
#net = torch.load("net.pth")
# net.cpu()
#net.cuda()
net.eval()
my_project_root = "/home/yanghe/Desktop/model/"
imglist = os.listdir(my_project_root + 'model/JPEGImages/')
a = []
for imgname in imglist:
imgname = my_project_root + 'model/JPEGImages/' + imgname
img = Image.open(imgname)
img = np.asarray(img)
image = img.transpose((2, 0, 1))
image = torch.from_numpy(image)
if isinstance(image, torch.ByteTensor):
image = image.float().div(255)
#image = (image * 255 - 127.5) * 0.0078125
net.eval()
image = Variable(image.resize_(1, 3, 128, 128))#.cuda()
loc_pred = net(image)
start = time.time()
a.append(imgname + ' ' + ','.join( str(j) for j in loc_pred.data.cpu().numpy()[0].tolist()))
end = time.time()
with open(my_project_root + 'model/result.txt', 'w') as f:
for i in a:
f.writelines(i + '\n')
data1 = read_file(my_project_root + 'model/labels.txt')
data2 = read_file(my_project_root + 'model/result.txt')
print('Cost time :',end - start)
print('ou : ', normal_ou(data1, data2))
cosin = normal_cos(data1, data2)
print('cos : ',cosin)
print('sorce : ', sorce(end - start, cosin))
使用tensorflow进行量化
- 安装bazel
https://docs.bazel.build/versions/master/install-ubuntu.html
- onnx to tensorflow
把onnx变为tensorflow的模型我一直有BNnormal报错,所以我只能先把BN层去掉,在转化为tensorflow的pb文件
方法
onnx-tf convert -t tf -i TestModel.onnx -o TestModel.pb
- 使用tensorflow进行量化
方法
bazel build tensorflow/tools/graph_transforms:transform_graph
bazel-bin/tensorflow/tools/graph_transforms/transform_graph --in_graph=TestModel.pb --out_graph=quantized_graph.pb --inputs=data --outputs=add_54 --transforms=' strip_unused_nodes(type=float, shape="1,3,128,128") strip_unused_nodes sort_by_execution_order remove_nodes(op=Identity, op=CheckNumerics) quantize_weights'
使用基于Caffe-Int8-Convert-Tools进行caffe模型转int8量化日常记录
https://blog.csdn.net/u014644466/article/details/83278954
- 把caffemodel 转变为table文件
python caffe-int8-convert-tool-dev-weight.py --proto=test/models/TestModel.prototxt --model=test/models/TestModel.caffemodel --mean 127.5 127.5 127.5 --norm=0.0078125 --images=test/images/ --output=TestModel.table --gpu=0
- 使用 caffe2nn 转换 TestModel.table 为TestModel.bin 和TestModel.param
./caffe2ncnn TestModel.prototxt TestModel.caffemodel TestModel.param TestModel.bin 256 TestModel.table
中兴算法大赛的初赛文档:
链接:https://pan.baidu.com/s/1gAfdJzJpKxs2enlpyg0A3w
提取码:gv90
参考:
https://blog.csdn.net/kangdi7547/article/details/81348254
https://blog.csdn.net/Dlyldxwl/article/details/79298969
https://blog.csdn.net/dlyldxwl/article/details/79502829
https://dgschwend.github.io/netscope/#/editor
https://blog.csdn.net/qq_33431368/article/details/85029041
https://blog.csdn.net/guvcolie/article/details/81286349
https://blog.csdn.net/u012101561/article/details/82587806
https://www.jiqizhixin.com/articles/2018-05-22-9
https://www.jiqizhixin.com/articles/2018-05-18-4
https://blog.csdn.net/daniaokuye/article/details/82746661
https://www.jiqizhixin.com/articles/2018-06-01-11
https://www.zhihu.com/question/40503595
https://www.jiqizhixin.com/articles/2017-10-29
https://www.hhyz.me/2018/06/26/2018-06-26-ModelCompression/
https://www.cnblogs.com/zhonghuasong/p/7493475.html
https://github.com/anlongstory/caffe_combine_relu/blob/master/doc/ZTE_challenge_2019.pdf
https://hey-yahei.cn/2019/05/22/zte_challenge_preliminary/
https://lutzroeder.github.io/netron/