Я использую два входа lmdb для идентификации глаз, носетипов и областей рта лица. Данные lmdb имеют размерность N
x3x H
x W
, в то время как метка lmdb имеет размерность N
x1x H
/4x W
/4. Изображение метки создается с помощью маскирования областей с использованием чисел 1-4 на opencv Mat, который был инициализирован как все 0s (так что в общей сложности есть 5 меток с 0, являющимся фоновой меткой). Я уменьшил изображение метки до 1/4 по ширине и высоте соответствующего изображения, потому что у меня есть 2 слоя объединения в моей сети. Это масштабирование гарантирует, что размер изображения метки будет соответствовать выходу последнего слоя свертки.caffe multi-label training с lmdb для классических областей лица
Мой train_val.prototxt:
name: "facial_keypoints"
layer {
name: "images"
type: "Data"
top: "images"
include {
phase: TRAIN
}
transform_param {
mean_file: "../mean.binaryproto"
}
data_param {
source: "../train_lmdb"
batch_size: 100
backend: LMDB
}
}
layer {
name: "labels"
type: "Data"
top: "labels"
include {
phase: TRAIN
}
data_param {
source: "../train_label_lmdb"
batch_size: 100
backend: LMDB
}
}
layer {
name: "images"
type: "Data"
top: "images"
include {
phase: TEST
}
transform_param {
mean_file: "../mean.binaryproto"
}
data_param {
source: "../test_lmdb"
batch_size: 100
backend: LMDB
}
}
layer {
name: "labels"
type: "Data"
top: "labels"
include {
phase: TEST
}
data_param {
source: "../test_label_lmdb"
batch_size: 100
backend: LMDB
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "images"
top: "conv1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 32
pad: 2
kernel_size: 5
stride: 1
weight_filler {
type: "gaussian"
std: 0.0001
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "pool1"
top: "pool1"
}
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 64
pad: 2
kernel_size: 5
stride: 1
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu2"
type: "ReLU"
bottom: "conv2"
top: "conv2"
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2"
top: "pool2"
pooling_param {
pool: AVE
kernel_size: 3
stride: 2
}
}
layer {
name: "conv_last"
type: "Convolution"
bottom: "pool2"
top: "conv_last"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 5
pad: 2
kernel_size: 5
stride: 1
weight_filler {
#type: "xavier"
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu2"
type: "ReLU"
bottom: "conv_last"
top: "conv_last"
}
layer {
name: "accuracy"
type: "Accuracy"
bottom: "conv_last"
bottom: "labels"
top: "accuracy"
include {
phase: TEST
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "conv_last"
bottom: "labels"
top: "loss"
}
В последнем свертке слоя я установил размер выходного быть 5, потому что у меня есть 5 классов надписей. Обучение сходится с окончательной потерей примерно на 0,3 и точностью 0,9 (хотя некоторые источники полагают, что эта точность неверно измерена для нескольких лабилей). При использовании обученной модели выходной слой правильно создает прямоугольник размером 1x5x H
/4x W
/4, который мне удалось отобразить как 5 отдельных одноканальных изображений. Однако, хотя первое изображение правильно освещает фоновые пиксели, оставшиеся 4 изображения выглядят почти одинаково со всеми выделенными четырьмя регионами.
визуализация 5 выходных каналов (интенсивность возрастает от синего до красного):
оригинал изображения (концентрические круги маркирует самую высокую интенсивность каждого канала некоторые больше просто отличить от других, как вы можете.. видеть, чем фон, остальные каналы имеют высокие активаций почти на той же области рта, которые не должны быть так.)
Может кто-то помочь мне определить ошибку, которую я сделал?
Спасибо.
Вы используете слой «Softmax» при запуске обученной модели на новые изображения лица? – Shai
привет @Shai, да, я использовал Softmax при работе обученной модели, это правильно? – projectcs2103t
(1) Если вы тренируетесь с помощью 'SoftmaxWithLoss', вы должны иметь' Softmax' в прототипе развертывания. Итак, в этом отношении вы правы. (2) Однако, если вы смотрите на вывод softmax, как все 4 метки «подсвечиваются» для одних и тех же пикселей? каковы основные вероятности? Возможно ли, что ваша модель только учится отличать фон? Возможно ли, что у вас есть 90% фона в ваших учебных изображениях? В этом случае постоянный вывод «фона» даст вам точность в 90% ... – Shai