Классификатор изображения стрелки CNN на стрелках различной формы - PullRequest
0 голосов
/ 07 декабря 2018

Я использую Keras с Tensorflow для классификации нормализованного изображения стрелки в оттенках серого 60x60 по 4 категориям: его ориентация: вверх, вниз, влево, вправо.Я создал набор данных из ~ 1800 изображений, почти одинаково распределенных по указанным категориям.

Однако существует проблема с классификацией.Из источника, в котором я создал набор данных, есть два типа стрелок: форма стрелки 1, enter image description here

и форма стрелки 2. enter image description here

Точность нормальна для стрелок, имеющих форму 1 (точность подтверждения ~ 70%), но для стрелок, подобных цифре 2, ужасна.

Я просмотрел свой набор данных иоколо 90% изображений набора данных имеют форму стрелки 1.

Означает ли это, что отсутствие данных для перемещения для формы стрелки 2 является причиной того, что он не может классифицировать их так же, как форму 1, и, следовательно, увеличивает набор данныхдля формы 2 решить эту проблему?

Если это правда, не означает ли это, что моя модель не удалось обобщить?

Кроме того, если цвета стрелок инвертированы, будет ли сеть подвержена влияниюэто?

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

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import os
from random import shuffle
import glob


train_dir = "images\\cropped\\traindata"
test_dir = "images\\cropped\\testdata"
MODEL_NAME = "ARROWS.model"

img_size = 60


# 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
from keras.layers import Dropout
from keras.layers import Activation
from keras.layers import BatchNormalization
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import adam
from keras.callbacks import TensorBoard
from keras import backend as K

from tensorflow import Session, ConfigProto, GPUOptions
gpuoptions = GPUOptions(allow_growth=True)
session = Session(config=ConfigProto(gpu_options=gpuoptions))
K.set_session(session)
classifier = Sequential()

classifier.add(Conv2D(32, (3,3), input_shape=(img_size, img_size, 1)))
classifier.add(BatchNormalization())
classifier.add(Activation("relu"))

classifier.add(Conv2D(32, (3,3)))
classifier.add(BatchNormalization())
classifier.add(Activation("relu"))
classifier.add(MaxPooling2D(pool_size=(2, 2)))
classifier.add(Dropout(0.25))
#classifier.add(Dropout(0.25))

classifier.add(Conv2D(64, (3,3), padding='same'))
classifier.add(BatchNormalization())
classifier.add(Activation("relu"))
classifier.add(MaxPooling2D(pool_size=(2, 2)))
classifier.add(Dropout(0.25))
#classifier.add(Dropout(0.25))

classifier.add(Flatten())
classifier.add(Dense(128))
classifier.add(BatchNormalization())
classifier.add(Activation("relu"))
classifier.add(Dropout(0.5))


classifier.add(Dense(4))
classifier.add(BatchNormalization())
classifier.add(Activation("softmax"))


classifier.compile(optimizer = adam(lr=1e-6), loss = 'categorical_crossentropy', metrics = ['accuracy'])

train_datagen = ImageDataGenerator(rotation_range=12)

test_datagen = ImageDataGenerator(rotation_range=12)

training_set = train_datagen.flow_from_directory('images/cropped/traindata',
                                                 color_mode="grayscale",
                                                 target_size = (img_size, img_size),
                                                 batch_size = 32,
                                                 class_mode = 'categorical', shuffle=True)

test_set = test_datagen.flow_from_directory('images/cropped/testdata',
                                            color_mode="grayscale",
                                            target_size = (img_size, img_size),
                                            batch_size = 32,
                                            class_mode = 'categorical', shuffle=True)

with open("class_indices.txt", "w") as indices_fine:  # Log debug data to file
    indices_fine.write(str(classifier.summary()))
    indices_fine.write("\n")
    indices_fine.write("training_set indices:\n"+str(training_set.class_indices))
    indices_fine.write("test_set indices:\n"+str(test_set.class_indices))


tbCallBack = TensorBoard(log_dir='./log', histogram_freq=0, write_graph=True, write_images=True)
classifier.fit_generator(training_set,steps_per_epoch = 8000,epochs = 15,validation_data = test_set,validation_steps = 2000, shuffle=True, callbacks=[tbCallBack])

classifier.save("arrow_classifier_keras_gray.h5")

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

Только представьте, что ваше первое изображение - крошечный кот, а второе - толстый кот, как Гарфилд.Распределение кошек - это то, что мы не можем изменить, но мы должны обнаружить всех кошек (даже когда кошки перевернуты или распылены в розовом).

Что бы я сделал, например, если бы у меня было 1000 крошечных кошек, я мог бы отфильтровать некоторые изображения, добавить некоторые искажения и эффект, чтобы увеличить тренировочный набор.Это называется увеличением данных.

Вам не нужно для каждой цели делать количество изображений толстых кошек равным количеству изображений крошечных кошек, если в конце вы хорошо их узнаете и обучили свой классификатор изображений, скажем, ~ 98%точность в этом наборе данных.

Важно проверить.

ПРИМЕЧАНИЕ. CNN должен хорошо распознавать изображения с инвертированными цветами.Это потому, что они используют технику свертки.

0 голосов
/ 07 декабря 2018

Означает ли это, что отсутствие данных для преобразования для формы стрелки 2 является причиной того, что она не может классифицировать их так же, как и форму 1, и, следовательно, увеличение набора данных для формы 2 решает эту проблему?

Распределение вашего набора данных очень важно и может привести к смещению в сторону определенного класса и не работать так, как вы ожидаете.В вашем случае число случаев shape 2 намного меньше, чем ваше shape 1 , поэтому в вашей модели глубокого обучения возникает смещение для предположения, что все стрелки вниз должны быть похожиформа 1, а не форма 2. Решение?Вы уже знаете ответ: Увеличение набора данных для формы 2 или делает форму 1 и форму 2 равномерно распределенными в классе стрелок вниз .

Если true,разве это не означает, что моя модель не смогла обобщить?

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

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