50% точность в CNN по двоичной классификации изображений - PullRequest
0 голосов
/ 18 июня 2020

У меня есть коллекция изображений с открытыми и закрытыми глазами.
Данные собираются из текущего каталога с помощью keras следующим образом:

batch_size = 64
N_images = 84898 #total number of images
datagen = ImageDataGenerator(
    rescale=1./255)
data_iterator = datagen.flow_from_directory(
    './Eyes',
    shuffle = 'False',
    color_mode='grayscale',
    target_size=(h, w),
    batch_size=batch_size,
    class_mode = 'binary')

У меня есть файл .csv с состояние каждого глаза.

Я построил эту Последовательную модель:

num_filters = 8
filter_size = 3
pool_size = 2

model = Sequential([
  Conv2D(num_filters, filter_size, input_shape=(90, 90, 1)),
  MaxPooling2D(pool_size=pool_size),
  Flatten(),
  Dense(16, activation='relu'),
  Dense(2, activation='sigmoid'), # Two classes. one for "open" and another one for "closed"
])

Составление модели.

model.compile(
    'adam',
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

Наконец, я сопоставил все данные со следующим:

model.fit(
  train_images,
  to_categorical(train_labels),
  epochs=3,
  validation_data=(test_images, to_categorical(test_labels)),
)

Результат колеблется около 50%, и я не понимаю почему.

1 Ответ

1 голос
/ 18 июня 2020

Ваша текущая модель по существу имеет один сверточный слой. То есть num_filters сверточные фильтры (которые в данном случае представляют собой массивы 3 x 3) определены и подходят так, что, когда они свертываются с изображением, они создают функции, которые являются максимально различимыми между классами. Затем вы выполняете maxpooling, чтобы немного уменьшить размер выходных характеристик CNN перед переходом к 2 плотным слоям.

Я бы начал с того, что одного сверточного слоя почти наверняка недостаточно, особенно с фильтрами 3x3. По сути, с одним сверточным слоем наиболее значимая информация, которую вы можете получить, - это края или линии. Эти функции лишь незначительно более полезны для аппроксиматора функции (то есть для ваших полностью подключенных слоев), чем необработанные значения интенсивности пикселей, потому что они по-прежнему имеют чрезвычайно высокую степень изменчивости как внутри класса, так и между классами. Учтите, что сдвиг изображения глаза на 2 пикселя влево приведет к совершенно другим значениям, выводимым из вашей однослойной CNN. Вы хотите, чтобы выходные данные вашей CNN были инвариантными к масштабированию, вращению, освещению и т. Д. c.

На практике это означает, что вам понадобится больше сверточных слоев. Относительно простой VGG net имеет как минимум 14 сверточных слоев, а современные сети на основе остаточных слоев часто имеют более 100 сверточных слоев. Попробуйте написать процедуру для последовательного определения более сложных сетей, пока не начнете замечать прирост производительности.

В качестве второстепенного пункта, как правило, вы не хотите использовать функцию активации sigmoid() на выходных данных последнего слоя во время обучения. Это сглаживает градиенты и значительно замедляет обратное распространение ваших потерь. На самом деле вас не волнует, что выходные значения находятся между 0 и 1, вас волнуют только их относительные величины. Обычной практикой является использование кросс-энтропийной потери, которая сочетает в себе логарифмическую функцию softmax (градиент более стабильный, чем нормальный softmax) и потерю отрицательной логарифмической вероятности, как вы уже сделали. Таким образом, поскольку часть log softmax преобразует выходные значения в желаемый диапазон, нет необходимости использовать функцию активации сигмоида.

...