Эффективный способ узнать, относится ли изображение к набору данных, которое использовалось для обучения сверточной нейронной сети

В настоящее время я использую методику VGG16 + Keras + Theano для определения классов растений. Это работает просто отлично и дает мне хорошую точность. Но следующая проблема, которую я пытаюсь решить, - это найти способ определить, содержит ли входное изображение растение. Я не хочу иметь еще один классификатор, который будет это делать, потому что это не очень эффективно.

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

from keras import backend as K

model = util.load_model() # VGG16 model
model.load_weights(path_to_weights)

def get_activations(m, layer, X_batch):
    x = [m.layers[0].input, K.learning_phase()]
    y = [m.get_layer(layer).output]
    get_activations = K.function(x, y)
    activations = get_activations([X_batch, 0])

    # trying to get some features from activations
    # to understand how can we identify if an image is relevant
    for l in activations[0]:
        not_nulls = [x for x in l if x > 0]

        # shows percentage of activated neurons
        c1 = float(len(not_nulls)) / len(l)
        n_activated = len(not_nulls)
        print 'c1:{}, n_activated:{}'.format(c1, n_activated)

    return activations

get_activations(model, 'the_latest_layer_name', inputs)

Из приведенного выше кода я заметил, что когда у нас есть очень нерелевантное изображение, количество активированных нейронов больше, чем для изображений, которые содержат растения:

  1. Для изображений, которые использовались для обучения модели, количество активированных нейронов 19%-23%
  2. Для изображений, которые содержат неизвестные виды растений 20%-26%
  3. Для нерелевантных изображений 24%-28%

Это не очень хорошая функция, чтобы понять, пересекаются ли изображения, относящиеся к процентным значениям.

Итак, есть ли хороший способ решить эту проблему?

1 ответ

Благодаря идее Фераса в комментарии выше. После нескольких испытаний я нашел оптимальное решение, позволяющее решить эту проблему с точностью до 99,99%.

Шаги:

  1. Тренируйте свою модель на наборе данных;
  2. Сохраните активации (см. Метод выше, как их получить), прогнозируя релевантные и не релевантные изображения, используя обученную модель из предыдущего шага. Вы должны получить активации от предпоследнего слоя. Для VGG16 это последний из двух Dense(4096), для InceptionV3 - дополнительный предпоследний уровень Dense(1024), для resnet50 - дополнительный предпоследний уровень Dense(2048).
  3. Решите бинарную проблему, используя сохраненные данные активаций. Я пробовал простой плоский NN и логистическую регрессию. Оба были хорошими по точности (плоская NN была немного более точной), но я выбрал Логистическую регрессию, так как она проще, быстрее и потребляет меньше памяти и ЦП / ГП.

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

В результате мы имеем еще одну маленькую модель для решения проблемы.

Другие вопросы по тегам