Тонкая настройка обнаружения объектов GluonCV - выберите, какие слои будут изменены (остальное заморозить)
У меня вопрос о процедуре тонкой настройки предварительно обученной модели обнаружения объектов с помощью GluonCV, описанной в этом руководстве.
Насколько я понимаю, описанная процедура изменяет все значения веса в модели. Я хотел только настроить полностью подключенный слой в конце сети и заморозить остальные веса.
Я предполагаю, что я должен указать, какие параметры я хочу изменить при создании трейнера:
trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': 0.001, 'wd': 0.0005, 'momentum': 0.9})
поэтому вместо net.collect_params() я должен перечислить параметры, которые мне нужны для обучения, и запустить остальную часть процесса в обычном режиме. Однако я не знаю, как точно выделить эти параметры... Я попробовал распечатать:
params = net.collect_params()
но из этого списка я не знаю, какие из них соответствуют последним слоям FC. Какие-либо предложения?
1 ответ
Допустим, у нас есть предварительно обученная глюонная модель для задачи классификации:
>>> import mxnet as mx
>>> net = mx.gluon.nn.HybridSequential()
>>> net.add(mx.gluon.nn.Conv2D(channels=6, kernel_size=5, padding=2, activation='sigmoid'))
>>> net.add(mx.gluon.nn.MaxPool2D(pool_size=2, strides=2))
>>> net.add(mx.gluon.nn.Flatten())
>>> net.add(mx.gluon.nn.Dense(units=10))
>>> net.collect_params()
hybridsequential0_ (
Parameter conv0_weight (shape=(6, 0, 5, 5), dtype=<class 'numpy.float32'>)
Parameter conv0_bias (shape=(6,), dtype=<class 'numpy.float32'>)
Parameter dense0_weight (shape=(1, 0), dtype=float32)
Parameter dense0_bias (shape=(1,), dtype=float32)
)
Чтобы точно настроить эту сверточную сеть, мы хотим заморозить все блоки, кроме.
Во-первых, напомним, что метод принимает строку регулярного выражения для выбора конкретных параметров блока по их именам (или префиксам;
prefix
параметр,
Dense
, или любой другой глюонный (гибридный) блок). По умолчанию префиксы являются именами классов, т.е. если блок
Conv2D
тогда префикс
conv0_
или же
conv1_
и т.д. Кроме того, возвращает экземпляр
mxnet.gluon.parameter.ParameterDict
, у которого есть
setattr
метод.
Решение:
>>> conv_params = net.collect_params('(?!dense).*')
>>> conv_params.setattr('grad_req', 'null')
или просто
>>> net.collect_params('(?!dense).*').setattr('grad_req', 'null')
Здесь мы исключаем все совпадающие параметры, чтобы получить только
conv
блоки и установите их атрибуты на. Теперь обучаем модель
net
с
mxnet.gluon.Trainer
будет обновлять только
dense
параметры.
Более удобно иметь предварительно обученную модель с отдельными атрибутами, указывающими определенные блоки, например, блок функций, генераторы привязок и т. Д. В нашем случае у нас есть сверточная сеть, которая извлекает признаки и передает их в выходной блок.
class ConvNet(mx.gluon.nn.HybridSequential):
def __init__(self, n_classes, params=None, prefix=None):
super().__init__(params=params, prefix=prefix)
self.features = mx.gluon.nn.HybridSequential()
self.features.add(mx.gluon.nn.Conv2D(channels=6, kernel_size=5, padding=2,
activation='sigmoid'))
self.add(mx.gluon.nn.MaxPool2D(pool_size=2, strides=2))
self.add(mx.gluon.nn.Flatten())
self.output = mx.gluon.nn.Dense(units=n_classes)
def hybrid_forward(self, F, x):
x = self.features(x)
return self.output(x)
С этим объявлением convnet нам не нужно использовать регулярные выражения для доступа к необходимым блокам:
>>> net = ConvNet(n_classes=10)
>>> net.features.collect_params().setattr('grad_req', 'null')
Модели Gluon CV следуют именно этой схеме. Посмотрите документацию на нужную модель и выберите блоки, которые вы хотите заморозить. Если документы пусты, запустите
collect_params
чтобы увидеть все параметры и отфильтровать с помощью регулярного выражения те, которые нужно настроить, и установить возвращаемые параметры '
grad_req
к
'null'
.