Learning to Segment Every Thing解读和Learning to Segment Every Thing算法笔记这两篇博客讲的很好了。
前面我们也讲了,模型的参数相当于 embeding vector包含了类别的appearance information。在box和mask 分支中只有最后一层包含category-specific的参数,是类别专属的,原有的mask rcnn里这两路是独立训练学习的,本文不直接学习mask 分支最后一层的参数,而是通过Weight Transfer学习一个从box分支参数到mask 分支参数的变换。前提的insight就是box和mask最后一层包含category-specific的参数,是类别专属的,算是类别语义信息的embeding,是很相关的,可以通过学习从box变换到mask这边来的。
我们以Mask RCNN(ResNet101-FPN)为例,box分支包含分类和回归,分类部分最后一层,每个类别的cls参数vector维度为1024,回归部分是1024x4=4096,mask分支,输出分辨率是28x28,最后一层每个类别的seg参数vector维度为256(从roialign出来是14141024,然后通过4个conv变成1414256,再加一个deconv到2828256,最后一个11的conv得到score map,这个11卷积的参数就是刚说的seg参数,总共参数是25611*#classes,每个类别的参数就是25611)
我们现在就要加个Weight Transfer,将检测分支的参数cls和box变换到seg,θ是class-agnostic(类别无关的),学习过来的。
就是要学习一个从1024或者4095或者1024+4096维向量到256维向量的变换矩阵
w s e g c = T ( w d e t c ; θ ) w_{\mathrm{seg}}^{c}=\mathcal{T}\left(w_{\mathrm{det}}^{c} ; \theta\right) wsegc=T(wdetc;θ)
# 输入为检测分支的参数,cls或者box或者cls cat box的参数
if (cfg.MRCNN.BBOX2MASK.INCLUDE_CLS_SCORE and
cfg.MRCNN.BBOX2MASK.INCLUDE_BBOX_PRED):
# Subcase a) using cls+box
concat_cls_score_bbox_pred(model)
class_embed = 'cls_score_bbox_pred'
class_embed_dim = 1024 + 4096
elif cfg.MRCNN.BBOX2MASK.INCLUDE_CLS_SCORE:
# Subcase b) using cls
class_embed = 'cls_score_w'
class_embed_dim = 1024
elif cfg.MRCNN.BBOX2MASK.INCLUDE_BBOX_PRED:
# Subcase c) using box; 'bbox_pred_w' need to be flattened
model.net.Reshape(
'bbox_pred_w', ['bbox_pred_w_flat', '_bbox_pred_w_oldshape'],
shape=(model.num_classes, -1))
class_embed = 'bbox_pred_w_flat'
class_embed_dim = 4096
# 变换函数,即需要学习的参数θ,简单的就是一层fc,复杂的话就多加一层fc和激活层等
if (not fc_mask_head_type) or fc_mask_head_type == '1_layer':
raw_mlp_branch = model.FC(
blob_in, 'mask_mlp_logits_raw', dim_in, dim_out,
weight_init=('GaussianFill', {'std': 0.001}),
bias_init=('ConstantFill', {'value': 0.}))
elif fc_mask_head_type == '2_layer':
mlp_l1 = model.FC(
blob_in, 'fc_mask_head_mlp_l1', dim_in, dim_h,
weight_init=('MSRAFill', {}),
bias_init=('ConstantFill', {'value': 0.}))
model.net.Relu(mlp_l1, mlp_l1)
raw_mlp_branch = model.FC(
mlp_l1, 'mask_mlp_logits_raw', dim_h, dim_out,
weight_init=('GaussianFill', {'std': 0.001}),
bias_init=('ConstantFill', {'value': 0.}))
elif fc_mask_head_type == '3_layer':
mlp_l1 = model.FC(
blob_in, 'fc_mask_head_mlp_l1', dim_in, dim_h,
weight_init=('MSRAFill', {}),
bias_init=('ConstantFill', {'value': 0.}))
model.net.Relu(mlp_l1, mlp_l1)
mlp_l2 = model.FC(
mlp_l1, 'fc_mask_head_mlp_l2', dim_h, dim_h,
weight_init=('MSRAFill', {}),
bias_init=('ConstantFill', {'value': 0.}))
model.net.Relu(mlp_l2, mlp_l2)
raw_mlp_branch = model.FC(
mlp_l2, 'mask_mlp_logits_raw', dim_h, dim_out,
weight_init=('GaussianFill', {'std': 0.001}),
bias_init=('ConstantFill', {'value': 0.}))
项目代码在这里