【问题标题】:Pass pretrained weights in CNN Pytorch to a CNN in Tensorflow将 CNN Pytorch 中的预训练权重传递给 Tensorflow 中的 CNN
【发布时间】:2020-08-04 18:26:20
【问题描述】:

我已经在 Pytorch 中为 224x224 大小的图像和 4 个类别训练了这个网络。

class CustomConvNet(nn.Module):
    def __init__(self, num_classes):
        super(CustomConvNet, self).__init__()

        self.layer1 = self.conv_module(3, 64)
        self.layer2 = self.conv_module(64, 128)
        self.layer3 = self.conv_module(128, 256)
        self.layer4 = self.conv_module(256, 256)
        self.layer5 = self.conv_module(256, 512)
        self.gap = self.global_avg_pool(512, num_classes)
        #self.linear = nn.Linear(512, num_classes)
        #self.relu = nn.ReLU()
        #self.softmax = nn.Softmax()

    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        out = self.layer5(out)
        out = self.gap(out)
        out = out.view(-1, 4)
        #out = self.linear(out)

        return out

    def conv_module(self, in_num, out_num):
        return nn.Sequential(
            nn.Conv2d(in_num, out_num, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=(2, 2), stride=None))

    def global_avg_pool(self, in_num, out_num):
        return nn.Sequential(
            nn.Conv2d(in_num, out_num, kernel_size=3, stride=1, padding=1),
            #nn.BatchNorm2d(out_num),
            #nn.LeakyReLU(),

            nn.ReLU(),
            nn.Softmax(),
            nn.AdaptiveAvgPool2d((1, 1)))

我从第一个 Conv2D 得到权重,它的大小是 torch.Size([64, 3, 3, 3])

我已将其保存为:

weightsCNN = net.layer1[0].weight.data
np.save('CNNweights.npy', weightsCNN)

这是我在 Tensorflow 中构建的模型。我想将从 Pytorch 模型中保存的权重传递到这个 Tensorflow CNN。

    model = models.Sequential()
    model.add(layers.Conv2D(64, (3, 3), activation='relu', input_shape=(224, 224, 3)))
    model.add(layers.MaxPooling2D((2, 2)))

    model.add(layers.Conv2D(128, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))

    model.add(layers.Conv2D(256, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))

    model.add(layers.Conv2D(256, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))

    model.add(layers.Conv2D(512, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))

    model.add(layers.Conv2D(512, (3, 3), activation='relu'))

    model.add(layers.GlobalAveragePooling2D())
    model.add(layers.Dense(4, activation='softmax'))
    print(model.summary())


    adam = optimizers.Adam(learning_rate=0.0001, amsgrad=False)
    model.compile(loss='categorical_crossentropy',
                  optimizer=adam,
                  metrics=['accuracy'])


    nb_train_samples = 6596
    nb_validation_samples = 1290
    epochs = 10
    batch_size = 256


    history = model.fit_generator(
        train_generator,
        steps_per_epoch=np.ceil(nb_train_samples/batch_size),
        epochs=epochs,
        validation_data=validation_generator,
        validation_steps=np.ceil(nb_validation_samples / batch_size)
        )

我应该怎么做呢? Tensorflow 需要什么形状的权重?谢谢!

【问题讨论】:

    标签: python tensorflow neural-network computer-vision pytorch


    【解决方案1】:

    您可以非常简单地检查所有keras 层的所有权重的形状:

    for layer in model.layers:
        print([tensor.shape for tensor in layer.get_weights()])
    

    这将为您提供所有权重的形状(包括偏差),因此您可以相应地准备加载的numpy 权重。

    要设置它们,请执行类似的操作:

    for torch_weight, layer in zip(model.layers, torch_weights):
        layer.set_weights(torch_weight)
    

    其中torch_weights 应该是一个列表,其中包含您必须加载的np.array 列表。

    通常torch_weights 的每个元素将包含一个np.array 用于权重和一个用于偏差。

    请记住,从打印中收到的形状必须与您在set_weights中输入的形状完全相同。

    请参阅documentation 了解更多信息。

    顺便说一句。确切的形状取决于模型执行的层和操作,有时您可能必须转置一些数组以“适应它们”。

    【讨论】:

    • 谢谢!我已经在 Tensorflow (3,3,3,54) 中获得了正确的权重形状。现在我的问题是如何将它们传递给我在 Tensorflow 中的第一个 Conv2D 层。有什么想法吗?
    • @Liz 如指定,在本例中为model.layers[0].set_weights([your_tensor_with_correct_shape])。请记住torch 在您的情况下具有[54, 3, 3, 3] 格式的权重,因为它首先是通道(至少到1.5),因此您需要在保存为np.array 之前对其进行转置。 weight_tensor.permute(1, 2, 3, 0).
    • 谢谢!!它现在抛出这个错误:ValueError: You called `set_weights(weights)` on layer "conv2d_3" with a weight list of length 3, but the layer was expecting 2 weights. Provided weights: [[[[-0.15836713 -0.178757 0.16782044 ... 0.175... 任何线索可能是什么问题?
    • 如所述,set_weights 的参数过多,请验证您要放置的权重
    猜你喜欢
    • 2018-11-14
    • 1970-01-01
    • 2017-06-17
    • 2016-06-20
    • 2016-03-14
    • 2017-10-24
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多