Эффективный способ узнать, относится ли изображение к набору данных, которое использовалось для обучения сверточной нейронной сети
В настоящее время я использую методику 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)
Из приведенного выше кода я заметил, что когда у нас есть очень нерелевантное изображение, количество активированных нейронов больше, чем для изображений, которые содержат растения:
- Для изображений, которые использовались для обучения модели, количество активированных нейронов 19%-23%
- Для изображений, которые содержат неизвестные виды растений 20%-26%
- Для нерелевантных изображений 24%-28%
Это не очень хорошая функция, чтобы понять, пересекаются ли изображения, относящиеся к процентным значениям.
Итак, есть ли хороший способ решить эту проблему?
1 ответ
Благодаря идее Фераса в комментарии выше. После нескольких испытаний я нашел оптимальное решение, позволяющее решить эту проблему с точностью до 99,99%.
Шаги:
- Тренируйте свою модель на наборе данных;
- Сохраните активации (см. Метод выше, как их получить), прогнозируя релевантные и не релевантные изображения, используя обученную модель из предыдущего шага. Вы должны получить активации от предпоследнего слоя. Для VGG16 это последний из двух Dense(4096), для InceptionV3 - дополнительный предпоследний уровень Dense(1024), для resnet50 - дополнительный предпоследний уровень Dense(2048).
- Решите бинарную проблему, используя сохраненные данные активаций. Я пробовал простой плоский NN и логистическую регрессию. Оба были хорошими по точности (плоская NN была немного более точной), но я выбрал Логистическую регрессию, так как она проще, быстрее и потребляет меньше памяти и ЦП / ГП.
Этот процесс следует повторять каждый раз после переобучения вашей модели, поскольку каждый раз, когда конечные веса для CNN различаются, а то, что работало ранее, будет другим в следующий раз.
В результате мы имеем еще одну маленькую модель для решения проблемы.