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