源码看的是基于keras实现的版本,代码在这里。CRFasRNN把fcn作为骨干网络,然后把fcn的输出作为CRF的二元势的初始化和一元势,前面fcn的部分不再赘述,文章中提出的CRFasRNN作为单独一层用TensorFlow实现,使用起来很简单:
output = CrfRnnLayer(image_dims=(height, weight),
num_classes=21,
theta_alpha=160.,
theta_beta=3.,
theta_gamma=3.,
num_iterations=10,
name='crfrnn')([upscore, img_input])
高斯核的参数theta_alpha
,theta_beta
,theta_gamma
作为超参数直接给出,没有参与训练。
CrfRnnLayer
的定义在crfrnn_layer.py
中,继承了layer
类,其中,build
方法通过add_weight
函数定义了该层可以训练的参数:
def build(self, input_shape):
# Weights of the spatial kernel
self.spatial_ker_weights = self.add_weight(name='spatial_ker_weights',
shape=(self.num_classes, self.num_classes),
initializer=_diagonal_initializer,
trainable=True)
# Weights of the bilateral kernel
self.bilateral_ker_weights = self.add_weight(name='bilateral_ker_weights',
shape=(self.num_classes, self.num_classes),
initializer=_diagonal_initializer,
trainable=True)
# Compatibility matrix
self.compatibility_matrix = self.add_weight(name='compatibility_matrix',
shape=(self.num_classes, self.num_classes),
initializer=_potts_model_initializer,
trainable=True)
super(CrfRnnLayer, self).build(input_shape)
其中,spatial_ker_weights
表示spatial kernel的权重,bilateral_ker_weights
表示bilateral kernel的权重 compatibility_matrix
表示相似度矩阵。
4. A Mean-field Iteration as a Stack of CNN Layers
将DenseCRF变分推断的迭代求解过程表示成RNN的形式,方便和CNN骨干网络共同进行参数更新。要学习的参数是:Gaussian kernels的参数,label compatibility function等等。使用随机梯度下降学习参数。
4.1. Initialization
Q i ( l ) ← 1 Z i exp ( U i ( l ) ) for all i Q_{i}(l) \leftarrow \frac{1}{Z_{i}} \exp \left(U_{i}(l)\right) \text { for all } i Qi(l)←Zi1exp(Ui(l)) for all i
CRF的一元势的初始化由CNN网络的输出结果直接给出: Q i ( l ) ← 1 Z i exp ( U i ( l ) ) Q_{i}(l) \leftarrow \frac{1}{Z_{i}} \exp \left(U_{i}(l)\right) Qi(l)←Zi1exp(Ui(l)),其中 Z i = ∑ l exp ( U i ( l ) ) Z_{i}=\sum_{l} \exp \left(U_{i}(l)\right) Zi=∑lexp(Ui(l)