ValueError: отрицательный размер измерения, вызванный вычитанием 2 из 1 для 'max_pooling3d_3 / MaxPool3D' (op: 'MaxPool3D') с входными формами [?, 1,60,60,128] - PullRequest
0 голосов
/ 18 июня 2020

Я создаю модель keras UNET для сегментации трехмерных изображений.

Форма изображения 240, 240, 150

Форма ввода: 240, 240, 150, 4, 335 >> обучающие данные

Форма вывода должна быть 240, 240, 150, 335 >> обучающие метки

Я использую Conv3D, MaxPooling3D, Conv3DTranspose и объединяю слои для построения модели

Я столкнулся с этой ошибкой во время построения модели где я делаю повышающую дискретизацию

ValueError: Negative dimension size caused by subtracting 2 from 1 for 'max_pooling3d_3/MaxPool3D' (op: 'MaxPool3D') with input shapes: [?,1,60,60,128].

Я искал некоторые решения и нашел слои padding='same' и k.set_image_data_format('channels_last')

, при этом я столкнулся с новой ошибкой при выполнении конкатенация после восходящей выборки

ValueError: A `Concatenate` layer requires inputs with matching shapes except for the concat axis. Got inputs shapes: [(None, 30, 30, 18, 256), (None, 30, 30, 19, 256)]

В настоящее время я переключаюсь между этими двумя ошибками и не могу найти точную проблему, чтобы решить, как ее решить

Вот код, в котором я создаю модель

def build_unet_model(input_shape):
    inputs = Input(input_shape)

    conv1 = create_shared_convolution(inputs, 32, config.KERNEL_SIZE)
    block1 = down_convolution(conv1, config.POOL_SIZE)

    conv2 = create_shared_convolution(block1, 64, config.KERNEL_SIZE)
    block2 = down_convolution(conv2, config.POOL_SIZE)

    conv3 = create_shared_convolution(block2, 128, config.KERNEL_SIZE)
    block3 = down_convolution(conv3, config.POOL_SIZE)

    conv4 = create_shared_convolution(block3, 256, config.KERNEL_SIZE)
    block4 = down_convolution(conv4, config.POOL_SIZE)

    conv5 = create_shared_convolution(block4, 512, config.KERNEL_SIZE)  # mid_con
    up1 = concatenate_layers(create_up_convolution(conv5, 256, config.STRIDE_SIZE), conv4)

    conv6 = create_shared_convolution(up1, 256, config.KERNEL_SIZE)
    up2 = concatenate_layers(create_up_convolution(conv6, 128, config.STRIDE_SIZE), conv3)

    conv7 = create_shared_convolution(up2, 128, config.KERNEL_SIZE)
    up3 = concatenate_layers(create_up_convolution(conv7, 64, config.STRIDE_SIZE), conv2)

    conv8 = create_shared_convolution(up3, 64, config.KERNEL_SIZE)
    up4 = concatenate_layers(create_up_convolution(conv8, 32, config.STRIDE_SIZE), conv1)

    conv9 = create_shared_convolution(up4, 32, config.KERNEL_SIZE)
    outputs = create_output_layer(conv9, 4, (1, 1, 1))

    model = Model(inputs=[inputs], outputs=[outputs])
    print(model.summary())
    return model.compile(optimizer=AdaBound(lr=1e-5, final_lr=1), loss=utils.ce_dl_loss, metrics=['accuracy'])

, и это 5 функций, используемых при построении модели

def create_shared_convolution(input_layer, number_of_nets, kernel_size,
                              activation='relu', padding='same',
                              kernel_initializer=initializers.random_normal(stddev=0.01)):
    conv = Conv3D(number_of_nets, kernel_size, activation=activation, padding=padding,
                  kernel_initializer=kernel_initializer)(input_layer)

    conv = Conv3D(number_of_nets, kernel_size, activation=activation, padding=padding,
                  kernel_initializer=kernel_initializer)(conv)
    return conv

def down_convolution(input_layer, pool_size):
    return MaxPooling3D(pool_size=pool_size)(input_layer)


def create_up_convolution(input_layer, number_of_nets, stride_size, padding='same',
                          kernel_initializer=initializers.random_normal(stddev=0.01)):
    return Conv3DTranspose(number_of_nets, stride_size, strides=stride_size, padding=padding,
                           kernel_initializer=kernel_initializer)(input_layer)

def concatenate_layers(layer1, layer2):
    return merge.concatenate([layer1, layer2])


def create_output_layer(input_layer, number_of_nets, kernel_size, activation='relu',
                        kernel_initializer=initializers.random_normal(stddev=0.01)):
    conv = Conv3D(number_of_nets, kernel_size, activation=activation,
                  kernel_initializer=kernel_initializer)(input_layer)

    return Activation('softmax')(conv)

1 Ответ

0 голосов
/ 18 июня 2020

Вот некоторые объяснения обеих ошибок.

Первая связана с тем, что ваши карты функций слишком малы в вашей сети. У меня нет подробной информации о вашей сетевой архитектуре, но если вы примените много слоев maxpooling к своему входу (формы 240, 240, 150), он может получить только одно значение в измерении (возможно, что-то вроде ( N, N, 1)). Добавление другого maxpooling поверх этого невозможно, потому что у вас недостаточно значения в измерении для его выполнения. Вот почему возникает отрицательная ошибка измерения.

Вторая, вероятно, связана с maxpooling слоями. Когда вы применяете свой первый maxpooling, нет никаких проблем: форма вывода (120, 120, 75), поэтому повышающая дискретизация вернет вам (240, 240, 150). Но следующий maxpooling (примененный к (120, 120, 75)) даст результат с формой (60, 60, 37), потому что последнее измерение нечетное. И повышающая дискретизация даст (120, 120, 74). Отсюда несоответствие. Решение этой проблемы - добавить ZeroPadding слоев, когда размер нечетный, перед их объединением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...