Потери Keras неизменно низкие, но точность сначала высокая, а затем падает

Во-первых, мои предположения могут быть ошибочными:

  1. Потеря - это то, насколько далеко от правильного ответа находится каждый обучающий пример (затем делится на количество примеров - своего рода средняя потеря).
  2. Точность - это количество правильных обучающих примеров (если за правильный ответ принимается самый высокий результат, то не имеет значения, будет ли это 0,7, что даст потерю 0,3, он все равно выдает правильный ответ). Это дается в процентах.

На мой взгляд, это означает, что точность обычно будет ближе к 100%, чем потеря будет к 0. Это не то, что я вижу:

10000/10000 [==============================] - 1067s - loss: 0.0408 - acc: 0.9577 - val_loss: 0.0029 - val_acc: 0.9995
Epoch 2/5
10000/10000 [==============================] - 991s - loss: 0.0021 - acc: 0.9997 - val_loss: 1.9070e-07 - val_acc: 1.0000
Epoch 3/5
10000/10000 [==============================] - 990s - loss: 0.0011 - acc: 0.4531 - val_loss: 1.1921e-07 - val_acc: 0.2440

Это 3 эпохи, вторая попытка заставить это работать. Это с train_dategen, имеющим shuffle=True. У меня есть результаты с shuffle=False (сначала я думал, что это может быть проблемой), здесь:

10000/10000 [==============================] - 1168s - loss: 0.0079 - acc: 0.9975 - val_loss: 0.0031 - val_acc: 0.9995
Epoch 2/5
10000/10000 [==============================] - 1053s - loss: 0.0032 - acc: 0.9614 - val_loss: 1.1921e-07 - val_acc: 0.2439
Epoch 3/5
10000/10000 [==============================] - 1029s - loss: 1.1921e-07 - acc: 0.2443 - val_loss: 1.1921e-07 - val_acc: 0.2438
Epoch 4/5
10000/10000 [==============================] - 1017s - loss: 1.1921e-07 - acc: 0.2439 - val_loss: 1.1921e-07 - val_acc: 0.2438
Epoch 5/5
10000/10000 [==============================] - 1041s - loss: 1.1921e-07 - acc: 0.2445 - val_loss: 1.1921e-07 - val_acc: 0.2435

Я использую categorical_crossentropy для проигрыша, так как у меня 3 класса. У меня больше данных, чем нужно (около 178 000 изображений, все классифицированы по 1 из 3 классов).

Я что-то не понимаю, или что-то пошло не так?

Вот мой полный код:

# Importing the Keras libraries and packages
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

# Initialising the CNN
classifier = Sequential()
# Step 1 - Convolution
classifier.add(Conv2D(32, (3, 3), input_shape = (200, 200, 3), activation = 'relu'))
# Step 2 - Pooling
classifier.add(MaxPooling2D(pool_size = (2, 2)))
# Adding a second convolutional layer
classifier.add(Conv2D(32, (3, 3), activation = 'relu'))
classifier.add(MaxPooling2D(pool_size = (2, 2)))
# Step 3 - Flattening
classifier.add(Flatten())
# Step 4 - Full connection
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dense(units = 3, activation = 'sigmoid'))
# Compiling the CNN
classifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])
# Part 2 - Fitting the CNN to the images
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale = 1./255)
test_datagen = ImageDataGenerator(rescale = 1./255)
training_set = train_datagen.flow_from_directory('dataset/training_set',
                target_size = (200, 200),
                batch_size = 64,
                class_mode = 'categorical',
                shuffle=True)

test_set = test_datagen.flow_from_directory('dataset/test_set',
                target_size = (200, 200),
                batch_size = 62,
                class_mode = 'categorical',
                shuffle=True)

classifier.fit_generator(training_set,
                steps_per_epoch = 10000,
                epochs = 5,
                validation_data = test_set,
                validation_steps=1000)

classifier.save("CSGOHeads.h5")
# Part 3 - Making new predictions
import numpy as np
from keras.preprocessing import image
test_image = image.load_img('dataset/single_prediction/1.bmp', target_size = (200, 200))
test_image = image.img_to_array(test_image)
test_image = np.expand_dims(test_image, axis = 0)
result = classifier.predict(test_image)
training_set.class_indices
if result[0][0] == 1:
    prediction = 'head'
else:
    prediction = 'not'

person FraserOfSmeg    schedule 18.06.2018    source источник
comment
Не могли бы вы также опубликовать свой код? Очевидно, что в процессе обучения (при правильной настройке) как значения потерь при валидации, так и потери при обучении уменьшаются, а точность увеличивается до достижения плато (и если вы продолжаете обучение, возможно, через некоторое время значение потерь при валидации начинает увеличиваться, а точность валидации падает, что вызывает -подгонка). Но в вашем случае точность высокая в самом начале, что очень странно и возможный признак бага или ошибки в вашем коде.   -  person today    schedule 18.06.2018
comment
@сегодня я опубликовал весь свой код, дайте мне знать, если что-то неясно (я все еще новичок в python, поэтому он может выглядеть полным беспорядком). Спасибо   -  person FraserOfSmeg    schedule 18.06.2018


Ответы (2)


Поскольку вы классифицируете изображения по одному из 3 классов (т.е. это называется многоклассовой классификацией с одной меткой: существует несколько классов, но каждое изображение имеет только одну метку), вы должны использовать softmax в качестве функции активации последнего слоя вместо использования sigmoid :

classifier.add(Dense(units = 3, activation = 'softmax')) # don't use sigmoid here

Если вы хотите, чтобы я объяснил больше, дайте мне знать, и я обновлю свой ответ.

person today    schedule 18.06.2018
comment
Спасибо, это имеет смысл. Я запущу код и отмечу ответ как ответ, как только проверю, что это была проблема! - person FraserOfSmeg; 19.06.2018

Чтобы дополнить ответ @today, если активация последнего слоя sigmoid, потеря должна быть binary_crossentropy. Это рецепт для проблем классификации с несколькими метками. В противном случае для классификации с одной меткой используйте softmax плюс categorical_crossentropy. Не путайте sigmoid с categorical_crossentropy.

person neurite    schedule 18.06.2018