mirror of https://github.com/JDAI-CV/fast-reid.git
update pytorchtocaffe tool
Summary: update pytorch to caffe toolchain to support model layers and bash scriptspull/150/head
parent
3732f94405
commit
27c48c8f02
|
@ -1,4 +1,4 @@
|
|||
# The Caffe in PytorchToCaffe Provides some convenient API
|
||||
# The Caffe in nn_tools Provides some convenient API
|
||||
If there are some problem in parse your prototxt or caffemodel, Please replace
|
||||
the caffe.proto with your own version and compile it with command
|
||||
`protoc --python_out ./ caffe.proto`
|
||||
|
|
|
@ -565,7 +565,6 @@ message LayerParameter {
|
|||
optional RecurrentParameter recurrent_param = 146;
|
||||
optional ReductionParameter reduction_param = 136;
|
||||
optional ReLUParameter relu_param = 123;
|
||||
optional ReLU6Parameter relu6_param = 208;
|
||||
optional ReshapeParameter reshape_param = 133;
|
||||
optional ROIPoolingParameter roi_pooling_param = 8266711; //roi pooling
|
||||
optional ScaleParameter scale_param = 142;
|
||||
|
@ -601,7 +600,7 @@ message LayerParameter {
|
|||
optional CropParameter crop_param = 167;
|
||||
optional DetectionEvaluateParameter detection_evaluate_param = 168;
|
||||
optional DetectionOutputParameter detection_output_param = 169;
|
||||
optional NormalizeParameter norm_param = 170;
|
||||
//optional NormalizeParameter normalize_param = 170;
|
||||
optional MultiBoxLossParameter multibox_loss_param = 171;
|
||||
optional PermuteParameter permute_param = 172;
|
||||
optional VideoDataParameter video_data_param = 173;
|
||||
|
@ -633,7 +632,7 @@ message LayerParameter {
|
|||
optional UpsampleParameter upsample_param = 100003;
|
||||
optional MatMulParameter matmul_param = 100005;
|
||||
optional PassThroughParameter pass_through_param = 100004;
|
||||
//optional NormalizeParameter norm_param = 100001;
|
||||
optional NormalizeParameter norm_param = 100001;
|
||||
}
|
||||
|
||||
//*********************add by wdd******************
|
||||
|
@ -659,13 +658,13 @@ message PassThroughParameter {
|
|||
optional uint32 block_width = 3 [default = 0];
|
||||
}
|
||||
|
||||
//message NormalizeParameter{
|
||||
//optional bool across_spatial = 1 [default = true];
|
||||
//optional FillerParameter scale_filler = 2;
|
||||
//optional bool channel_shared = 3 [default = true];
|
||||
//optional float eps = 4 [default = 1e-10];
|
||||
//optional float sqrt_a = 5 [default = 1];
|
||||
//}
|
||||
message NormalizeParameter{
|
||||
optional bool across_spatial = 1 [default = true];
|
||||
optional FillerParameter scale_filler = 2;
|
||||
optional bool channel_shared = 3 [default = true];
|
||||
optional float eps = 4 [default = 1e-10];
|
||||
optional float sqrt_a = 5 [default = 1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1593,15 +1592,19 @@ message MultiBoxLossParameter {
|
|||
}
|
||||
|
||||
// Message that stores parameters used by NormalizeLayer
|
||||
message NormalizeParameter {
|
||||
optional bool across_spatial = 1 [default = true];
|
||||
// Initial value of scale. Default is 1.0 for all
|
||||
optional FillerParameter scale_filler = 2;
|
||||
// Whether or not scale parameters are shared across channels.
|
||||
optional bool channel_shared = 3 [default = true];
|
||||
// Epsilon for not dividing by zero while normalizing variance
|
||||
optional float eps = 4 [default = 1e-10];
|
||||
}
|
||||
//message NormalizeParameter {
|
||||
// //optional bool across_spatial = 1 [default = true];
|
||||
// // Initial value of scale. Default is 1.0 for all
|
||||
// //optional FillerParameter scale_filler = 2;
|
||||
// // Whether or not scale parameters are shared across channels.
|
||||
// //optional bool channel_shared = 3 [default = true];
|
||||
// // Epsilon for not dividing by zero while normalizing variance
|
||||
// //optional float eps = 4 [default = 1e-10];
|
||||
// //**************************************************
|
||||
// optional string normalize_type = 1 [default = "L2"];
|
||||
// optional bool fix_gradient = 2 [default = false];
|
||||
// optional bool bp_norm = 3 [default = false];
|
||||
//}
|
||||
|
||||
message PermuteParameter {
|
||||
// The new orders of the axes of data. Notice it should be with
|
||||
|
@ -1789,16 +1792,6 @@ message ReLUParameter {
|
|||
optional Engine engine = 2 [default = DEFAULT];
|
||||
}
|
||||
|
||||
// Message that stores parameters used by ReLU6Layer
|
||||
message ReLU6Parameter {
|
||||
enum Engine {
|
||||
DEFAULT = 0;
|
||||
CAFFE = 1;
|
||||
CUDNN = 2;
|
||||
}
|
||||
optional Engine engine = 2 [default = DEFAULT];
|
||||
}
|
||||
|
||||
message ReshapeParameter {
|
||||
// Specify the output dimensions. If some of the dimensions are set to 0,
|
||||
// the corresponding dimension from the bottom layer is used (unchanged).
|
||||
|
|
|
@ -7,7 +7,6 @@ from .layer_param import Layer_param
|
|||
class _Net(object):
|
||||
def __init__(self):
|
||||
self.net=pb.NetParameter()
|
||||
self.needChange = {}
|
||||
|
||||
def layer_index(self,layer_name):
|
||||
# find a layer's index by name. if the layer was found, return the layer position in the net, else return -1.
|
||||
|
@ -40,20 +39,6 @@ class _Net(object):
|
|||
return
|
||||
raise(AttributeError, "cannot found layer %s" % str(layer_name))
|
||||
|
||||
|
||||
|
||||
def remove_layer_by_type(self,type_name):
|
||||
for i,layer in enumerate(self.net.layer):
|
||||
if layer.type == type_name:
|
||||
# self.change_layer_bottom(layer.top,layer.bottom)
|
||||
s1 = "\"" + layer.top[0] + "\""
|
||||
s2 = "\"" + layer.bottom[0] + "\""
|
||||
self.needChange[s1]=s2
|
||||
del self.net.layer[i]
|
||||
return
|
||||
|
||||
|
||||
|
||||
def get_layer_by_name(self, layer_name):
|
||||
# get the layer by layer_name
|
||||
for layer in self.net.layer:
|
||||
|
@ -67,10 +52,7 @@ class _Net(object):
|
|||
for layer in prototxt.layer:
|
||||
del layer.blobs[:]
|
||||
with open(path,'w') as f:
|
||||
string = text_format.MessageToString(prototxt)
|
||||
for origin_name in self.needChange.keys():
|
||||
string = string.replace(origin_name,self.needChange[origin_name])
|
||||
f.write(string)
|
||||
f.write(text_format.MessageToString(prototxt))
|
||||
|
||||
def layer(self,layer_name):
|
||||
return self.get_layer_by_name(layer_name)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -71,46 +71,9 @@ class Layer_param():
|
|||
conv_param.dilation.extend(pair_reduce(dilation))
|
||||
if groups:
|
||||
conv_param.group=groups
|
||||
if groups != 1:
|
||||
conv_param.engine = 1
|
||||
self.param.convolution_param.CopyFrom(conv_param)
|
||||
|
||||
def norm_param(self, eps):
|
||||
"""
|
||||
add a conv_param layer if you spec the layer type "Convolution"
|
||||
Args:
|
||||
num_output: a int
|
||||
kernel_size: int list
|
||||
stride: a int list
|
||||
weight_filler_type: the weight filer type
|
||||
bias_filler_type: the bias filler type
|
||||
Returns:
|
||||
"""
|
||||
l2norm_param = pb.NormalizeParameter()
|
||||
l2norm_param.across_spatial = False
|
||||
l2norm_param.channel_shared = False
|
||||
l2norm_param.eps = eps
|
||||
self.param.norm_param.CopyFrom(l2norm_param)
|
||||
|
||||
|
||||
def permute_param(self, order1, order2, order3, order4):
|
||||
"""
|
||||
add a conv_param layer if you spec the layer type "Convolution"
|
||||
Args:
|
||||
num_output: a int
|
||||
kernel_size: int list
|
||||
stride: a int list
|
||||
weight_filler_type: the weight filer type
|
||||
bias_filler_type: the bias filler type
|
||||
Returns:
|
||||
"""
|
||||
permute_param = pb.PermuteParameter()
|
||||
permute_param.order.extend([order1, order2, order3, order4])
|
||||
|
||||
self.param.permute_param.CopyFrom(permute_param)
|
||||
|
||||
|
||||
def pool_param(self,type='MAX',kernel_size=2,stride=2,pad=None, ceil_mode = True):
|
||||
def pool_param(self,type='MAX',kernel_size=2,stride=2,pad=None, ceil_mode = False):
|
||||
pool_param=pb.PoolingParameter()
|
||||
pool_param.pool=pool_param.PoolMethod.Value(type)
|
||||
pool_param.kernel_size=pair_process(kernel_size)
|
||||
|
@ -158,10 +121,22 @@ class Layer_param():
|
|||
if isinstance(size,int):
|
||||
upsample_param.upsample_h = size
|
||||
else:
|
||||
upsample_param.upsample_h = size[0] * scale_factor
|
||||
upsample_param.\
|
||||
upsample_w = size[1] * scale_factor
|
||||
upsample_param.upsample_h = size[0]
|
||||
upsample_param.upsample_w = size[1]
|
||||
#upsample_param.upsample_h = size[0] * scale_factor
|
||||
#upsample_param.upsample_w = size[1] * scale_factor
|
||||
self.param.upsample_param.CopyFrom(upsample_param)
|
||||
def interp_param(self,size=None, scale_factor=None):
|
||||
interp_param=pb.InterpParameter()
|
||||
if scale_factor:
|
||||
if isinstance(scale_factor,int):
|
||||
interp_param.zoom_factor = scale_factor
|
||||
|
||||
if size:
|
||||
print('size:', size)
|
||||
interp_param.height = size[0]
|
||||
interp_param.width = size[1]
|
||||
self.param.interp_param.CopyFrom(interp_param)
|
||||
|
||||
def add_data(self,*args):
|
||||
"""Args are data numpy array
|
||||
|
|
|
@ -1 +1 @@
|
|||
raise ImportError('the nn_tools.Caffe.net is no longer used, please use nn_tools.Caffe.caffe_net')
|
||||
raise ImportError,'the nn_tools.Caffe.net is no longer used, please use nn_tools.Caffe.caffe_net'
|
|
@ -1,3 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import traceback
|
||||
|
@ -7,6 +10,8 @@ from torch.autograd import Variable
|
|||
from Caffe import layer_param
|
||||
from torch.nn.modules.utils import _pair
|
||||
import numpy as np
|
||||
import math
|
||||
from torch.nn.modules.utils import _list_with_default
|
||||
|
||||
"""
|
||||
How to support a new layer type:
|
||||
|
@ -18,24 +23,28 @@ How to support a new layer type:
|
|||
log.cnet.add_layer(layer)
|
||||
|
||||
Please MUTE the inplace operations to avoid not find in graph
|
||||
|
||||
注意:只有torch.nn.functional中的函数才能转换为caffe中的层
|
||||
"""
|
||||
|
||||
|
||||
# TODO: support the inplace output of the layers
|
||||
|
||||
class Blob_LOG():
|
||||
def __init__(self):
|
||||
self.data = {}
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.data[key] = value
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.data[key]
|
||||
|
||||
def __len__(self):
|
||||
return len(self.data)
|
||||
|
||||
|
||||
NET_INITTED = False
|
||||
|
||||
|
||||
# 转换原理解析:通过记录
|
||||
class TransLog(object):
|
||||
def __init__(self):
|
||||
|
@ -55,6 +64,7 @@ class TransLog(object):
|
|||
:param inputs: is a list of input variables
|
||||
"""
|
||||
self.add_blobs(inputs)
|
||||
|
||||
def add_layer(self, name='layer'):
|
||||
if name in self.layers:
|
||||
return self.layers[name]
|
||||
|
@ -81,24 +91,27 @@ class TransLog(object):
|
|||
rst.append('{}'.format(name))
|
||||
if self.debug:
|
||||
print("{}:{} was added to blobs".format(blob_id, rst[-1]))
|
||||
# print('Add blob {} : {}'.format(rst[-1].center(21),blob.size()))
|
||||
print('Add blob {} : {}'.format(rst[-1].center(21), blob.size()))
|
||||
self._blobs[blob_id] = rst[-1]
|
||||
return rst
|
||||
|
||||
def blobs(self, var):
|
||||
var = id(var)
|
||||
# if self.debug:
|
||||
# print("{}:{} getting".format(var, self._blobs[var]))
|
||||
if self.debug:
|
||||
print("{}:{} getting".format(var, self._blobs[var]))
|
||||
try:
|
||||
return self._blobs[var]
|
||||
except:
|
||||
print("WARNING: CANNOT FOUND blob {}".format(var))
|
||||
return None
|
||||
|
||||
|
||||
log = TransLog()
|
||||
|
||||
layer_names = {}
|
||||
|
||||
|
||||
def _conv2d(raw, input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1):
|
||||
print('conv: ',log.blobs(input))
|
||||
x = raw(input, weight, bias, stride, padding, dilation, groups)
|
||||
name = log.add_layer(name='conv')
|
||||
log.add_blobs([x], name='conv_blob')
|
||||
|
@ -108,12 +121,15 @@ def _conv2d(raw,input, weight, bias=None, stride=1, padding=0, dilation=1, group
|
|||
pad=_pair(padding), dilation=_pair(dilation), bias_term=bias is not None, groups=groups)
|
||||
if bias is not None:
|
||||
layer.add_data(weight.cpu().data.numpy(), bias.cpu().data.numpy())
|
||||
#print('conv2d weight, bias: ',weight.cpu().data.numpy(), bias.cpu().data.numpy())
|
||||
|
||||
else:
|
||||
layer.param.convolution_param.bias_term = False
|
||||
layer.add_data(weight.cpu().data.numpy())
|
||||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _conv_transpose2d(raw, input, weight, bias=None, stride=1, padding=0, output_padding=0, groups=1, dilation=1):
|
||||
x = raw(input, weight, bias, stride, padding, output_padding, groups, dilation)
|
||||
name = log.add_layer(name='conv_transpose')
|
||||
|
@ -121,7 +137,7 @@ def _conv_transpose2d(raw,input, weight, bias=None, stride=1, padding=0, output_
|
|||
layer = caffe_net.Layer_param(name=name, type='Deconvolution',
|
||||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
layer.conv_param(x.size()[1], weight.size()[2:], stride=_pair(stride),
|
||||
pad=_pair(padding),dilation=_pair(dilation),bias_term=bias is not None, groups = groups)
|
||||
pad=_pair(padding), dilation=_pair(dilation), bias_term=bias is not None)
|
||||
if bias is not None:
|
||||
layer.add_data(weight.cpu().data.numpy(), bias.cpu().data.numpy())
|
||||
else:
|
||||
|
@ -130,6 +146,7 @@ def _conv_transpose2d(raw,input, weight, bias=None, stride=1, padding=0, output_
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _linear(raw, input, weight, bias=None):
|
||||
x = raw(input, weight, bias)
|
||||
layer_name = log.add_layer(name='fc')
|
||||
|
@ -144,6 +161,7 @@ def _linear(raw,input, weight, bias=None):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _split(raw, tensor, split_size, dim=0):
|
||||
# split in pytorch is slice in caffe
|
||||
x = raw(tensor, split_size, dim)
|
||||
|
@ -162,23 +180,25 @@ def _pool(type,raw,input,x,kernel_size,stride,padding,ceil_mode):
|
|||
# TODO dilation,ceil_mode,return indices
|
||||
layer_name = log.add_layer(name='{}_pool'.format(type))
|
||||
top_blobs = log.add_blobs([x], name='{}_pool_blob'.format(type))
|
||||
layer = caffe_net.Layer_param(name=layer_name, type='Pooling',
|
||||
bottom=[log.blobs(input)], top=top_blobs)
|
||||
layer = caffe_net.Layer_param(name=layer_name, type='Pooling', bottom=[log.blobs(input)], top=top_blobs)
|
||||
|
||||
# TODO w,h different kernel, stride and padding
|
||||
# processing ceil mode
|
||||
layer.pool_param(kernel_size=kernel_size, stride=kernel_size if stride is None else stride,
|
||||
pad=padding, type=type.upper() , ceil_mode = ceil_mode)
|
||||
pad=padding, type=type.upper())
|
||||
log.cnet.add_layer(layer)
|
||||
if ceil_mode == False and stride is not None:
|
||||
oheight = (input.size()[2] - _pair(kernel_size)[0] + 2 * _pair(padding)[0]) % (_pair(stride)[0])
|
||||
owidth = (input.size()[3] - _pair(kernel_size)[1] + 2 * _pair(padding)[1]) % (_pair(stride)[1])
|
||||
if oheight != 0 or owidth != 0:
|
||||
caffe_out=raw(input, kernel_size, stride, padding, ceil_mode=True)
|
||||
caffe_out = raw(input, kernel_size, stride, padding, ceil_mode=False)
|
||||
print("WARNING: the output shape miss match at {}: "
|
||||
|
||||
"input {} output---Pytorch:{}---Caffe:{}\n"
|
||||
"This is caused by the different implementation that ceil mode in caffe and the floor mode in pytorch.\n"
|
||||
"You can add the clip layer in caffe prototxt manually if shape mismatch error is caused in caffe. ".format(layer_name,input.size(),x.size(),caffe_out.size()))
|
||||
"You can add the clip layer in caffe prototxt manually if shape mismatch error is caused in caffe. ".format(
|
||||
layer_name, input.size(), x.size(), caffe_out.size()))
|
||||
|
||||
|
||||
def _max_pool2d(raw, input, kernel_size, stride=None, padding=0, dilation=1,
|
||||
ceil_mode=False, return_indices=False):
|
||||
|
@ -186,23 +206,12 @@ def _max_pool2d(raw,input, kernel_size, stride=None, padding=0, dilation=1,
|
|||
_pool('max', raw, input, x, kernel_size, stride, padding, ceil_mode)
|
||||
return x
|
||||
|
||||
|
||||
def _avg_pool2d(raw, input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True):
|
||||
x = raw(input, kernel_size, stride, padding, ceil_mode, count_include_pad)
|
||||
_pool('ave', raw, input, x, kernel_size, stride, padding, ceil_mode)
|
||||
return x
|
||||
|
||||
def _adaptive_avg_pool2d(raw, input, output_size):
|
||||
_output_size = _list_with_default(output_size, input.size())
|
||||
x = raw(input, _output_size)
|
||||
if isinstance(_output_size, int):
|
||||
out_dim = _output_size
|
||||
else:
|
||||
out_dim = _output_size[0]
|
||||
tmp = max(input.shape[2], input.shape[3])
|
||||
stride = tmp //out_dim
|
||||
kernel_size = tmp - (out_dim - 1) * stride
|
||||
_pool('ave', raw, input, x, kernel_size, stride, 0, False)
|
||||
return x
|
||||
|
||||
def _max(raw, *args):
|
||||
x = raw(*args)
|
||||
|
@ -221,6 +230,7 @@ def _max(raw,*args):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _cat(raw, inputs, dimension=0):
|
||||
x = raw(inputs, dimension)
|
||||
bottom_blobs = []
|
||||
|
@ -234,6 +244,7 @@ def _cat(raw,inputs, dimension=0):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _dropout(raw, input, p=0.5, training=False, inplace=False):
|
||||
x = raw(input, p, training, inplace)
|
||||
bottom_blobs = [log.blobs(input)]
|
||||
|
@ -246,6 +257,7 @@ def _dropout(raw,input,p=0.5, training=False, inplace=False):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _threshold(raw, input, threshold, value, inplace=False):
|
||||
# for threshold or relu
|
||||
if threshold == 0 and value == 0:
|
||||
|
@ -269,6 +281,7 @@ def _threshold(raw,input, threshold, value, inplace=False):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _relu(raw, input, inplace=False):
|
||||
# for threshold or prelu
|
||||
x = raw(input, False)
|
||||
|
@ -278,6 +291,8 @@ def _relu(raw, input, inplace=False):
|
|||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _prelu(raw, input, weight):
|
||||
# for threshold or prelu
|
||||
x = raw(input, weight)
|
||||
|
@ -294,6 +309,7 @@ def _prelu(raw, input, weight):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _leaky_relu(raw, input, negative_slope=0.01, inplace=False):
|
||||
x = raw(input, negative_slope)
|
||||
name = log.add_layer(name='leaky_relu')
|
||||
|
@ -304,6 +320,7 @@ def _leaky_relu(raw, input, negative_slope=0.01, inplace=False):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _tanh(raw, input):
|
||||
# for tanh activation
|
||||
x = raw(input)
|
||||
|
@ -314,6 +331,7 @@ def _tanh(raw, input):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _softmax(raw, input, dim=None, _stacklevel=3):
|
||||
# for F.softmax
|
||||
x = raw(input, dim=dim)
|
||||
|
@ -328,6 +346,18 @@ def _softmax(raw, input, dim=None, _stacklevel=3):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _sigmoid(raw, input):
|
||||
# for tanh activation
|
||||
x = raw(input)
|
||||
name = log.add_layer(name='Sigmoid')
|
||||
log.add_blobs([x], name='Sigmoid_blob')
|
||||
layer = caffe_net.Layer_param(name=name, type='Sigmoid',
|
||||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _batch_norm(raw, input, running_mean, running_var, weight=None, bias=None,
|
||||
training=False, momentum=0.1, eps=1e-5):
|
||||
# because the runing_mean and runing_var will be changed after the _batch_norm operation, we first save the parameters
|
||||
|
@ -347,6 +377,8 @@ def _batch_norm(raw,input, running_mean, running_var, weight=None, bias=None,
|
|||
running_mean_clone = running_mean.clone()
|
||||
running_var_clone = running_var.clone()
|
||||
layer1.add_data(running_mean_clone.cpu().numpy(), running_var_clone.cpu().numpy(), np.array([1.0]))
|
||||
#print('running_mean: ',running_mean_clone.cpu().numpy())
|
||||
#print('running_var: ',running_var_clone.cpu().numpy())
|
||||
log.cnet.add_layer(layer1)
|
||||
if weight is not None and bias is not None:
|
||||
layer_name2 = log.add_layer(name='bn_scale')
|
||||
|
@ -355,8 +387,11 @@ def _batch_norm(raw,input, running_mean, running_var, weight=None, bias=None,
|
|||
layer2.param.scale_param.bias_term = True
|
||||
layer2.add_data(weight.cpu().data.numpy(), bias.cpu().data.numpy())
|
||||
log.cnet.add_layer(layer2)
|
||||
#print('scale weight: ', weight.cpu().data.numpy())
|
||||
#print('scale bias: ', bias.cpu().data.numpy())
|
||||
return x
|
||||
|
||||
|
||||
def _instance_norm(raw, input, running_mean=None, running_var=None, weight=None,
|
||||
bias=None, use_input_stats=True, momentum=0.1, eps=1e-5):
|
||||
# TODO: the batch size!=1 view operations
|
||||
|
@ -400,88 +435,61 @@ def _interpolate(raw, input,size=None, scale_factor=None, mode='nearest', align_
|
|||
# 有用,对输出进行额外 padding 在 h、w 方向上的数值;upsample_h、upsample_w,输
|
||||
# 出图像尺寸的数值。在 Upsample 的相关代码中,推荐仅仅使用 upsample_h、
|
||||
# upsample_w 准确定义 Upsample 层的输出尺寸,其他所有的参数都不推荐继续使用。
|
||||
'''
|
||||
if mode == 'bilinear':
|
||||
x = raw(input, size, scale_factor, mode)
|
||||
name = log.add_layer(name='conv_transpose')
|
||||
log.add_blobs([x], name='conv_transpose_blob')
|
||||
layer = caffe_net.Layer_param(name=name, type='Deconvolution',
|
||||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
print('Deconv: ', name)
|
||||
print(input.shape)
|
||||
print(x.size())
|
||||
print(size)
|
||||
factor = float(size[0]) / input.shape[2]
|
||||
C = x.size()[1]
|
||||
print(factor,C)
|
||||
kernel_size = int(2 * factor - factor % 2)
|
||||
stride = int(factor)
|
||||
num_output = C
|
||||
group = C
|
||||
pad = math.ceil((factor-1) / 2.)
|
||||
print('kernel_size, stride, num_output, group, pad')
|
||||
print(kernel_size, stride, num_output, group, pad)
|
||||
layer.conv_param(num_output, kernel_size, stride=stride,
|
||||
pad=pad, weight_filler_type='bilinear', bias_term=False, groups=group)
|
||||
|
||||
layer.param.convolution_param.bias_term = False
|
||||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
'''
|
||||
# transfer bilinear align_corners=True to caffe-interp
|
||||
if mode == "bilinear" and align_corners == True:
|
||||
x = raw(input, size, scale_factor, mode)
|
||||
name = log.add_layer(name='interp')
|
||||
log.add_blobs([x], name='interp_blob')
|
||||
layer = caffe_net.Layer_param(name=name, type='Interp',
|
||||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
layer.interp_param(size=size, scale_factor=scale_factor)
|
||||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
# for nearest _interpolate
|
||||
if mode != "nearest" or align_corners != None:
|
||||
raise NotImplementedError("not implement F.interpolate totoaly")
|
||||
x = raw(input, size, scale_factor, mode)
|
||||
|
||||
layer_name = log.add_layer(name='upsample')
|
||||
top_blobs = log.add_blobs([x], name='upsample_blob'.format(type))
|
||||
layer = caffe_net.Layer_param(name=layer_name, type='Upsample',
|
||||
bottom=[log.blobs(input)], top=top_blobs)
|
||||
#layer.upsample_param(size=(input.size(2), input.size(3)), scale_factor=scale_factor)
|
||||
#layer.upsample_param(size=size, scale_factor=scale_factor)
|
||||
layer.upsample_param(size=None, scale_factor=size[0])
|
||||
|
||||
layer.upsample_param(size =(input.size(2),input.size(3)), scale_factor= scale_factor)
|
||||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
#sigmid layer
|
||||
def _sigmoid(raw, input):
|
||||
# Applies the element-wise function:
|
||||
#
|
||||
# Sigmoid(x)= 1/(1+exp(−x))
|
||||
#
|
||||
#
|
||||
x = raw(input)
|
||||
name = log.add_layer(name='sigmoid')
|
||||
log.add_blobs([x], name='sigmoid_blob')
|
||||
layer = caffe_net.Layer_param(name=name, type='Sigmoid',
|
||||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
log.cnet.add_layer(layer)
|
||||
|
||||
#tanh layer
|
||||
def _tanh(raw, input):
|
||||
# Applies the element-wise function:
|
||||
#
|
||||
# torch.nn.Tanh
|
||||
#
|
||||
#
|
||||
x = raw(input)
|
||||
name = log.add_layer(name='tanh')
|
||||
log.add_blobs([x], name='tanh_blob')
|
||||
layer = caffe_net.Layer_param(name=name, type='TanH',
|
||||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
log.cnet.add_layer(layer)
|
||||
|
||||
def _hardtanh(raw, input, min_val, max_val, inplace):
|
||||
# Applies the element-wise function:
|
||||
#
|
||||
# torch.nn.ReLu6
|
||||
#
|
||||
#
|
||||
print('relu6: ', log.blobs(input))
|
||||
x = raw(input, min_val, max_val)
|
||||
name = log.add_layer(name='relu6')
|
||||
log.add_blobs([x], name='relu6_blob')
|
||||
layer = caffe_net.Layer_param(name=name, type='ReLU6',
|
||||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
#L2Norm layer
|
||||
def _l2Norm(raw, input, weight, eps):
|
||||
# Applies the element-wise function:
|
||||
#
|
||||
# L2Norm in vgg_ssd
|
||||
#
|
||||
#
|
||||
x = raw(input, weight, eps)
|
||||
name = log.add_layer(name='normalize')
|
||||
log.add_blobs([x], name='normalize_blob')
|
||||
layer = caffe_net.Layer_param(name=name, type='Normalize',
|
||||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
layer.norm_param(eps)
|
||||
|
||||
layer.add_data(weight.cpu().data.numpy())
|
||||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
def _div(raw,inputs, inputs2):
|
||||
x=raw(inputs, inputs2)
|
||||
log.add_blobs([x],name='div_blob')
|
||||
return x
|
||||
|
||||
|
||||
# ----- for Variable operations --------
|
||||
|
||||
def _view(input, *args):
|
||||
|
@ -490,8 +498,13 @@ def _view(input, *args):
|
|||
return x
|
||||
layer_name = log.add_layer(name='view')
|
||||
top_blobs = log.add_blobs([x], name='view_blob')
|
||||
layer=caffe_net.Layer_param(name=layer_name,type='Reshape',
|
||||
bottom=[log.blobs(input)],top=top_blobs)
|
||||
|
||||
# print('*'*60)
|
||||
# print('input={}'.format(input))
|
||||
# print('layer_name={}'.format(layer_name))
|
||||
# print('top_blobs={}'.format(top_blobs))
|
||||
|
||||
layer = caffe_net.Layer_param(name=layer_name, type='Reshape', bottom=[log.blobs(input)], top=top_blobs)
|
||||
# TODO: reshpae added to nn_tools layer
|
||||
dims = list(args)
|
||||
dims[0] = 0 # the first dim should be batch_size
|
||||
|
@ -499,6 +512,7 @@ def _view(input, *args):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _mean(input, *args, **kwargs):
|
||||
x = raw_mean(input, *args, **kwargs)
|
||||
if not NET_INITTED:
|
||||
|
@ -518,21 +532,37 @@ def _mean(input, *args,**kwargs):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _add(input, *args):
|
||||
# check if add a const value
|
||||
if isinstance(args[0], int):
|
||||
print('value: ',args[0])
|
||||
x = raw__add__(input, *args)
|
||||
#x = raw(input)
|
||||
layer_name = log.add_layer(name='scale')
|
||||
log.add_blobs([x], name='Scale_blob')
|
||||
layer = caffe_net.Layer_param(name=layer_name, type='Scale',
|
||||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
dim = x.shape[1]
|
||||
layer.param.scale_param.bias_term = True
|
||||
weight = np.ones(dim, dtype=np.float32)
|
||||
bias = args[0] * np.ones(dim, dtype=np.float32)
|
||||
layer.add_data(weight, bias)
|
||||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
# otherwise add a tensor
|
||||
x = raw__add__(input, *args)
|
||||
if not NET_INITTED:
|
||||
return x
|
||||
layer_name = log.add_layer(name='add')
|
||||
top_blobs = log.add_blobs([x], name='add_blob')
|
||||
if log.blobs(args[0]) == None:
|
||||
log.add_blobs([args[0]], name='extra_blob')
|
||||
else:
|
||||
layer = caffe_net.Layer_param(name=layer_name, type='Eltwise',
|
||||
bottom=[log.blobs(input), log.blobs(args[0])], top=top_blobs)
|
||||
layer.param.eltwise_param.operation = 1 # sum is 1
|
||||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _iadd(input, *args):
|
||||
x = raw__iadd__(input, *args)
|
||||
if not NET_INITTED:
|
||||
|
@ -546,6 +576,7 @@ def _iadd(input, *args):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _sub(input, *args):
|
||||
x = raw__sub__(input, *args)
|
||||
if not NET_INITTED:
|
||||
|
@ -559,6 +590,7 @@ def _sub(input, *args):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _isub(input, *args):
|
||||
x = raw__isub__(input, *args)
|
||||
if not NET_INITTED:
|
||||
|
@ -572,8 +604,9 @@ def _isub(input, *args):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _mul(input, *args):
|
||||
x = raw__mul__(input, *args)
|
||||
x = raw__sub__(input, *args)
|
||||
if not NET_INITTED:
|
||||
return x
|
||||
layer_name = log.add_layer(name='mul')
|
||||
|
@ -584,8 +617,9 @@ def _mul(input, *args):
|
|||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
|
||||
def _imul(input, *args):
|
||||
x = raw__imul__(input, *args)
|
||||
x = raw__isub__(input, *args)
|
||||
if not NET_INITTED:
|
||||
return x
|
||||
x = x.clone()
|
||||
|
@ -599,64 +633,12 @@ def _imul(input, *args):
|
|||
return x
|
||||
|
||||
|
||||
#Permute layer
|
||||
def _permute(input, *args):
|
||||
x = raw__permute__(input, *args)
|
||||
name = log.add_layer(name='permute')
|
||||
log.add_blobs([x], name='permute_blob')
|
||||
layer = caffe_net.Layer_param(name=name, type='Permute',
|
||||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
order1 = args[0]
|
||||
order2 = args[1]
|
||||
order3 = args[2]
|
||||
order4 = args[3]
|
||||
|
||||
layer.permute_param(order1, order2, order3, order4)
|
||||
log.cnet.add_layer(layer)
|
||||
def _adaptive_avg_pool2d(raw, input, output_size):
|
||||
_output_size = _list_with_default(output_size, input.size())
|
||||
x = raw(input, _output_size)
|
||||
_pool('ave', raw, input, x, input.shape[2], input.shape[2], 0, False)
|
||||
return x
|
||||
|
||||
#contiguous
|
||||
def _contiguous(input, *args):
|
||||
x = raw__contiguous__(input, *args)
|
||||
name = log.add_layer(name='contiguous')
|
||||
log.add_blobs([x], name='contiguous_blob')
|
||||
layer = caffe_net.Layer_param(name=name, type='NeedRemove',
|
||||
bottom=[log.blobs(input)], top=[log.blobs(x)])
|
||||
log.cnet.add_layer(layer)
|
||||
return x
|
||||
|
||||
#pow
|
||||
def _pow(input, *args):
|
||||
x = raw__pow__(input, *args)
|
||||
log.add_blobs([x], name='pow_blob')
|
||||
return x
|
||||
|
||||
#sum
|
||||
def _sum(input, *args):
|
||||
x = raw__sum__(input, *args)
|
||||
log.add_blobs([x], name='sum_blob')
|
||||
return x
|
||||
|
||||
# sqrt
|
||||
def _sqrt(input, *args):
|
||||
x = raw__sqrt__(input, *args)
|
||||
log.add_blobs([x], name='sqrt_blob')
|
||||
return x
|
||||
|
||||
# unsqueeze
|
||||
def _unsqueeze(input, *args):
|
||||
x = raw__unsqueeze__(input, *args)
|
||||
log.add_blobs([x], name='unsqueeze_blob')
|
||||
return x
|
||||
|
||||
# sqrt
|
||||
def _expand_as(input, *args):
|
||||
x = raw__expand_as__(input, *args)
|
||||
log.add_blobs([x], name='expand_as_blob')
|
||||
return x
|
||||
|
||||
|
||||
|
||||
|
||||
# 核心组件,通过该类,实现对torch的function中的operators的输入,输出以及参数的读取
|
||||
class Rp(object):
|
||||
|
@ -681,11 +663,10 @@ class Rp(object):
|
|||
return out
|
||||
|
||||
|
||||
|
||||
|
||||
F.conv2d = Rp(F.conv2d, _conv2d)
|
||||
F.linear = Rp(F.linear, _linear)
|
||||
F.relu = Rp(F.relu, _relu)
|
||||
|
||||
F.leaky_relu = Rp(F.leaky_relu, _leaky_relu)
|
||||
F.max_pool2d = Rp(F.max_pool2d, _max_pool2d)
|
||||
F.avg_pool2d = Rp(F.avg_pool2d, _avg_pool2d)
|
||||
|
@ -697,16 +678,12 @@ F.instance_norm=Rp(F.instance_norm,_instance_norm)
|
|||
F.softmax = Rp(F.softmax, _softmax)
|
||||
F.conv_transpose2d = Rp(F.conv_transpose2d, _conv_transpose2d)
|
||||
F.interpolate = Rp(F.interpolate, _interpolate)
|
||||
F.sigmoid = Rp(F.sigmoid,_sigmoid)
|
||||
F.tanh = Rp(F.tanh,_tanh)
|
||||
F.tanh = Rp(F.tanh,_tanh)
|
||||
F.hardtanh = Rp(F.hardtanh,_hardtanh)
|
||||
# F.l2norm = Rp(F.l2norm,_l2Norm)
|
||||
F.adaptive_avg_pool2d = Rp(F.adaptive_avg_pool2d, _adaptive_avg_pool2d)
|
||||
|
||||
torch.split = Rp(torch.split, _split)
|
||||
torch.max = Rp(torch.max, _max)
|
||||
torch.cat = Rp(torch.cat, _cat)
|
||||
torch.div=Rp(torch.div,_div)
|
||||
torch.sigmoid = Rp(torch.sigmoid, _sigmoid)
|
||||
|
||||
# TODO: other types of the view function
|
||||
try:
|
||||
|
@ -745,20 +722,6 @@ except:
|
|||
t.__mul__ = _mul
|
||||
raw__imul__ = t.__imul__
|
||||
t.__imul__ = _imul
|
||||
raw__permute__ = t.permute
|
||||
t.permute = _permute
|
||||
raw__contiguous__ = t.contiguous
|
||||
t.contiguous = _contiguous
|
||||
raw__pow__ = t.pow
|
||||
t.pow = _pow
|
||||
raw__sum__ = t.sum
|
||||
t.sum = _sum
|
||||
raw__sqrt__ = t.sqrt
|
||||
t.sqrt = _sqrt
|
||||
raw__unsqueeze__ = t.unsqueeze
|
||||
t.unsqueeze = _unsqueeze
|
||||
raw__expand_as__ = t.expand_as
|
||||
t.expand_as = _expand_as
|
||||
|
||||
|
||||
def trans_net(net, input_var, name='TransferedPytorchModel'):
|
||||
|
@ -775,9 +738,10 @@ def trans_net(net,input_var,name='TransferedPytorchModel'):
|
|||
out = net.forward(input_var)
|
||||
print('Transform Completed')
|
||||
|
||||
|
||||
def save_prototxt(save_name):
|
||||
log.cnet.remove_layer_by_type("NeedRemove")
|
||||
log.cnet.save_prototxt(save_name)
|
||||
|
||||
|
||||
def save_caffemodel(save_name):
|
||||
log.cnet.save(save_name)
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
|
||||
python caffe_inference.py --model-def "logs/caffe_R34/baseline_R34.prototxt" \
|
||||
--model-weights "logs/caffe_R34/baseline_R34.caffemodel" \
|
||||
--height 256 --width 128 \
|
||||
--input \
|
||||
'/export/home/DATA/Market-1501-v15.09.15/bounding_box_test/1182_c5s3_015240_04.jpg' \
|
||||
'/export/home/DATA/Market-1501-v15.09.15/bounding_box_test/1182_c6s3_038217_01.jpg' \
|
||||
'/export/home/DATA/Market-1501-v15.09.15/bounding_box_test/1183_c5s3_006943_05.jpg' \
|
||||
'/export/home/DATA/DukeMTMC-reID/bounding_box_train/0728_c4_f0161265.jpg' \
|
||||
--output "caffe_R34_output"
|
Loading…
Reference in New Issue