Вопрос или проблема
Я имею около 43 различных категорий изображений дорожных знаков. Если я использую небольшие данные из 3 категорий, максимальная точность, которую я получаю, составляет около 65%, и я пробовал много различных значений слоев, а также функции потерь и оптимизаторы. Когда я использую полный набор данных, я получаю только около 5% точности. Пожалуйста, дайте некоторые советы по повышению точности. Скажите, нужно ли мне добавлять больше слоев, и если у кого-то есть хороший пример где-либо, пожалуйста, предоставьте ссылку.
Добавление большего количества изображений в обучающий набор — один из способов увеличить точность. Вы также можете использовать метод передачи обучения, т.е. использовать слои, обученные на более крупном наборе данных, если вы классифицируете общие вещи, такие как животные, которые имеют сети, уже обученные, такие как ResNet50.
Когда у вас будет достаточно изображений, при которых точность больше не будет расти, вы можете попробовать добавить больше слоев, чередуя сверточные слои и слои ReLu. Если вы тренируете модель в течение многих эпох, и модель начинает переобучаться, т.е. точность обучающего набора продолжает расти, а точность тестового набора снижается, вы можете добавить слои, которые уменьшают переобучение, такие как слой Dropout. Вам сначала нужно заставить модель переобучиться, а затем попытаться снизить переобучение.
Если у вас недостаточно обучающих данных, вы также можете сделать аугментацию, т.е. добавить повернутые, сдвинутые и перевернутые изображения в обучающий набор.
Проблема с дорожными знаками заключается в том, что если вы классифицируете изображения с также пейзажем, а не только обрезанными дорожными знаками, вы столкнетесь с проблемами. Вам также следует обнаружить дорожные знаки (YOLO v3 может быть использован как передача обучения), а не просто классифицировать их.
Вот еще один хороший пример классификации дорожных знаков с использованием передачи обучения на Kaggle: https://www.kaggle.com/valentynsichkar/traffic-signs-classification-with-cnn
Чтобы улучшить точность, сначала нужно понять текущие проблемы. Не заглядывая в набор данных, я предполагаю, что возникают следующие проблемы:
1) Ваша нейронная сеть слишком проста по своей структуре.
2) Количество изображений довольно мало.
3) Количество изображений по классам не сбалансировано.
Как только эти проблемы будут хорошо поняты, у вас появится шанс повысить точность.
Давайте обсудим эти проблемы подробнее.
Проблема 1) (Ваша нейронная сеть слишком проста по своей структуре):
Ваша определенная сеть является прямой сверточной нейронной сетью (CNN). Она применяет 32 различных свертки, за которыми следует функция relu к входному изображению. В результате вы получаете 32 так называемых карты признаков. Интерпретация состоит в том, что каждая карта признаков привлекается к некоторому признаку изображения, который необходим для выполнения задачи классификации. Например, одна такая свертка может соответствовать фильтру Превитта, который выводит горизонтальные или вертикальные края, присутствующие на изображении. Другая карта признаков может соответствовать обнаружению круглых углов, дуг и т. д. Финальный полностью связанный слой затем классифицирует изображение на основе этих сгенерированных признаков.
В глубокой свёрточной нейронной сети (CNN) было замечено, что карты признаков на ранних слоях соответствуют низкоуровневым признакам (углы, линии и т. д.), в то время как карты признаков на более позднем слое соответствуют высокоуровневым признакам (композиции низкоуровневых признаков, например, квадраты, круги, лица и т. д.), так как каждая свертка применяется к “изображению”, созданному предыдущим слоем (которое не является входным изображением, а является картой признаков). Соответственно, необходимо иметь несколько слоев, чтобы достичь этой иерархической конструкции признаков, что оказалось очень эффективным (и похоже на то, как работает человеческий мозг в некоторых областях).
Таким образом, одним из направлений для повышения точности является добавление большего количества слоев сверток (и пуллингов). Хотя это уже оказалось достаточным для многих задач, чтобы достичь очень высокой точности, это, вероятно, не будет достаточным в вашем случае, из-за проблемы 2).
Проблема 2) Количество изображений довольно мало:
Теоретически, если вы используете глубокую CNN, должны быть некоторые веса, которые обеспечивают очень хорошие точности. Это, вероятно, не сработает на практике в вашем случае, в основном из-за:
– все известные методы оптимизации, которые используются для получения (обучения) весов CNN, не обеспечивают глобальное оптимальное решение.
– даже в случае, если у нас есть глобальное оптимальное решение и даже если у нас есть 100% точность на обучающем наборе, это не означает, что CNN хорошо работает на невидимых изображениях.
Скорее всего, вы получите веса, которые приводят к плохим тестовым точностям, даже если вы получите правильные классификации на обучающем наборе. Главное — причина в том, что весьма вероятно, что выученные веса не соответствуют правдоподобным “объяснениям” для общей задачи (классификации дорожных знаков), а являются “краткими путями”.
Пример: предположим, что все изображения знака “Стоп” были сняты с помощью камеры A, а все изображения знака “Держитесь правее” были сняты с помощью камеры B. Теперь, если сенсор камеры A имеет некоторый дефект, например, центральный пиксель всегда черный, оптимизация весов приведет к классификации знака “Стоп”, глядя на центральный пиксель. Тем не менее, как только у вас будет изображение знака “Стоп” в тестовом наборе, снятое с другой камеры, это приведет к неверной классификации.
В общем, если вы используете глубокую CNN, есть много переменных, которые нужно оптимизировать из обучающих данных (среди прочего, веса ядра сверток). Чтобы избежать классификаций, основанных на неправдоподобных рассуждениях, крайне важно иметь много обучающих изображений, чтобы не было возможных “кратких путей”. В примере было бы важно взять изображения с разных камер, чтобы, надеюсь, “объяснения” или признаки, изученные CNN, не были бы некоторыми специальными характеристиками обучающих данных, а сосредоточились на правдоподобной модели (дорожный знак — это восьмиугольник с красным фоном и текстом…).
В случае, если у вас недостаточно обучающих данных, одним из вариантов является использование передачи обучения, т.е. мы используем предварительно обученную модель CNN (обученную на другой задаче, но на огромном наборе данных), таким образом, признаки на ранних слоях привлекаются к низкоуровневым признакам. Затем вы используете обучение только для адаптации высокоуровневых признаков к вашей конкретной задаче классификации. Это менее подвержено “кратким путям”, так как в ранних слоях уже есть значимые признаки, которые передаются через сеть.
Другим вариантом является использование другой модели машинного обучения, например, Random Forest, которая не требует так много обучающих образцов, так как признаки не изучаются. В этом случае признаки должны быть определены или изучены другим способом.
Проблема 3) Существует несколько способов обработки дисбаланса классов для Random Forest и нейронной сети. Большинство из них влияет на то, как вы выбираете ваши данные.
Ответ или решение
Для улучшения точности модели распознавания дорожных знаков, описанной в вашем коде, необходимо учитывать несколько ключевых аспектов. Давайте рассмотрим их по порядку.
1. Структура нейросети
Проблема: У вас довольно простая архитектура нейронной сети. Ваша модель состоит из одного свертки и одного полносоединённого слоя. Глубина сети важна для извлечения иерархических функций из изображений.
Решение: Увеличьте количество свёрточных слоёв и используйте слои подвыборки (max pooling) после каждого свёрточного слоя. Например:
def get_model():
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(IMG_WIDTH, IMG_HEIGHT, 3)),
tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
tf.keras.layers.Conv2D(128, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(256, activation='relu'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(NUM_CATEGORIES, activation='softmax')
])
model.compile(optimizer='Nadam', loss='categorical_crossentropy', metrics=['accuracy'])
return model
2. Объём данных
Проблема: Небольшое количество изображений может вызвать переобучение модели. Это особенно важно, если у вас несбалансированный набор данных по категориям.
Решение:
- Попробуйте использовать аугментацию данных, чтобы увеличить объём обучающего набора. Это может включать повороты, сдвиги, изменение яркости и отражение изображений.
- Пример аугментации данных с использованием Keras:
from tensorflow.keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
rotation_range=15,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.1,
zoom_range=0.1,
horizontal_flip=True,
fill_mode='nearest')
# Используйте fit с генератором данных
model.fit(datagen.flow(x_train, y_train, batch_size=32), epochs=EPOCHS)
3. Передача обучения
Используйте transfer learning. Это означает, что вы можете начать с предобученной модели, такой как ResNet50 или VGG16, и адаптировать её к вашей задаче. Эти модели обучены на большом наборе данных, что позволяет им извлекать полезные характеристики из изображений.
Пример:
from tensorflow.keras.applications import VGG16
base_model = VGG16(weights='imagenet', include_top=False, input_shape=(IMG_WIDTH, IMG_HEIGHT, 3))
base_model.trainable = False # Заморозить базовую модель
model = tf.keras.models.Sequential([
base_model,
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(NUM_CATEGORIES, activation='softmax')
])
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=EPOCHS)
4. Балансировка классов
Проблема: Если данные по категориям несбалансированы, это может негативно сказаться на точности.
Решение: Используйте техники балансировки классов, такие как oversampling (увеличение числа примеров меньшинств) или undersampling (уменьшение числа примеров большинства), чтобы создать более сбалансированный набор данных.
5. Настройка гиперпараметров
Экспериментируйте с гиперпараметрами таких как скорость обучения, размер батча и количество эпох.
Заключение
Улучшить точность вашей модели можно с помощью комбинирования всех вышеперечисленных методов. Разработка качественной модели требует времени и экспериментов, поэтому не бойтесь пробовать разные архитектуры и настройки. В конечном счете, чем больше качественных данных вы сможете собрать, тем лучше сеть сможет обобщать на новых данных.