【caffe】caffe实现sharing weights

最近在Re-ID任务中有不少网络都是sharing weights的。一般都是有一个已经训练好的模型比如resnet-50,然后自己造的主网络都是有几个resnet-50的分支的,而每个分支的卷积层权重又是共享的,caffe是怎样处理的呢?

经过一番折腾,终于整明白了,其实很简单。

首先定位到caffe.proto,LayerParameter中有这样一项

repeated ParamSpec param = 6;

也就是设置每层参数学习率,正则化因子的参数。然后找到ParamSpec的定义,其中有这样一项

// The names of the parameter blobs -- useful for sharing parameters among
// layers, but never required otherwise.  To share a parameter between two
// layers, give it a (non-empty) name.
optional string name = 1;

说的就是如果指定参数blob名字的话,则不同的层可以指向同一个blob,也就达到了sharing weights的目的。

举个例子,加入已经训练好的网络只有一个卷积层,如图所示

【caffe】caffe实现sharing weights_第1张图片

而咱们自己造的网络有3个分支,如图所示

【caffe】caffe实现sharing weights_第2张图片

同时,我们希望每个分支的权重是共享的,这时候只需要将train_val.prototxt中的param中加上同样的name参数即可。

####################################layer1 ##############################


layer {
    bottom: "data/layer1"
    top: "conv1/layer1"
    name: "conv1/layer1"
    type: "Convolution"
    param {
        name: "layer/conv1_w"
        lr_mult: 1
        decay_mult: 1
    }
    param {
        name: "layer/conv1_b"
        lr_mult: 2
        decay_mult: 0
    }
    convolution_param {
        num_output: 64
        kernel_size: 7
        pad: 3
        stride: 2
        weight_filler {
            type: "xavier"
        }
    }
}


######################################layer2#############################


layer {
    bottom: "data/layer2"
    top: "conv1/layer2"
    name: "conv1/layer2"
    type: "Convolution"
    param {
        name: "layer/conv1_w"
        lr_mult: 1
        decay_mult: 1
    }
    param {
        name: "layer/conv1_b"
        lr_mult: 2
        decay_mult: 0
    }
    convolution_param {
        num_output: 64
        kernel_size: 7
        pad: 3
        stride: 2
        weight_filler {
      type: "xavier"
    }
    }
}



#######################################layer3###############################


layer {
    bottom: "data/layer3"
    top: "conv1/layer3"
    name: "conv1/layer3"
    type: "Convolution"
    param {
        name: "layer/conv1_w"
        lr_mult: 1
        decay_mult: 1
    }
    param {
        name: "layer/conv1_b"
        lr_mult: 2
        decay_mult: 0
    }
    convolution_param {
        num_output: 64
        kernel_size: 7
        pad: 3
        stride: 2
        weight_filler {
      type: "xavier"
    }
    }
}

这样在fine-tune时,有同样name的参数都会指向同一个blob,反向更新的时候各个分支的梯度都会累加到同一个blob的diff中去,这样就达到了sharing weights的目的。

你可能感兴趣的:(CAFFE)