Точность кераса и фактическая точность точно противоположны друг другу - PullRequest
2 голосов
/ 02 июня 2019

Я изучаю нейронные сети и в настоящее время внедрил классификацию объектов в наборе данных CFAR-10 с использованием библиотеки Keras. Вот мое определение нейронной сети, определенной Keras:

# Define the model and train it
model = Sequential()

model.add(Dense(units = 60, input_dim = 1024, activation = 'relu'))
model.add(Dense(units = 50, activation = 'relu'))
model.add(Dense(units = 60, activation = 'relu'))
model.add(Dense(units = 70, activation = 'relu'))
model.add(Dense(units = 30, activation = 'relu'))
model.add(Dense(units = 10, activation = 'sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

model.fit(X_train, y_train, epochs=50, batch_size=10000)

Итак, у меня есть 1 входной слой с входными размерами 1024 или (1024,) (каждое изображение размером 32 * 32 * 3 сначала преобразуется в оттенки серого, что дает размеры 32 * 32), 5 скрытых слоев и 1 выходной слой, как определено в приведенном выше коде.

Когда я тренирую свою модель более 50 эпох, я получаю точность 0.9 или 90%. Также, когда я оцениваю его, используя набор тестовых данных, я получаю точность прибл. 90%. Вот строка кода, которая оценивает модель:

print (model.evaluate(X_test, y_test))

Это печатает после потери и точности:

[1.611809492111206, 0.8999999761581421]

Но когда я вычисляю точность вручную, делая прогнозы для каждого изображения тестовых данных, я получаю точность около 11% (это почти то же самое, что вероятность случайного прогноза). Вот мой код для вычисления вручную:

wrong = 0

for x, y in zip(X_test, y_test):
  if not (np.argmax(model.predict(x.reshape(1, -1))) == np.argmax(y)):
    wrong += 1

print (wrong)

Это выводит 9002 из 10000 неверных прогнозов. Так чего мне здесь не хватает? Почему обе точности точно противоположны (100 - 89 = 11%) друг от друга? Любое интуитивное объяснение поможет! Спасибо.

EDIT:

Вот мой код, который обрабатывает набор данных:

# Process the training and testing data and make in Neural Network comfortable

# convert given colored image to grayscale
def rgb2gray(rgb):
  return np.dot(rgb, [0.2989, 0.5870, 0.1140])

X_train, y_train, X_test, y_test = [], [], [], []

def process_batch(batch_path, is_test = False):
  batch = unpickle(batch_path)
  imgs = batch[b'data']
  labels = batch[b'labels']


  for img in imgs:
    img = img.reshape(3,32,32).transpose([1, 2, 0])
    img = rgb2gray(img)
    img = img.reshape(1, -1)
    if not is_test:
      X_train.append(img)
    else:
      X_test.append(img)

  for label in labels:
    if not is_test:
      y_train.append(label)
    else:
      y_test.append(label)

process_batch('cifar-10-batches-py/data_batch_1')
process_batch('cifar-10-batches-py/data_batch_2')
process_batch('cifar-10-batches-py/data_batch_3')
process_batch('cifar-10-batches-py/data_batch_4')
process_batch('cifar-10-batches-py/data_batch_5')

process_batch('cifar-10-batches-py/test_batch', True)

number_of_classes = 10
number_of_batches = 5
number_of_test_batch = 1

X_train = np.array(X_train).reshape(meta_data[b'num_cases_per_batch'] * number_of_batches, -1)
print ('Shape of training data: {0}'.format(X_train.shape))

# create labels to one hot format
y_train = np.array(y_train)

y_train = np.eye(number_of_classes)[y_train]
print ('Shape of training labels: {0}'.format(y_train.shape))


# Process testing data

X_test = np.array(X_test).reshape(meta_data[b'num_cases_per_batch'] * number_of_test_batch, -1)
print ('Shape of testing data: {0}'.format(X_test.shape))

# create labels to one hot format
y_test = np.array(y_test)

y_test = np.eye(number_of_classes)[y_test]
print ('Shape of testing labels: {0}'.format(y_test.shape))

1 Ответ

2 голосов
/ 02 июня 2019

Причина, по которой это происходит, связана с функцией потери, которую вы используете. Вы используете двоичную кросс-энтропию, где вы должны использовать категориальную кросс-энтропию в качестве потери. Двоичный файл предназначен только для задачи с двумя метками, но у вас есть 10 меток здесь из-за CIFAR-10.

Когда вы показываете метрику точности, это фактически вводит вас в заблуждение, потому что показывает двоичную производительность классификации. Решение состоит в том, чтобы переобучить вашу модель, выбрав categorical_crossentropy.

В этом посте есть более подробная информация: Keras binary_crossentropy vs категорически_crossentropy производительность?

Связанный - этот пост отвечает на другой вопрос, но, по сути, ответ состоит в том, в чем заключается ваша проблема: Keras: model.evaluate vs model.predict разница в точности в многоклассовой задаче NLP

Редактировать

Вы упомянули, что точность вашей модели колеблется в пределах 10% и не улучшается в ваших комментариях. После изучения вашей записной книжки Colab и перехода к категориальной кросс-энтропии выясняется, что вы не нормализуете свои данные. Поскольку значения пикселей изначально представляют собой 8-разрядное целое число без знака, при создании обучающего набора он переводит значения в значения с плавающей запятой, но из-за динамического диапазона данных вашей нейронной сети трудно усвоить правильные веса. Когда вы пытаетесь обновить весовые коэффициенты, градиенты настолько малы, что обновления практически отсутствуют, и, следовательно, ваша сеть работает как случайный шанс. Решение состоит в том, чтобы просто разделить ваш тренировочный и тестовый набор данных на 255, прежде чем продолжить:

X_train /= 255.0
X_test /= 255.0

Это преобразует ваши данные так, что динамический диапазон масштабируется от [0,255] до [0,1]. Ваша модель будет легче тренироваться из-за меньшего динамического диапазона, который должен помочь градиентам распространяться и не исчезать из-за большего масштаба перед нормализацией. Поскольку в исходной спецификации модели имеется значительное количество плотных слоев, из-за динамического диапазона ваших данных обновления градиента, скорее всего, исчезнут, поэтому изначально производительность низкая.

Когда я запускаю ваш ноутбук, я получаю 37% точности. Это не является неожиданным для CIFAR-10 и только для полностью подключенной / плотной сети. Также, когда вы сейчас запускаете свой ноутбук, точность и доля неправильных примеров совпадают.

Если вы хотите повысить точность, у меня есть пара предложений:

  1. На самом деле включить информацию о цвете. Каждый объект в CIFAR-10 имеет отдельный цветовой профиль, который должен помочь в различении
  2. Добавить сверточные слои. Я не уверен, где вы находитесь в процессе обучения, но сверточные слои помогают в изучении и выделении правильных элементов изображения, чтобы наиболее плотные слои были представлены в плотных слоях, чтобы классификация этих элементов увеличивала точность. Прямо сейчас вы классифицируете необработанные пиксели, что не рекомендуется, учитывая, насколько они могут быть шумными, или из-за того, как могут получаться несвязанные объекты (вращение, перемещение, наклон, масштабирование и т. Д.).
...