Керас CNN переоснащение для более чем четырех классов - PullRequest
1 голос
/ 12 мая 2019

Я пытаюсь обучить классификатор на Google QuickDraw рисунках с использованием Керас :

import numpy as np
from tensorflow.keras.layers import Conv2D, Dense, Flatten, MaxPooling2D
from tensorflow.keras.models import Sequential

model = Sequential()

model.add(Conv2D(filters=32, kernel_size=5, data_format="channels_last", activation="relu", input_shape=(28, 28, 1)))
model.add(MaxPooling2D(data_format="channels_last"))
model.add(Conv2D(filters=16, kernel_size=3, data_format="channels_last", activation="relu"))
model.add(MaxPooling2D(data_format="channels_last"))

model.add(Flatten(data_format="channels_last"))

model.add(Dense(units=128, activation="relu"))
model.add(Dense(units=64, activation="relu"))
model.add(Dense(units=4, activation="softmax"))

model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])

x = np.load("./x.npy")
y = np.load("./y.npy")

model.fit(x=x, y=y, batch_size=100, epochs=40, validation_split=0.2)

Входные данные представляют собой массив 4d с 12000 нормализованных изображений(28 х 28 х 1) в классе.Выходные данные - это массив из одного вектора с горячим кодированием.

Если я обучу эту модель четырем классам, она даст убедительные результаты:

loss 4 classes accuracy 4 classes

(красный - данные об обучении, синий - данные проверки)

Я знаю, что модель слегка перегружена.Однако я хочу сохранить архитектуру как можно более простой, поэтому я согласился с этим.

Моя проблема в том, что, как только я добавляю только один произвольный класс, модель начинает чрезмерно подходить для модели:

loss 5 classes accuracy 5 classes

Я пробовал много разных вещей, чтобы предотвратить его переоснащение, таких как нормализация партии, выпадение, регуляризаторы ядра, много других данных обучения иразных размеров партий, ни один из которых не вызвал какого-либо значительного улучшения.

В чем может быть причина, почему мой CNN так сильно перезаряжается?


РЕДАКТИРОВАТЬ: Этокод, который я использовал для создания x.npy и y.npy:

import numpy as np

from tensorflow.keras.utils import to_categorical

files = ['cat.npy', 'dog.npy', 'apple.npy', 'banana.npy', 'flower.npy']

SAMPLES = 12000

x = np.concatenate([np.load(f'./data/{f}')[:SAMPLES] for f in files]) / 255.0
y = np.concatenate([np.full(SAMPLES, i) for i in range(len(files))])

# (samples, rows, cols, channels)
x = x.reshape(x.shape[0], 28, 28, 1).astype('float32')
y = to_categorical(y)

np.save('./x.npy', x)
np.save('./y.npy', y)

Файлы .npy поступают из здесь .

1 Ответ

3 голосов
/ 13 мая 2019

Проблема заключается в том, как выполняется разделение данных.Обратите внимание, что есть 5 классов, и вы делаете 0.2 разделение проверки.По умолчанию нет тасования, и в вашем коде вы вводите данные в последовательном порядке.Что это означает:

  • Учебные данные целиком состоят из 4 классов: «cat.npy», «dog.npy», «apple.npy», «banana.npy».Это 0.8 обучающий сплит.
  • Тестовые данные это 'flower.npy'.Это ваш 0.2 разделение проверки.Модель никогда не обучалась этому, поэтому она получает ужасную точность.

Такие результаты возможны только благодаря тому, что validation_split=0.2, поэтому вы приближаетесь к идеальному разделению классов.

Решение

x = np.load("./x.npy")
y = np.load("./y.npy")

# Shuffle the data!
p = np.random.permutation(len(x))
x = x[p]
y = y[p]

model.fit(x=x, y=y, batch_size=100, epochs=40, validation_split=0.2)

Если моя гипотеза верна, установка validation_split на, например, 0.5 также должна дать вам гораздо лучшие результаты (хотя это нераствор).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...