首页 > 解决方案 > 如何更改 Tensorflow 中预训练 ResNet 的第一个卷积?

问题描述

嗨,我需要将模型的第一个卷积从 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] 但问题出在检查点上!

非常感谢你的帮助!

标签: pythontensorflowdeep-learning

解决方案


正如您使用 Pytorch 所做的那样,您可以在 Keras 中做同样的事情,它现在是 TF2 的一个模块(更多信息)。

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

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 文档的图层部分

希望它会有所帮助


推荐阅读