【问题标题】:How to change the first convolution of a pretrained ResNet in Tensorflow?如何更改 Tensorflow 中预训练 ResNet 的第一个卷积?
【发布时间】:2019-10-13 15:21:14
【问题描述】:

您好,我需要将模型的第一个卷积从 rgb/resnet_v1_50/conv1/weights:0 (float32_ref 7x7x3x64) 更改为 rgb/resnet_v1_50/conv1/weights:0 (float32_ref 7x7x4x64),因此基本上增加了过滤器的数量从 3 到 4 接受 4 个通道的图像,但在其他地方保留预训练的权重(只是额外的通道初始化 ramdonly)。

你知道如何在 Tensorflow 1.x 中做到这一点(我更喜欢 PyTorch 人......)?

在 PyTorch 中我这样做:

net = model.resnet50(num_classes=dataset_train.num_classes(),pretrained=True)

new_conv1 = nn.Conv2d(4, 64, kernel_size=7, stride=2,padding=3,bias=False)  

conv1 = net.conv1

with torch.no_grad():

   new_conv1.weight[:, :3, :, :]= conv1.weight

   new_conv1.bias = conv1.bias

net.conv1 = new_conv1

这是在 tensorflow 中创建模型的方式:

def single_stream(self, images, modality, is_training, reuse=False):

    with tf.variable_scope(modality, reuse=reuse):
        with slim.arg_scope(resnet_v1.resnet_arg_scope()):
            _, end_points = resnet_v1.resnet_v1_50(
                images, self.no_classes, is_training=is_training, reuse=reuse)

    # last bottleneck before logits
    net = end_points[modality + '/resnet_v1_50/block4']
    if 'autoencoder' in self.mode:
        return net

    with tf.variable_scope(modality + '/resnet_v1_50', reuse=reuse):
        bottleneck = slim.conv2d(net, self.hidden_repr_size, [
                                 7, 7], padding='VALID', activation_fn=tf.nn.relu, scope='f_repr')
        net = slim.conv2d(bottleneck, self.no_classes, [
                          1, 1], activation_fn=None, scope='_logits_')

    if ('train_hallucination' in self.mode or 'test_disc' in self.mode or 'train_eccv' in self.mode):
        return net, bottleneck

    return net

我可以使用 build_model 中的命令:self.images = tf.placeholder(tf.float32, [None, 224, 224, 4], modality + '_images') 有效将 3 更改为 4: rgb/resnet_v1_50/conv1/weights:0 (float32_ref 7x7x4x64) [12544, bytes: 50176] 但问题出在检查点上!

非常感谢您的帮助!

【问题讨论】:

    标签: python tensorflow deep-learning


    【解决方案1】:

    与使用 Pytorch 一样,您可以在 Keras 中执行相同的操作,它现在是 TF2 的一个模块 (more info)。

    我将向您展示一种可能的方法:

    net_conv1 = model.layers[2] # first 2D convolutional layer, from model.layers, or model.summary()
    # your new set of weights must have same dimensions of the ouput of the layer
    print( 'weights shape: ', numpy.shape(net_conv1.weights) )
    print( net_conv1.weights[0].shape )
    print( net_conv1.weights[1].shape )
    # New weights
    osh_0 = net_conv1.weights[0].shape.as_list()
    osh_1 = net_conv1.weights[1].shape.as_list()
    print(osh_0, osh_1)
    new_conv1_w_0 = numpy.random.rand( *osh_0 )
    new_conv1_w_1 = numpy.random.rand( *osh_1 )
    # update the weights
    net_conv1.set_weights([new_conv1_w_0, new_conv1_w_1])
    # check the result
    net_conv1.get_weights()
    # update the model
    model.layers[2] = net_conv1
    

    查看 Keras 文档的layers section

    希望对你有帮助

    【讨论】:

    • 我不太习惯 Keras 我正在运行的所有代码都在 TF1.4 中我必须保留这个版本以进行比较(这是为了一篇文章)...我可以只需在 Keras 中添加一部分代码,无需将所有内容从 TF 更改为 Keras 代码(我知道 keras 是控制 tensorflow 的高级程序)?
    • 是的,我只是尝试在 tensorflow 代码中使用 keras 它不起作用,因为模型是使用 tensorflow 而不是 keras 创建的(所以模型没有任何属性层)......正如我所说的那样我的代码我只是想通过我的修改(4 个通道而不是 3 个)来运行它,以便发表一篇文章。
    猜你喜欢
    • 2020-12-07
    • 2021-06-09
    • 2018-07-25
    • 1970-01-01
    • 2021-10-06
    • 2017-01-22
    • 1970-01-01
    • 2017-07-26
    • 2018-07-07
    相关资源
    最近更新 更多