Точность CNN не меняется в течение нескольких эпох

#python #machine-learning #keras #deep-learning #conv-neural-network

#python #машинное обучение #keras #глубокое обучение #conv-нейронная сеть

Вопрос:

Я пытаюсь создать CNN, который различает черно-белые изображения глаз с симптомами диабетической ретинопатии или без них. Когда я попытался запустить свою модель, точность не улучшилась вообще. Я пытался использовать разные скорости обучения, но это не сработало. Поскольку я впервые выступаю на Си-эн-эн, я думаю, что, возможно, допустил ошибку в другом месте. Если вы видите проблемы в моем коде, пожалуйста, дайте мне знать, я был бы очень признателен за помощь.

 Train on 980 samples, validate on 327 samples
Epoch 1/5
980/980 [==============================] - 777s 792ms/step - loss: 8.1986 - accuracy: 0.4653 - val_loss: 8.8154 - val_accuracy: 0.4251
Epoch 2/5
980/980 [==============================] - 666s 679ms/step - loss: 8.1986 - accuracy: 0.4653 - val_loss: 8.8154 - val_accuracy: 0.4251
Epoch 3/5
980/980 [==============================] - 672s 686ms/step - loss: 8.1986 - accuracy: 0.4653 - val_loss: 8.8154 - val_accuracy: 0.4251
 

Вот мой код:

 DATADIR = "C:\Users.."
CATEGORIES = ["nosymptoms", "symptoms"]
training_data = []
IMG_SIZE = 512
for category in CATEGORIES:
    path = os.path.join(DATADIR, category) #brings us to folder with categories
    class_num = CATEGORIES.index(category)
    for img in os.listdir(path):
        img_array = cv2.imread(os.path.join(path,img), cv2.IMREAD_GRAYSCALE)
        new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE)) #img resized and becomes array
        training_data.append([new_array, class_num]) #classification is appended to image 
 
 import random
random.shuffle(training_data)
for sample in training_data[:10]:
    print(sample[1])#0 is the image array, 1 is the label
X = [] #features set
y = [] #labels
X = np.array(X).reshape(-1, IMG_SIZE, IMG_SIZE, 1)#shape of features (-1 means any), img size, 1 (b/c it is a grayscale) 
#Save data
import pickle
pickle_out = open("X.pickle","wb")
pickle.dump(X, pickle_out)
pickle_out.close()

pickle_out = open("y.pickle","wb")
pickle.dump(y, pickle_out)
pickle_out.close()

X = pickle.load(open("X.pickle", "rb"))
y = pickle.load(open("y.pickle", "rb"))

X = X/255.0
 
 model = Sequential()

model.add(Convolution2D(32, (3,3),input_shape=(X.shape[1:]),activation='relu'))
model.add(Convolution2D(32, (3,3),activation='relu'))
model.add(Convolution2D(32, (3,3),activation='relu'))

model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Flatten())
model.add(Dense(16, activation='relu'))
model.add(Dense(12, activation='relu'))
model.add(Dense(1, activation='softmax'))

from keras.optimizers import SGD
opt = SGD(lr=0.01)
model.compile(loss = "binary_crossentropy", optimizer = opt, metrics=['accuracy'])
print(model.summary())

model.fit(X, y, batch_size = 16, epochs = 5, validation_split=.25)
 

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

1. Можете ли вы обновить свой вопрос несколькими вещами. Во-первых, запустите 15 эпох и опубликуйте результат вместо 3 эпох. Во-вторых, можете ли вы опубликовать, как выглядят X и y?

2. Это происходит потому, что вы используете softmax с одним нейроном, который выдает постоянный вывод, здесь есть сотни вопросов с той же проблемой. Просто измените активацию на сигмовидную.

Ответ №1:

Поскольку у вас есть 2 класса, измените свой последний слой на 2 нейрона

 model = Sequential() 
model.add(Convolution2D(32, (3,3),input_shape=(X.shape[1:]),activation='relu'))
model.add(Convolution2D(32, (3,3),activation='relu'))
model.add(Convolution2D(32, (3,3),activation='relu'))

model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Flatten())
model.add(Dense(16, activation='relu'))
model.add(Dense(12, activation='relu'))
model.add(Dense(2, activation='softmax'))

from keras.optimizers import SGD
opt = SGD(lr=0.01)
model.compile(loss = "categorical_crossentropy", optimizer = opt, metrics=['accuracy'])
print(model.summary())

model.fit(X, y, batch_size = 16, epochs = 5, validation_split=.25)
 

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

1. Для двоичных меток вы можете использовать 1 вывод для 0 или 1, или вы можете использовать 2 для однократных 01 и 10, и это зависит от вашей реализации. проблема не в этом. также для вашего ответа вы должны использовать categorical_crossentropy для loss