Я пытаюсь создать CNN с некоторыми конверсионными слоями, где половина фильтров в слое фиксирована, а другая половина может быть изучена при обучении модели. Но я ничего не нашел по этому поводу.
то, что я пытаюсь сделать, похоже на то, что они сделали в этой статье https://arxiv.org/pdf/1705.04748.pdf
Есть ли способ сделать это в Keras, Pytorch...
Вот несколько связанный вопрос, который я задал в Обмен стеками, на который вы можете ссылаться и найти дополнительную информацию.
Чтобы не создавать собственные пользовательские слои, допускающие частичное замораживание, возможно, было бы лучше создать два слоя, один из которых заморожен, а другой нет. Тогда следующий уровень сможет подключиться к ним обоим, и остальная часть сети будет такой же. Затем вы можете использовать небольшое обучение переносу и перенести первый слой из предварительно обученной сети в замороженный слой. Для этого вы можете использовать Функциональный 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())
Конечно. В 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()