def TranslateConv(layer, pretrained_blobs): caffe_op = BaseTranslate(layer, "Conv") output = caffe_op.outputs[0] caffe_op.inputs.extend([output + '_w', output + '_b']) param = layer.convolution_param AddArgument(caffe_op, "stride", param.stride) AddArgument(caffe_op, "kernel", param.kernel_size) AddArgument(caffe_op, "pad", param.pad) AddArgument(caffe_op, "order", "NCHW") if param.group > 1: # Now, if the model is grouped convolution, let's do a backward hack and make # things working but in an efficient way by inserting zero parameters. n, c, h, w = pretrained_blobs[0].shape g = param.group og = int(n / g) if (og * g != n): raise ValueError("This should not happen") weight = np.zeros((n, c * g, h, w), dtype=np.float32) for i in range(param.group): weight[i * og : (i + 1) * og, i * c : (i+1) * c, :, :] = pretrained_blobs[0][i * og : (i + 1) * og] else: weight = pretrained_blobs[0] weight = utils.NumpyArrayToCaffe2Tensor(weight, output + '_w') bias = utils.NumpyArrayToCaffe2Tensor( pretrained_blobs[1].flatten(), output + '_b') # Todo: deal with parameters. return caffe_op, [weight, bias]
def TranslateInnerProduct(layer, pretrained_blobs): caffe_op = BaseTranslate(layer, "FC") output = caffe_op.output[0] caffe_op.input.extend([output + '_w', output + '_b']) weight = utils.NumpyArrayToCaffe2Tensor(pretrained_blobs[0][0, 0], output + '_w') bias = utils.NumpyArrayToCaffe2Tensor(pretrained_blobs[1].flatten(), output + '_b') return caffe_op, [weight, bias]
def TranslateConvWithGroups(layer, pretrained_blobs): print("Legacy warning: convolution with groups seem to be less and less " + "popular, so we no longer have it as a first-class citizen op. " + "Instead, we will simulate it with depth split followed by conv " + "followed by depth concat.") caffe_ops = [] caffe_params = [] param = layer.convolution_param weight, bias = pretrained_blobs bias = bias.flatten() n, c, h, w = weight.shape g = param.group # group od = int(n / g) # output dimension if (od * g != n): # This should not happen: n should always be divisible by g. raise ValueError("This should not happen.") output = layer.top[0] # first, depth_split depth_split_op = core.CreateOperator("DepthSplit")( layer.bottom[0], ['_' + output + '_gconv_split_' + str(i) for i in range(g)], dimensions=[c for i in range(g)], order="NCHW") caffe_ops.append(depth_split_op) # second, convolutions for i in range(g): # convolution layer i this_weight = utils.NumpyArrayToCaffe2Tensor( weight[i * od:(i + 1) * od], output + '_gconv_' + str(i) + '_w') this_bias = utils.NumpyArrayToCaffe2Tensor( bias[i * od:(i + 1) * od], output + '_gconv_' + str(i) + '_b') conv_op = core.CreateOperator("Conv")( [depth_split_op.output[i], this_weight.name, this_bias.name], ['_' + output + '_gconv_conv_' + str(i)], stride=param.stride, kernel=param.kernel_size, pad=param.pad, order="NCHW") caffe_ops.append(conv_op) caffe_params.extend([this_weight, this_bias]) # third, depth concat depth_concat_op = core.CreateOperator("DepthConcat")( ['_' + output + '_gconv_conv_' + str(i) for i in range(g)], [output, '_' + output + '_gconv_concat_dims'], order="NCHW") caffe_ops.append(depth_concat_op) return caffe_ops, caffe_params
def TranslateConv(layer, pretrained_blobs): param = layer.convolution_param if param.group > 1: return TranslateConvWithGroups(layer, pretrained_blobs) # If there is no odd things, we will basically translate it to a standard # caffe2 op. caffe_op = BaseTranslate(layer, "Conv") output = caffe_op.output[0] caffe_op.input.extend([output + '_w', output + '_b']) AddArgument(caffe_op, "stride", param.stride) AddArgument(caffe_op, "kernel", param.kernel_size) AddArgument(caffe_op, "pad", param.pad) AddArgument(caffe_op, "order", "NCHW") weight = utils.NumpyArrayToCaffe2Tensor(pretrained_blobs[0], output + '_w') bias = utils.NumpyArrayToCaffe2Tensor(pretrained_blobs[1].flatten(), output + '_b') return caffe_op, [weight, bias]