Точность модели и потери не улучшаются в CNN - PullRequest
1 голос
/ 29 апреля 2020

Я использую приведенную ниже архитектуру L eNet для обучения моей модели классификации изображений. Я заметил, что оба тренинга, точность оценки не улучшается для каждой итерации. Может ли кто-нибудь из специалистов в этой области объяснить, что могло пойти не так?

тренировочные образцы - 110 изображений, относящихся к 2 классам. проверка - 50 изображений, относящихся к 2 классам.

#LeNet

import keras 
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense

#import dropout class if needed
from keras.layers import Dropout

from keras import regularizers

model = Sequential()
#Layer 1
#Conv Layer 1
model.add(Conv2D(filters = 6, 
                 kernel_size = 5, 
                 strides = 1, 
                 activation = 'relu', 
                 input_shape = (32,32,3)))
#Pooling layer 1
model.add(MaxPooling2D(pool_size = 2, strides = 2))
#Layer 2
#Conv Layer 2
model.add(Conv2D(filters = 16, 
                 kernel_size = 5,
                 strides = 1,
                 activation = 'relu',
                 input_shape = (14,14,6)))
#Pooling Layer 2
model.add(MaxPooling2D(pool_size = 2, strides = 2))
#Flatten
model.add(Flatten())
#Layer 3
#Fully connected layer 1
model.add(Dense(units=128,activation='relu',kernel_initializer='uniform'
                     ,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))
#Layer 4
#Fully connected layer 2
model.add(Dense(units=64,activation='relu',kernel_initializer='uniform'
                     ,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))

#layer 5
#Fully connected layer 3
model.add(Dense(units=64,activation='relu',kernel_initializer='uniform'
                     ,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))

#layer 6
#Fully connected layer 4
model.add(Dense(units=64,activation='relu',kernel_initializer='uniform'
                     ,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))

#Layer 7
#Output Layer
model.add(Dense(units = 2, activation = 'softmax'))
model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])

from keras.preprocessing.image import ImageDataGenerator

#Image Augmentation
train_datagen = ImageDataGenerator(
        rescale=1./255, #rescaling pixel value bw 0 and 1
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)

#Just Feature scaling
test_datagen = ImageDataGenerator(rescale=1./255)

training_set = train_datagen.flow_from_directory(
       '/Dataset/Skin_cancer/training',
        target_size=(32, 32),
        batch_size=32,
        class_mode='categorical')

test_set = test_datagen.flow_from_directory(
        '/Dataset/Skin_cancer/testing',
        target_size=(32, 32),
        batch_size=32,
        class_mode='categorical')

model.fit_generator(
        training_set,
        steps_per_epoch=50,   #number of input (image)
        epochs=25,
        validation_data=test_set,
        validation_steps=10)          # number of training sample

Epoch 1/25
50/50 [==============================] - 52s 1s/step - loss: 0.8568 - accuracy: 0.4963 - val_loss: 0.7004 - val_accuracy: 0.5000
Epoch 2/25
50/50 [==============================] - 50s 1s/step - loss: 0.6940 - accuracy: 0.5000 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 3/25
50/50 [==============================] - 48s 967ms/step - loss: 0.6932 - accuracy: 0.5065 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 4/25
50/50 [==============================] - 50s 1s/step - loss: 0.6932 - accuracy: 0.4824 - val_loss: 0.6933 - val_accuracy: 0.5000
Epoch 5/25
50/50 [==============================] - 49s 974ms/step - loss: 0.6932 - accuracy: 0.4949 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 6/25
50/50 [==============================] - 51s 1s/step - loss: 0.6932 - accuracy: 0.4854 - val_loss: 0.6931 - val_accuracy: 0.5000
Epoch 7/25
50/50 [==============================] - 49s 976ms/step - loss: 0.6931 - accuracy: 0.5015 - val_loss: 0.6918 - val_accuracy: 0.5000
Epoch 8/25
50/50 [==============================] - 51s 1s/step - loss: 0.6932 - accuracy: 0.4986 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 9/25
50/50 [==============================] - 49s 973ms/step - loss: 0.6932 - accuracy: 0.5000 - val_loss: 0.6929 - val_accuracy: 0.5000
Epoch 10/25
50/50 [==============================] - 50s 1s/step - loss: 0.6931 - accuracy: 0.5044 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 11/25
50/50 [==============================] - 49s 976ms/step - loss: 0.6931 - accuracy: 0.5022 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 12/25

Accuracy on each iteration

loss for each iteration

Ответы [ 2 ]

3 голосов
/ 29 апреля 2020

Удалить все kernel_initializer='uniform' аргументы из ваших слоев; здесь ничего не указывайте, по умолчанию инициализатор glorot_uniform настоятельно рекомендуется (а uniform особенно плох).

