论文:Weakly-Supervised Unconstrained Action Unit Detection via Latent Feature Domain
源码:https://github.com/ZhiwenShao/ADLD
复现结果:
采用BP4D作为source database,EmotioNet作为dest database训练弱监督(–mode=‘weak’)模型,
在EmotioNet上的测试结果为平均F1是0.331,比论文中的0.368略低,
在BP4D上的测试结果为平均F1是0.629,比论文中的0.610略高。
感受:代码风格很好写得又易读又美观,完全可以根据代码把整个结构和训练过程理解一下画一下,跑整个工作基本上按照步骤走就能直接跑出来,复现过程没有碰上任何困难,感谢作者无私奉献公开代码,敢于公开代码的才是真大佬呀,膜拜~
算法内容和代码整合理解
论文中作者给的算法结构图:
我自己画出来完整的训练过程结构图是这样的:
其中蓝色字母代表输入输出的图片或者特征图,黑色字母代表网络结构块,红色字母代表loss function。虚线部分是全监督(目标数据集图片也提供AU标签的时候)才有的。
代码与上图对应符号信息:
下面从左到右按照我画的这张图和表格来挨着讲这个结构。
训练过程解释:
图上网络结构中所有的相同符号代表同一个网络,参数完全相同的,比如图上 G G G出现了6次,实际上是同一个网络结构。一共有8个网络结构块(上图表格里面第一列的8个符号代表的8个网络)需要训练学习,其中 D f s D_f^s Dfs与 D f t D_f^t Dft具有相同的网络结构,但是是两个网络,不共享参数。
g s g^s gs和 g t g^t gt是输入图片,图片分别是源数据集BP4D和目标数据集EmotioNet的图片,大小为 3 × 176 × 176 3 \times 176 \times 176 3×176×176, s s s是sourse源, t t t是target目标。
E f E_f Ef对输入的图片提取基础特征,得到特征图 x s x^s xs和 x t x^t xt, 大小为 64 × 44 × 44 64 \times 44 \times 44 64×44×44.
E t E_t Et和 F l F_l Fl分别用于提取跟landmark无关的文本特征和landmark特征(t: texture feature, l: landmark-related feature, 姑且这么记)。landmark信息和AU信息是一伙的,绑定在一起了,所以哪个图有landmark信息哪个就有AU信息。生成的特征图 z t ? z_t^? zt? 和 z l ? z_l^? zl? ( ? ? ?代表 t t t或 s s s) 的大小分别是 64 × 44 × 44 64 \times 44 \times 44 64×44×44 和 49 × 44 × 44 49 \times 44 \times 44 49×44×44.
从 x ? x^? x?到 z t ? z_t^? zt? 和 z l ? z_l^? zl?的过程是把特征解耦的过程,目的是把landmark特征隔离出来。 z l ? z_l^? zl? 我们期望它含有landmark信息的,所以用来计算特征点检测的loss L l L_l Ll。 z t ? z_t^? zt?我们期待它不含有landmark信息,所以用一个对抗网络 D l D_l Dl来获取landmark信息,我们希望 E t E_t Et不能获取landmark信息,希望 D l D_l Dl能提取到landmark信息。由此确定landmark对抗学习的loss L a d l L_{ad_l} Ladl。
F a F_a Fa是提取AU信息的网络,这里 F a ( x s ) F_a(x^s) Fa(xs)期望能得到真实的AU信息,所以 F a ( x s ) F_a(x^s) Fa(xs)被用于计算AU检测的loss L a L_a La了。同样地,如果是全监督(–mode=‘full’),那么目标数据集也会提供AU标签,所以 F a ( x t ) F_a(x^t) Fa(xt)也应该被用于计算 L a L_a La。
G G G是生成网络,以 z t ? z_t^? zt? 和 z l ? z_l^? zl?作为输入的生成网络一共跑了4次 G G G,其中有2个属于交叉生成(目的是交换源图和目标图的landmark信息),有2个属于特征重建,图片自身的两种特征合并起来。
我们期望2个重建特征生成网络的输出能完美恢复出原来的信息,由此计算特征重建的loss L r L_r Lr。
对于交叉生成的图,我们期待它能保持原始图片的文本信息,也就是 x ? ~ \tilde{x_?} x?~与 x ? x_? x?一致,所以分别用俩对抗网络 D f s D_f^s Dfs和 D f t D_f^t Dft来学习特征,据此计算对抗学习特征的loss L a d f L_{ad_f} Ladf。 另一方面,我们期望交叉生成确实交换了landmark信息,跟随landmark信息的AU信息也应该交换了,所以从 z t ~ \tilde{z_t} zt~应该可以提取au特征得到相应源图的au信息,也就是要计算au检测的loss L a L_a La,交叉生成图中的landmark信息也能用 F l F_l Fl中再获取出来,所以用来计算landmark的loss F l F_l Fl, 并且,生成的数据重新再拆分一次landmark特征和文本特征并再交叉生成一次,理论上交叉后应该能再把landmark信息换回来,恢复原始数据,这里用于计算两次交叉的loss L c c L_{cc} Lcc。
整个训练过程大概可以视为把源图片和目标图片的landmark特征和文本特征解耦合,交叉再交叉就能恢复。为了确保网络能真的拆分出来landmark信息和文本特征信息,文章设计了一系列的loss函数。
下面详细讲一下文章设计的这几个loss函数
1)au检测的loss:(loss_au,
L
a
L_a
La)
这里的
X
~
T
\tilde{X}^T
X~T是第一次交叉生成的结果,
P
S
P^S
PS是源图
X
S
X^S
XS对应的AU标签,左边代表根据
X
~
T
\tilde{X}^T
X~T和
P
S
P^S
PS计算loss来训练
F
a
F_a
Fa的参数。右边
m
m
m是AU总种类数,在这篇文章中是6,
p
p
p和
p
~
\tilde{p}
p~分别是标签和预测的AU出现概率,
w
j
s
w_j^s
wjs是源图中第j个AU的loss权重,是根据不同AU在源文件中出现的频率计算的,计算方式可参考同一个作者的两一篇文章JAA算法,即:
其中
r
r
r是rate,对应AU出现频率,出现频率越高的AU,在loss计算中的重要性越低。
对于弱监督,
L a L_a La = ( L a ( F a , X ~ T , P S ) (L_a(F_a, \tilde{X}^T, P^S) (La(Fa,X~T,PS) + L a ( F a , X S , P S ) ) × 0.5 L_a(F_a, X^S, P^S) )\times 0.5 La(Fa,XS,PS))×0.5,
也就是说我们期望 x ~ t \tilde{x}^t x~t和 x s x^s xs包含源文件 g s g_s gs的AU信息。
对于强监督,
L a L_a La = ( L a ( F a , X ~ T , P S ) (L_a(F_a, \tilde{X}^T, P^S) (La(Fa,X~T,PS) + L a ( F a , X S , P S ) L_a(F_a, X^S, P^S) La(Fa,XS,PS) + L a ( F a , X ~ S , P T ) L_a(F_a, \tilde{X}^S, P^T) La(Fa,X~S,PT) + L a ( F a , X T , P T ) ) × 0.25 L_a(F_a, X^T, P^T)) \times 0.25 La(Fa,XT,PT))×0.25
代码实现的时候用带权重的BCEloss计算,标签AU信息大小是[N, 6], F a F_a Fa输出结果大小是[N, 6].
2)landmark检测的loss: (loss_land,
L
l
L_l
Ll)
这里
X
T
X^T
XT是目标文件经过特征提取的结果,
Y
T
Y^T
YT代表目标文件的landmark特征标签信息。左边表示根据
X
T
X^T
XT和
Y
T
Y_T
YT训练
F
l
F_l
Fl。右边是计算的方法。右边的
k
k
k是landmark分类,所以最大是
d
2
d_2
d2也就是44*44个分类,n是landmark个数,这里是49。
这里landmark的loss计算作者有一个比较特殊的地方。一般我们认为landmark是回归问题,但是作者把landmark视为分类问题。他是这样转化的:landmark特征提取图原本的大小是[49, 44, 44],作者把49个点的坐标转化为分类,换算方法是 c = x ∗ 44 + y c = x * 44 + y c=x∗44+y, 其中x,y是某个特征点的坐标,所以49个点的坐标实际上分别替换成了一个分类号,该分类号范围是[0,44*44-1]。那么对于每个landmark,预测出来的是一张特征图[44, 44],用softmax操作这[44,44]个点看谁概率最高就认为是这个分类。
L l L_l Ll = ( L l ( F l , X T , Y T ) (L_l(F_l, X^T, Y^T) (Ll(Fl,XT,YT) + L l ( F l , X S , Y S ) L_l(F_l, X^S, Y^S) Ll(Fl,XS,YS) + L l ( F l , X ~ T , Y S ) L_l(F_l, \tilde{X}^T, Y^S) Ll(Fl,X~T,YS) + L l ( F l , X ~ S , Y T ) ) × 0.25 L_l(F_l, \tilde{X}^S, Y^T)) \times 0.25 Ll(Fl,X~S,YT))×0.25
也就是说我们期望 x s x^s xs和融合了 x s x^s xslandmark信息的 x ~ t \tilde{x}^t x~t都包含 x s x^s xs的landmark信息;而 x t x^t xt和融合了 x t x^t xtlandmark信息的 x ~ s \tilde{x}^s x~s都包含 x t x^t xt的landmark信息。
代码实现的时候用CrossEntropyLoss实现。
3)特征重建loss:(loss_self_recons ,
L
r
L_r
Lr)
这个比较容易理解,就是期望特征重建生成的图能恢复出原图,也就是
G
(
z
t
t
,
z
l
t
)
G(z_t^t, z_l^t)
G(ztt,zlt)与
x
t
x^t
xt要一样。
L r L_r Lr = ( L r ( F l , E t , G , X T ) + L r ( F l , E t , G , X S ) ) × 0.5 (L_r(F_l, E_t, G, X^T) + L_r(F_l, E_t, G, X^S)) \times 0.5 (Lr(Fl,Et,G,XT)+Lr(Fl,Et,G,XS))×0.5
代码实现上用L1Loss
4)双交叉生成loss:(loss_gen_cycle ,
L
c
c
L_{cc}
Lcc)
这个也比较容易理解,交换两次信息后理论上我们期望能恢复出原来的信息,也就是
x
^
t
\widehat{x}^t
x
t与
x
t
x^t
xt要一样。
L c c L_{cc} Lcc = ( L c c ( F l , E t , G , X T , X S ) (L_{cc}(F_l, E_t, G, X^T, X^S) (Lcc(Fl,Et,G,XT,XS) + L c c ( F l , E t , G , X S , X T ) ) × 0.5 L_{cc}(F_l, E_t, G, X^S,X^T)) \times 0.5 Lcc(Fl,Et,G,XS,XT))×0.5
代码实现上用L1Loss
5)生成对抗loss : (loss_invar_shape_adaptation与loss_gen_adaptation, L a d l L_{ad_l} Ladl与 L a d f L_{ad_f} Ladf)
这部分因为我没了解过生成对抗网络所以对我来说理解起来最难。
L
a
d
l
L_{ad_l}
Ladl是由下面两个部分组成的:
上面两个式子加起来就是下面的
L
a
d
l
L_{ad_l}
Ladl. 第一个式子代表的含义是训练
D
l
D_l
Dl的时候我们希望它能够提取到检测到landmark信息,所以希望能在正确的地方预测为real_label (也就是1),在错误的地方预测为fake_label(也就是0). 第二个式子代表的含义是训练
E
t
E_t
Et的时候我们希望它提取不到landmark信息,所以就希望它的所有地方预测结果都是随机概率值1/(d^2)。两个合起来就是对landmark的对抗网络loss。
L
a
d
l
L_{ad_l}
Ladl =
(
L
a
d
l
(
E
t
,
D
l
,
X
T
,
Y
T
)
+
L
a
d
l
(
E
t
,
D
l
,
X
S
,
Y
S
)
)
×
0.5
(L_{ad_l}(E_t, D_l, X^T, Y^T) + L_{ad_l}(E_t, D_l, X^S, Y^S)) \times 0.5
(Ladl(Et,Dl,XT,YT)+Ladl(Et,Dl,XS,YS))×0.5
对于
L
a
d
f
L_{ad_f}
Ladf, 我们是希望生成的数据能尽可能保持原始数据的整体信息,所以希望经过
D
f
D_f
Df能得到real_label (也就是1)
L
a
d
f
=
(
L
a
d
f
(
F
l
,
E
t
,
G
,
D
f
t
,
X
T
)
+
L
a
d
f
(
F
l
,
E
t
,
G
,
D
f
s
,
X
S
)
)
×
0.5
L_{ad_f} = (L_{ad_f}(F_l, E_t, G, D_f^t, X^T) + L_{ad_f}(F_l, E_t, G, D_f^s, X^S)) \times 0.5
Ladf=(Ladf(Fl,Et,G,Dft,XT)+Ladf(Fl,Et,G,Dfs,XS))×0.5
代码实现上用MSELoss