固定的 Gabor 滤波器卷积神经网络

3
我正在尝试构建一个CNN,其中一些卷积层的一半滤波器是固定的,而另一半则在训练模型时可学习。但我没有找到相关资料。
我想做的与他们在这篇论文中所做的类似https://arxiv.org/pdf/1705.04748.pdf
在Keras、Pytorch等框架中有实现这个功能的方法吗?
2个回答

5
当然。在PyTorch中,您可以使用nn.Conv2d,并将其weight参数手动设置为所需的过滤器,或者将这些权重从学习中排除。以下是一个简单的示例:
import torch
import torch.nn as nn

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

        self.conv_learning = nn.Conv2d(1, 5, 3, bias=False)
        self.conv_gabor = nn.Conv2d(1, 5, 3, bias=False)
        # weights HAVE TO be wrapped in `nn.Parameter` even if they are not learning
        self.conv_gabor.weight = nn.Parameter(torch.randn(1, 5, 3, 3))

    def forward(self, x):
        y = self.conv_learning(x)
        y = torch.sigmoid(y)
        y = self.conv_gabor(y)

        return y.mean()

model = Model()
xs = torch.randn(10, 1, 30, 30)
ys = torch.randn(10)
loss_fn = nn.MSELoss()

# we can exclude parameters from being learned here, by filtering them
# out based on some criterion. For instance if all your fixed filters have
# "gabor" in name, the following will do
learning_parameters = (param for name, param in model.named_parameters()
                             if 'gabor' not in name)
optim = torch.optim.SGD(learning_parameters, lr=0.1)

epochs = 10
for e in range(epochs):
    y = model(xs)
    loss = loss_fn(y, ys)

    model.zero_grad()
    loss.backward()
    optim.step()

1

这里有一个我在Stack Exchange上提出的与之相关的问题,您可以参考并查找其他信息。

为了避免构建自己的自定义层以允许部分冻结,也许最好创建两个层,其中一个被冻结,另一个没有。然后下一层可以连接到它们两个,并且其余的网络将保持不变。然后,您可以使用一些转移学习,并将预先训练的网络中的第一层转移到冻结的层中。对于此操作,您可以使用Keras函数式API

以下是如何使其工作的简单示例。

from tensorflow.python.keras import layers, Model
from tensorflow.python.keras.applications import InceptionV3

# Sample CNN
input_layer = layers.Input(shape=(224, 224, 3))
frozen_layer = layers.Conv2D(32, kernel_size=(3, 3), use_bias=False, trainable=False, name="frozen_layer")(input_layer)
thawed_layer = layers.Conv2D(32, kernel_size=(3, 3), trainable=True)(input_layer)
concat = layers.concatenate([frozen_layer, thawed_layer])
another_layer = layers.Conv2D(64, kernel_size=(3, 3), trainable=True)(concat)
output_layer = layers.Dense(10)(another_layer)
model = Model(inputs=[input_layer], outputs=[output_layer])

# Build a pre-trained model to extract weights from
transfer_model = InceptionV3(weights='imagenet', include_top=False)

assert transfer_model.layers[1].get_weights()[0].shape == model.get_layer(name="frozen_layer").get_weights()[0].shape

# Transfer the weights 
model.get_layer(name="frozen_layer").set_weights(transfer_model.layers[1].get_weights())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接