1

顔の目、鼻先、口の領域を識別するために、2 つの lmdb 入力を使用しています。データ lmdb の次元はNx3x HxWですが、ラベル lmdb の次元はNx1x H/4x W/4 です。ラベル イメージは、すべて 0 に初期化された opencv Mat で番号 1 ~ 4 を使用して領域をマスキングすることによって作成されます (つまり、合計 5 つのラベルがあり、0 が背景ラベルです)。ネットに 2 つのプーリング レイヤーがあるため、対応する画像の幅と高さが 1/4 になるようにラベル画像を縮小しました。このダウンスケーリングにより、ラベル イメージの次元が最後の畳み込み層の出力と一致することが保証されます。

私の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 つの画像は 4 つの領域すべてが強調表示されているため、ほとんど同じように見えます。

5 つの出力チャネルの視覚化 (強度は青から赤に増加):
クリックして画像を表示

元の画像 (同心円は、各チャネルの最高強度を示しています。他と区別するために大きいものもあります。背景以外でわかるように、残りのチャネルは、ほぼ同じ口領域で最も高いアクティベーションを持っていますが、そうではありません。 )
クリックして画像を表示

誰かが私が犯した間違いを見つけるのを手伝ってくれませんか?

ありがとう。

4

1 に答える 1