Как правило, сохраняйте в имейте в виду, что значения по умолчанию для таких довольно продвинутых настроек существуют для вашего удобства, они неявно рекомендуются, и вам лучше не связываться с ними, если у вас нет конкретных c причин для этого и вы точно знаете, что делаете.

В частности, для аргумента kernel_initializer я начал верить, что он причиняет много ненужной боли людям (просто см. здесь для самого последнего примера).

Кроме того, отсев не должен использоваться по умолчанию, особенно в тех случаях, как здесь, где модель, кажется, изо всех сил пытается чему-то научиться; начните без выпадения (закомментируйте соответствующие слои) и добавляйте его обратно, только если вы видите признаки переобучения.

1 голос
/ 05 мая 2020

Самое главное, что вы используете loss = 'categorical_crossentropy', измените его на loss = 'binary_crossentropy', так как у вас есть только 2 класса. А также измените class_mode='categorical' на class_mode='binary' в flow_from_directory.

Как справедливо упомянуто @desertnaut, categorical_crossentropy идет рука об руку с softmax активацией на последнем слое, и если вы изменяете потери на binary_crossentropy, последняя активация также должна быть изменена на sigmoid .

Другие улучшения:

  1. У вас очень ограниченные данные (160 изображений), и вы использовали почти 50% данных в качестве данных проверки.
  2. Когда вы строите модель для классификации изображений, у вас есть только два слоя Conv2D и 4 плотных слоя. Плотные слои добавляют огромное количество весов для изучения. Добавьте еще несколько слоев conv2d и уменьшите Плотный слой.
  3. Установите batch_size = 1 и удалите steps_per_epoch. Поскольку у вас очень мало входных данных, пусть у каждой эпохи будет то же количество шагов, что и у входных записей.
  4. Используйте инициализатор ядра glorot_uniform по умолчанию.
  5. Для дальнейшей настройки вашей модели создайте модель, используя несколько слоев Conv2D, затем слой GlobalAveragePooling2D и слой F C и конечный слой softmax.
  6. Используйте метод увеличения данных, например horizontal_flip, vertical_flip, shear_range, zoom_range ImageDataGenerator, чтобы увеличить количество обучающих и проверочных изображений .

Перемещение комментариев в раздел ответов в соответствии с предложением @desertnaut -

Вопрос - Спасибо! Да, проблема в том, что я решил меньше данных. Еще один вопрос - почему добавление более плотного слоя, чем конвон слоя негативно влияет на модель, есть ли какое-то правило, которому нужно следовать, когда мы решаем, сколько конв и плотного слоя мы будем использовать? - Arun_Ramji_Shanmugam 2 дня a go

Ответ - Чтобы ответить на первую часть вашего вопроса, слой Conv2D поддерживает пространственную информацию об изображении, а вес, который нужно выучить, зависит от размера ядра и шага, упомянутых в слое где плотному слою необходимо выровнять вывод Conv2D и использовать его далее, теряя пространственную информацию. Также плотный слой добавляет большее количество весов, например, 2 плотных слоя из 512 добавляет (512 * 512) = 262144 парам или весов к модели (должен быть изучен моделью). Это означает, что вы должны тренироваться для большего количества эпохи и с хорошими настройками параметров рекламы для изучения этих весов. - Tensorflow Warriors 2 дня a go

Ответ - Чтобы ответить на вторую часть вашего вопроса, используйте систематические c эксперименты, чтобы узнать, что лучше всего подходит для вашего указанного c набора данных. Также это зависит от вычислительной мощности, которую вы держите. Помните, что более глубокие сети всегда лучше, за счет большего объема данных и повышенной сложности обучения. Традиционный подход состоит в том, чтобы искать похожие проблемы и архитектуры глубокого обучения, которые уже были показаны для работы Также у нас есть гибкость в использовании предварительно подготовленных моделей, таких как re snet, vgg и c, использование этих моделей путем замораживания части слоев и обучения на оставшихся слоях. - Tensorflow Warriors 2 дня go

Вопрос - Спасибо за подробный ответ !! Если вас не волнует еще один вопрос - поэтому, когда мы используем уже обученную модель (может быть, несколько слоев), разве не нужно обучаться на тех же входных данных, что и те, с которыми мы будем работать? - Arun_Ramji_Shanmugam вчера

Ответ - Интуиция, лежащая в основе обучения передаче для классификации изображений, состоит в том, что если модель обучается на большом и достаточно общем наборе данных, эта модель будет эффективно служить обобщенной c моделью визуального мира. , Вы можете найти пример обучения передаче с объяснением здесь - tenorflow.org/tutorials/images/transfer_learning. - Tensorflow Warriors вчера

...