Фиксированный фильтр Габора в сверточных нейронных сетях - PullRequest
1 голос
/ 09 апреля 2019

Я пытаюсь создать CNN с несколькими конверсными слоями, где половина фильтров в слое зафиксирована, а другая половина обучаема во время обучения модели.Но я ничего не нашел об этом.

То, что я пытаюсь сделать, похоже на то, что они делали в этой статье https://arxiv.org/pdf/1705.04748.pdf

Есть ли способ сделать это в Керасе?, Pytorch ...

Ответы [ 2 ]

1 голос
/ 09 апреля 2019

Конечно.В PyTorch вы можете использовать nn.Conv2d и

  1. , установить его параметр weight вручную для желаемых фильтров
  2. исключить эти веса из обучения

Простой пример:

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 голос
/ 09 апреля 2019

Вот несколько связанный вопрос, который я задал на Stack Exchange , на который вы можете сослаться и найти дополнительную информацию.

Чтобы не создавать собственные пользовательские слои, допускающие частичное замораживание,возможно, было бы лучше создать два слоя, где один заморожен, а другой нет.Тогда следующий уровень мог бы соединиться с ними обоими, и остальная сеть была бы той же самой.Затем вы можете использовать небольшое обучение переносу и перенести первый слой из предварительно обученной сети в замороженный слой.Для этого вы можете использовать Функциональный API Keras .

Вот простой пример того, как вы могли бы сделать эту работу.

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())
...