Во-первых, ваша функция потерь неверна: вы находитесь в настройке классификации нескольких классов и используете функцию потерь, подходящую для регрессии, а не классификации (MSE).
Измените компиляцию нашей моделипо:
model.compile(loss='categorical_crossentropy',
optimizer='SGD',
metrics=['accuracy'])
См. пример Keras MNIST MLP для подтверждения и собственный ответ в Какая функция определяет точность в Keras, когда потеря представляет собой среднеквадратическую ошибку (MSE)? для более подробной информации (хотя здесь у вас фактически есть обратная проблема, то есть потеря регрессии в настройке классификации).
Кроме того, неясно, нормализован ли используемый вами вариант MNIST;если нет, вам следует нормализовать их самостоятельно:
x_train = x_train.values/255
x_test = x_test.values/255
Также не ясно, почему вы запрашиваете слой в 784 единицы, поскольку на самом деле это второй слой вашего NN (первый неявно задается аргументом input_shape
- см. входной слой последовательной модели Keras * (1019 *), и, конечно, ему не нужно содержать одну единицу для каждой из ваших 784 входных функций.
ОБНОВЛЕНИЕ (после комментариев):
Но почему MSE не имеет смысла для классификации?
Это теоретическая проблема, не совсем подходящая для SO;грубо говоря, по той же причине, по которой мы не используем линейную регрессию для классификации - мы используем логистическую регрессию, фактическая разница между этими двумя подходами является именно функцией потерь.Эндрю Нг, в своем популярном курсе машинного обучения в Coursera, хорошо объясняет это - см. Его Лекция 6.1 - Логистическая регрессия |Классификация на Youtube (объяснение начинается в ~ 3:00), а также раздел 4.2. Почему не линейная регрессия [для классификации]? из (настоятельно рекомендуется и свободно доступного) учебника AnВведение в статистическое обучение Хасти, Тибширани и его коллег.
И MSE дает высокую точность, так почему же это не имеет значения?
В наше время,почти что-нибудь , которое вы бросаете в MNIST, будет "работать", что, конечно, ни делает это правильным, ни хорошим подходом для более требовательных наборов данных ...
ОБНОВЛЕНИЕ 2 :
всякий раз, когда я бегу с кроссентропией, точность просто колеблется на уровне ~ 10%
Извините, не могу воспроизвести поведение ... Принимая MLP * MNIST Kerasпример с упрощенной версией вашей модели, а именно:
model = Sequential()
model.add(Dense(784, activation='linear', input_shape=(784,)))
model.add(Dense(50, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer=SGD(),
metrics=['accuracy'])
, мы легко получаем точность ~ 92% только после 5 эпох:
history = model.fit(x_train, y_train,
batch_size=128,
epochs=5,
verbose=1,
validation_data=(x_test, y_test))
Train on 60000 samples, validate on 10000 samples
Epoch 1/10
60000/60000 [==============================] - 4s - loss: 0.8974 - acc: 0.7801 - val_loss: 0.4650 - val_acc: 0.8823
Epoch 2/10
60000/60000 [==============================] - 4s - loss: 0.4236 - acc: 0.8868 - val_loss: 0.3582 - val_acc: 0.9034
Epoch 3/10
60000/60000 [==============================] - 4s - loss: 0.3572 - acc: 0.9009 - val_loss: 0.3228 - val_acc: 0.9099
Epoch 4/10
60000/60000 [==============================] - 4s - loss: 0.3263 - acc: 0.9082 - val_loss: 0.3024 - val_acc: 0.9156
Epoch 5/10
60000/60000 [==============================] - 4s - loss: 0.3061 - acc: 0.9132 - val_loss: 0.2845 - val_acc: 0.9196
Обратите внимание на activation='linear'
первого плотного слоя, что эквивалентно без указания чего-либо , как в вашем случае (как я уже сказал, практически все, что вы бросаете в MNIST, будет "работать") ...
Последний совет: попробуйте изменить модель следующим образом:
model = tf.keras.Sequential()
model.add(layers.Dense(784, activation = 'relu',input_shape=(784,)))
model.add(layers.Dense(h1, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
, чтобы использовать лучший (и по умолчанию ) 'glorot_uniform'
инициализатор, и удалить аргументы kernel_regularizer
(они могутбыть причиной любой проблемы - всегда начать просто!) ...