В кофе, слой convolution
берет один нижний блок и свертывает его с помощью изученных фильтров (которые инициализируются с использованием весового типа - "Xavier", "MSRA" и т.д.). Однако, мой вопрос заключается в том, можем ли мы просто сверлить две нижние капли и создать верхний капля. Какой был бы самый элегантный способ сделать это? Цель этого: один из нижних blob будет data
, а другой будет динамическим фильтром (изменяющимся в зависимости от data
), созданным предыдущими слоями (я пытаюсь реализовать динамическая свертка).
Моя попытка:
Один из способов, который пришел мне на ум, состоял в том, чтобы изменить filler.hpp
и назначить нижнюю blob как матрицу filler
(вместо "Xavier", "MSRA" и т.д.). Потом я подумал, что слой свертки поднимется оттуда. Мы можем установить lr = 0
, чтобы указать, что вес, инициализированный нашим пользовательским наполнителем, не должен изменяться. Однако, посмотрев исходный код, я все еще не знаю, как это сделать. С другой стороны, я не хочу нарушать работу кофе. Я все еще хочу, чтобы conv-слои функционировали нормально, если я хочу их.
Очевидно, что более утомительным способом является использование комбинации слоев Slice
, tile
и/или Scale
, чтобы буквально реализовать свертку. Я думаю, что это сработает, но это будет беспорядочно. Любые другие мысли?
Изменить 1:
Я написал новый слой, изменив слой свертки с кофе. В частности, в src/caffe/layers/conv_layer.cpp
, в строке 27, он принимает вес, определенный filler
, и свертывает его с нижним блобом. Поэтому вместо того, чтобы заполнять этот blob из filler
, я изменил слой таким образом, что теперь он принимает два нижних. Одно из дна непосредственно назначается наполнителю. Теперь мне пришлось внести некоторые другие изменения, например:
-
weight
blob имеет одинаковое значение для всех образцов. Здесь он будет иметь другое значение для разных образцов. Поэтому я изменил строку 32 из:
this->forward_cpu_gemm(
bottom_data + n * this->bottom_dim_,
weight,
top_data + n * this->top_dim_);
в
this->forward_cpu_gemm(
bottom_data + n * bottom[1]->count(1),
bottom[0]->cpu_data() + n * bottom[0]->count(1),
top_data + n * this->top_dim_);
Чтобы сделать вещи проще, я предположил, что нет никакого смещения, участвующего в этом вопросе, шаг всегда 1, заполнение всегда равно 0, группа всегда будет 1 и т.д. Однако, когда я тестировал передний проход, это дало мне странный ответ (с простым ядром свертки = np.ones((1,1,3,3))
). Скорости обучения были установлены равными нулю для этого ядра, так что он не изменяется. Однако я не могу получить правильный ответ. Любые предложения будут оценены.
Пожалуйста, не предлагайте решения с использованием существующих слоев, таких как Slice, Eltwise, Crop
. Я уже реализовал - он работает, но он невероятно сложный и неэффективный.