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

1

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

  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'
Теги:
machine-learning
keras
cross-entropy

2 ответа

3
Лучший ответ

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

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

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

  • 0
    Спасибо, это имеет смысл. Я запускаю код и отмечаю как отвеченный, как только я проверил, что это была проблема!
2

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню