Страницы

Поиск по вопросам

воскресенье, 1 декабря 2019 г.

Как осуществить поиск объекта на изображении с помощью полносверточной нейронной сети

#python #нейронные_сети #keras


Здравствуйте, стоит задача поиска объекта с помощью полносверточной нейронной сети,
используя Keras, theano, на языке python. На данный момент используется вот такая конфигурация
сети: 

def create_encoding_layers():
    kernel = 3
    filter_size = 64
    pad = 1
    pool_size = 2
    return [
        ZeroPadding2D(padding=(pad,pad)),
        Convolution2D(filter_size, kernel, kernel, border_mode='valid'),
        BatchNormalization(),
        Activation('relu'),
        MaxPooling2D(pool_size=(pool_size, pool_size)),

        ZeroPadding2D(padding=(pad,pad)),
        Convolution2D(32, kernel, kernel, border_mode='valid'),
        BatchNormalization(),
        Activation('relu'),
        MaxPooling2D(pool_size=(pool_size, pool_size)),

        ZeroPadding2D(padding=(pad,pad)),
        Convolution2D(32, kernel, kernel, border_mode='valid'),
        BatchNormalization(),
        Activation('relu'),
        MaxPooling2D(pool_size=(pool_size, pool_size)),

        ZeroPadding2D(padding=(pad,pad)),
        Convolution2D(64, kernel, kernel, border_mode='valid'),
        BatchNormalization(),
        Activation('relu'),
    ]
    def create_decoding_layers():
    kernel = 3
    filter_size = 64
    pad = 1
    pool_size = 2
    return[
        ZeroPadding2D(padding=(pad,pad)),
        Convolution2D(64, kernel, kernel, border_mode='valid'),
        BatchNormalization(),

        UpSampling2D(size=(pool_size,pool_size)),
        ZeroPadding2D(padding=(pad,pad)),
        Convolution2D(32, kernel, kernel, border_mode='valid'),
        BatchNormalization(),

        UpSampling2D(size=(pool_size,pool_size)),
        ZeroPadding2D(padding=(pad,pad)),
        Convolution2D(32, kernel, kernel, border_mode='valid'),
        BatchNormalization(),

        UpSampling2D(size=(pool_size,pool_size)),
        ZeroPadding2D(padding=(pad,pad)),
        Convolution2D(filter_size, kernel, kernel,     border_mode='valid'),
        BatchNormalization(),
        ZeroPadding2D(padding=(0,pad+1)),
    ]

    segnet_basic = models.Sequential()
    segnet_basic.add(Layer(input_shape=(120, 420, 1)))
    segnet_basic.encoding_layers = create_encoding_layers()
    for l in segnet_basic.encoding_layers:
        segnet_basic.add(l)
    segnet_basic.decoding_layers = create_decoding_layers()
    for l in segnet_basic.decoding_layers:
        segnet_basic.add(l)
    segnet_basic.add(Convolution2D(1, 1, 1, border_mode='valid',))
    segnet_basic.summary()
    segnet_basic.add(Reshape((120,420,1)))


На вход подается фотография и маска(область, где находится объект заполнена единицами,
а остальная область нулями). Как я понимаю, на выходе мы должны получить такую же маску.
Пробовал разные функции потерь. На выходе получается ерунда. Собственно вопрос: что
нужно исправить, чтобы получить на выходе аналогичную маску ? Какую функцию потерь
и  optimizer использовать? 
 На картинке пример работы уже обученной сети. image - изображение, которое подается
сети, label - ожидаемый результат, который я для вывода умножил на 255, result - то,
что выдает сеть.Так же умножил на 255 для вывода 

    


Ответы

Ответ 1



Исходя из того, что указано в вопросе, можно сделать выводы: Ваша НС, вероятно, переобучается. Это следует из того, что на train множестве Вы имеете хорошие результаты, а на тестовом -- никакие. Один из возможных вариантом -- это использование регуляризации. Кроме того, попробуйте использовать метод dropOut. Данная техника способствует уменьшению переобучения путём случайного исключения связей в НС. Вам необходимо делать cross-validation (cv). Данная процедура проводится для оценки модели и подбора параметров. Нас интересут оценка. В scikit-learn есть замечательные механизмы, позволяющие это делать. Один из вариантов cv (вам он подходит больше, так как ваша выборка маленькая) заключается в том, что исходное множество разбивается на 2 части (например): 0.3 - 0.7. Та часть, которая больше 0.7 является обучающим множеством. Та часть, которая меньше -- валидационном. Мы производим обучение на обучающем множестве. После чего проверяем наш результат на валидационном. Проделаем так много раз. Возьмите, для простоты 10. Всё зависит от дисперсии ответов и размера множества. Если cv не делать, то судить о модели никак нельзя. Ещё одной вероятной причиной переобучения является наличие большого количества слоёв в НС при необльшом количестве примеров. Для того, чтобы повысить число примеров, можно воспользоваться нарезкой изображений. Берём и режем каждое изображение на необшие области, сопостовимые с объектом интереса (желательно, чтобы области были больше объекта). Лучше резать картинку так, чтобы зоны ложились в нахлёст. Например, пусть исходная картика имеет размер 400х400. Порежем её на семплы 20х20. Будем передвигать окно 20х20 с шагом 10. Тогда получится, что каждое окно будет ложиться на предыдущее. Для каждого окна можно осуществлять предсказание, которое Вы хотели делать. Ещё одним возможным вариантом является вращение картинок на небольшие углы. Но данный вид трансформации может быть пагубным (в зависимости от задачи). Дальнейшие советы давать сложно, поскольку не видно всего множества, а также непонятна конечная цель задачи.

Ответ 2



В конфигурации Вашей сети на вход подается одно изображение формата (120, 420, 1). На выходе сети одно изображение такого же формата (120, 420, 1). Соответственно, чтобы научить эту (или другую) сеть строить из изображения маску, необходимо сеть обучить, то есть прогнать через нее большое количество пар (картинка, маска). Тогда в случае успешного обучения сеть будет уметь по картинке получать маску. Если просто загнать картинку в необученную сеть, на выходе разумеется будет ерунда. Функцию потерь в случае маски можно вполне брать стандартную вроде mse. Более эффективно в случае детектирования объектов таргетировать bounding box, а не маску и, соответственно, использовать box regression loss.

Комментариев нет:

Отправить комментарий