Свертка для уменьшения размерности одномерного вектора

В CNN, если выходные данные являются одномерным вектором (скажем, предварительным логическим уровнем), как можно уменьшить размерность до указанного размера, используя только свертки?

Как получить размеры фильтра / поле восприятия для выполнения такой задачи?

Я знаю, что это может быть достигнуто путем размещения полностью подключенного слоя на конце сети, но это не кажется таким элегантным.

3 ответа

Решение

Используйте идею, первоначально предложенную в документе All Convolutional Net, а затем широко использовавшуюся в начальной сети, т.е. примените свертку для уменьшения размерности.

Хитрость заключается в том, чтобы выполнить свертку с единицей filter (1x1 для двумерной свертки, 1x1x1 для 3D и т. д.) с меньшим количеством фильтров. В настоящее время этот прием применяется постоянно для сохранения вычислений в очень глубоких сверточных сетях, поэтому его можно использовать и перед сверточными слоями. В вашем вопросе выходной тензор является одномерным (кроме размера пакета), поэтому используйте 1-D свертку с 1 размер ядра.

Вот код в программе tenorflow, который уменьшает длину тензора с 64 до 32:

                              # `x` shape:  [batch, length] = [?, 64]
layer = tf.expand_dims(x, 2)  # reshape to: [batch, channels, 1] = [?, 64, 1]

output = tf.layers.conv1d(layer, filters=32, kernel_size=1,
                          strides=1, padding='valid',
                          data_format='channels_first')

                              # new shape:  [batch, filters, 1] = [?, 32, 1]
output = tf.squeeze(output)   # reshape to: [batch, length] = [?, 32]

Как насчет одномерной свертки? Вы можете использовать шаги как в следующем:

n,w = x.shape
c = 1
x = x.reshape(n,w,c) # 1d vector with one 1 channel
x = conv1d(x, 1, 3, stride=2, pad=1) # 1 filter so output size will be (n,w/2,c)
x = x.reshape(n,w//2)

Это даст вам целочисленное деление вашей текущей размерности. Или вы могли бы иметь канал для каждого измерения для вашего вывода, а затем объединить по всей 1D области:

x = x.reshape(n,w,c)
x = conv1d(x, d, 3, pad=1) # d filters so output (n,w,d)
x = x.mean(1) # mean over 1d space so now (n,d)

Нет никаких гарантий относительно того, будет ли какой-либо из них действительно работать хорошо, но, будучи нейронной сетью, они, вероятно, ничего плохого не сломают.

Наконец, чит-ответ:

x = x.reshape(n,c,w) # (n,1,w)
x = conv1d(x, d, 1) # (n,1,d)
x = x.reshape(n,d)

У вас есть возможность добавить пул слой после свертки? Если да, то это одна из основных целей этого слоя, уменьшить вектор до более низкого размера.

В противном случае количество примененных фильтров является размерностью вашего выходного пространства.