xxradon / PytorchToCaffe

Pytorch model to caffe model, supported pytorch 0.3, 0.3.1, 0.4, 0.4.1 ,1.0 , 1.0.1 , 1.2 ,1.3 .notice that only pytorch 1.1 have some bugs
MIT License
783 stars 224 forks source link

a=featuremap*1.5,像这样的简单的乘法或者加法该怎么办? #48

Closed dreamhighchina closed 4 years ago

dreamhighchina commented 4 years ago

因为这个1.5并不是什么blob,所以在 layer = caffe_net.Layer_param(name=layer_name, type='Eltwise', bottom=[log.blobs(input), log.blobs(args[0])], top=top_blobs)的时候,会出现 log.blobs(args[0])keyerror的原因,这个该怎么解决???

xxradon commented 4 years ago

那就是用torch.mul()之类的函数替换*

Guanmoyu commented 4 years ago

你可以在重载的_mul函数里加个判断分支,如果为常数,重载为Scale层

Guanmoyu commented 4 years ago

x * 1.5这种转换到caffe,我这边有三种思路,假设x维度为(n,c,h,w),第一种把1.5先expand as成相同维度的blob,每个值都是1.5,然后用eltwise实现,需要重载一下expand_as;第二种,把1.5先expand as (n,c,1,1)的blob,每个值都是1.5,然后用双bottom的scale实现,这种稍微绕了一下;第三种,可以将scale的weight设为1.5,具体的可以参考_instance_norm的实现,应该也是可以实现的,不过我没试过。

dreamhighchina commented 4 years ago

我觉得还是expand的方式比较好哈哈,回头试试,因为对caffe框架不熟悉,谢谢大佬指导。

baoxin1100 commented 2 years ago

x * 1.5这种,可以修改pytorch_to_caffe.py的_mul函数,如下,添加对int值或者float值的判断,用Scale完成乘法/加法/减法操作。关键在layer.scale_param(scale=scale, bias=None)这一句,如果是乘法,就设置scale,bias设为None或者0,同理如果是加减法,scale要设置为1,bias设置为具体的数值。注意这里的scale和bias的形状是featuremap通道的个数,即scale.shape[0]==featuremap.shape[1],可以看下面代码, args[0]就是1.5,要把1.5转为通道长度的ndarray。

def _mul(input, *args):
    x = raw__mul__(input, *args)
    if not NET_INITTED or log.blobs(input) is None:
        return x
    if log.blobs(args[0]) is not None and input.shape == args[0].shape:
        layer_name = log.add_layer(name='mul')
        top_blobs = log.add_blobs([x], name='mul_blob')
        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 = 0  # product is 0
        log.cnet.add_layer(layer)
    elif isinstance(args[0], int) or isinstance(args[0], float):
        layer_name = log.add_layer(name='mul')
        top_blobs = log.add_blobs([x], name='mul_blob')
        layer = caffe_net.Layer_param(name=layer_name, type='Scale',
                                      bottom=[log.blobs(input)], top=top_blobs)
        scale = np.array(args[0],dtype=np.float32).squeeze().repeat(input.shape[1], 0)
        layer.scale_param(scale=scale, bias=None)
        layer.add_data(scale)
        log.cnet.add_layer(layer)

同理,加法_add和减法_sub也可添加相应的判断,代码如下: 加法:

def _add(input, *args):
    x = raw__add__(input, *args)
    if not NET_INITTED or log.blobs(input) is None:
        return x
    if log.blobs(args[0]) is not None and input.shape == args[0].shape:
        layer_name = log.add_layer(name='add')
        top_blobs = log.add_blobs([x], name='add_blob')
        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)
    elif isinstance(args[0], int) or isinstance(args[0], float):
        layer_name = log.add_layer(name='sub')
        top_blobs = log.add_blobs([x], name='sub_blob')
        layer = caffe_net.Layer_param(name=layer_name, type='Scale',
                                      bottom=[log.blobs(input)], top=top_blobs)
        bias = np.array(args[0],dtype=np.float32).squeeze().repeat(input.shape[1], 0)
        scale = np.ones(bias.shape, dtype=np.float32)
        layer.scale_param(scale=scale, bias=bias)
        layer.add_data(scale, bias)
        log.cnet.add_layer(layer)

减法:

def _sub(input, *args):
    x = raw__sub__(input, *args)
    if not NET_INITTED or log.blobs(input) is None:
        return x
    if log.blobs(args[0]) is not None and input.shape == args[0].shape:
        layer_name = log.add_layer(name='sub')
        top_blobs = log.add_blobs([x], name='sub_blob')
        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
        layer.param.eltwise_param.coeff.extend([1., -1.])
        log.cnet.add_layer(layer)
    elif isinstance(args[0], int) or isinstance(args[0], float):
        layer_name = log.add_layer(name='add')
        top_blobs = log.add_blobs([x], name='add_blob')
        layer = caffe_net.Layer_param(name=layer_name, type='Scale',
                                      bottom=[log.blobs(input)], top=top_blobs)
        bias = np.array(args[0],dtype=np.float32).squeeze().repeat(input.shape[1], 0)
        scale = np.ones(bias.shape, dtype=np.float32)
        layer.scale_param(scale=scale, bias=bias)
        layer.add_data(scale, -bias)
        log.cnet.add_layer(layer)