Как определить двумерную свертку на тензорах с рангом больше 4 в керасе / тензорном потоке - PullRequest
1 голос
/ 10 июля 2019

Я пытаюсь найти способ выполнить двумерные свертки над тензорами, размерность которых больше 4, что является входным рангом, необходимым для keras.layers.Conv2D и keras.backend.conv2d .Под этим я подразумеваю, что вместо ввода размером [batch, W, H, C] я хотел бы иметь возможность использовать [batch,<some_other_dimensions>, W, H, C], и для этих других измерений обрабатывать, по существу, так же, как «пакет» (например, незатронутыйсвертка).Неудивительно, что это приводит к ошибке, поэтому изменение формы массива кажется наиболее простым решением, однако есть проблемы с этим (как описано ниже).

При изменении формы я возиться с тем, что Керас видит какпакетное измерение, поэтому мне нужно использовать keras.backend.reshape , а не keras.layers.Reshape , который, по-видимому, не обращается к пакетному измерению ваших данных.Используя лямбда-слой и keras.backend.reshape , мы можем создать входные массивы размером [batch*<some_other_dimensions>,W,H,C], а затем снова изменить их форму после выполнения нашей свертки. Тем не менее, важно, чтобы этот слой мог образовывать часть полностью сверточной сети, которая может работать с произвольными размерами изображений, которые имеют неопределенные значения W и H (установите значение «Нет» при создании экземпляра формы входного слоя). Следовательно,мы заканчиваем тем, что передаем форму, которая имеет два неопределенных пространственных измерения, в keras.backend.reshape , которую он явно не может использовать: [batch*<some_other_dimensions>,None,None,C].

Я могу заставить ее работать, когдаявно объявив ширину и высоту (как вы можете видеть в моем коде).Однако я действительно не хочу жертвовать способностью принимать произвольные размеры пространственных измерений, поскольку для моего проекта важно иметь возможность сделать это.

Единственный другой вариант, который я могу придумать, - это на самом деле определить мойсобственный пользовательский слой, который может обрабатывать> 4-мерные входы для 2D сверток.Я не знаю, с чего начать, но совет был бы весьма желателен, если бы люди думали, что это самый жизнеспособный путь.Или, может быть, есть отличный лямбда-слой, который решает мою проблему?

from keras.layers import Input, Conv2D, Lambda
import keras.backend as K
from keras.models import Model


def reshape_then_conv(data_shape):

    input = Input(shape=data_shape)
    #should equal (None, *data_shape) because batch is prepended as None
    print('      INPUT SHAPE: ', input.shape)

    #reshaping input into 4D
    reshaped = Lambda(lambda x: K.reshape(x,(-1, *input.shape[3:])))(input)
    print('    AFTER RESHAPE: ', reshaped.shape)

    #convolve new 4D tensor
    convolved = Conv2D(10,(3,3),strides=2)(reshaped)
    print('AFTER CONVOLUTION: ', convolved.shape)

    #reshaping back but keeping new spatial and channel dimensions from convolution
    reshaped_back = Lambda(lambda x: K.reshape(x,(-1,*input.shape[1:3],*convolved.shape[-3:])))(convolved)
    return Model(inputs=input,outputs=reshaped_back)



#images of size 100,100,3 in 4-by-4 set
layer = reshape_then_conv([4,4,100,100,3])
print('     OUTPUT SHAPE: ', layer.output_shape,'\n')
#images of undefined size in 4-by-4 set
layer = reshape_then_conv([4,4,None,None,3])
print('     OUTPUT SHAPE: ', layer.output_shape)

Как и ожидалось, первый вызов 'reshape_then_conv' работает, так как мы явно устанавливаем ширину и высоту.Однако во втором примере:

TypeError: Не удалось преобразовать объект типа в Tensor.> Содержание: (-1, Размер (Нет), Размер (Нет), Размер (3)).Рассмотрим> приведение элементов к поддерживаемому типу.

Заранее благодарим за любые идеи, которые у вас могут быть!

ОБНОВЛЕНИЕ

Благодаря @Ответ DMolony, я изменил код следующим образом ...

from keras.layers import Input, Conv2D, Lambda
import keras.backend as K
from keras.models import Model

def reshape_then_conv(data_shape):

    input = Input(shape=data_shape)
    print('      INPUT SHAPE: ', input.shape)
    new_shape = K.concatenate((K.variable([-1],dtype='int32'),K.shape(input)[3:]))
    #reshaping input into 4D
    reshaped = Lambda(lambda x: K.reshape(x,new_shape))(input)
    print('    AFTER RESHAPE: ', reshaped.shape)

    #convolve new 4D tensor
    convolved = Conv2D(10,(3,3),strides=2)(reshaped)
    print('AFTER CONVOLUTION: ', convolved.shape)

    returning_shape = K.concatenate((K.variable([-1],dtype='int32'),K.shape(input)[1:3],K.shape(convolved)[-3:]))
    #reshaping back but keeping new spatial and channel dimensions from convolution
    reshaped_back = Lambda(lambda x: K.reshape(x,returning_shape))(convolved)
    return Model(inputs=input,outputs=reshaped_back)

#images of size 100,100,3 in 4-by-4 set
layer = reshape_then_conv([4,4,100,100,3])
print('     OUTPUT SHAPE: ', layer.output_shape,'\n')
#images of undefined size in 4-by-4 set
layer = reshape_then_conv([4,4,None,None,3])
print('     OUTPUT SHAPE: ', layer.output_shape)

1 Ответ

0 голосов
/ 10 июля 2019

При изменении формы вместо использования статической формы, например

input.shape[1:3]  

попробуйте предоставить динамическую форму, например

K.shape(input)[1:3]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...