caffe 模型压缩

为了使用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

  1. caffe to pb

得到 TestModel.pb

方法

mmtoir -f caffe -n TestModel.prototxt -w TestModel.caffemodel -o TestModel
  1. 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进行量化

  1. 安装bazel
    https://docs.bazel.build/versions/master/install-ubuntu.html
  1. onnx to tensorflow
    把onnx变为tensorflow的模型我一直有BNnormal报错,所以我只能先把BN层去掉,在转化为tensorflow的pb文件

方法

onnx-tf convert -t tf -i TestModel.onnx -o TestModel.pb
  1. 使用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

  1. 把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
  1. 使用 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/

你可能感兴趣的:(caffe 模型压缩)