この記事では、完全な MMDetection に含まれる設定ファイル内のモデル ファイル --model.py を主に紹介します。
次のコードは、モデル ファイルに含まれるコードの意味と使用法を 1 行ずつ詳細に説明しています。
1. 特徴抽出ネットワークバックボーン
上図に示す SwinTransformer を特徴抽出ネットワークのバックボーンとして使用し、次の構成を実行します。
他のバックボーン モデルを選択する場合は、「type='新しいモデル名'」を変更し、選択した新しいモデルに応じて新しいパラメーターを定義する必要があります。たとえば、次のバックボーンとしての SwinTransformer の例と、対応するパラメータ
backbone=dict(
type='SwinTransformer', #主干网络(特征提取网络)采用Swin Transformer,以下为关于Swin Transformer网络参数的选取
embed_dim=96, #输入Swin Transformer第一层的嵌入维度,整个过程为[96, 192, 384, 768]
depths=[2, 2, 6, 2], #Swin Transformer四个阶段W-MSA和SW-MSA的个数
num_heads=[3, 6, 12, 24], #Swin Transformer四个阶段分别对应的多头数
window_size=7, #Swin Transformer整个阶段采用的窗口大小
mlp_ratio=4., #MPL的词向量嵌入维度,默认为4
qkv_bias=True,
qk_scale=None,
drop_rate=0.,
attn_drop_rate=0.,
drop_path_rate=0.2,
ape=False,
patch_norm=True,
out_indices=(0, 1, 2, 3),
use_checkpoint=False),
2.機能強化されたネックネットワーク
上の図に示されている機能ピラミッド ネットワーク (FPN) 機能ピラミッドを特徴抽出ネットワークのバックボーンとして使用し、次の構成を実行します。
同様に、他のネックを選択したい場合は、「type='新しいモデル名'」を変更し、選択した新しいモデルに応じて新しいパラメータを定義する必要があります。たとえば、次のバックボーンとしてのFPNの例と、その意味対応するパラメータのうち、in_channels は swin トランスフォーマーの 4 段のスケールチャンネル数に対応し、out_channels は各スケールの出力チャンネル数に対応し、num_outs は出力スケール数で、RCNN の出力スケールはさらに 1 つになります。特徴抽出ネットワークよりもスケールが大きいため、num_outs=バックボーンスケール番号+1
neck=dict(
type='FPN', #neck特征增强采用FPN(特征金字塔)
in_channels=[96, 192, 384, 768],#每个尺度的输入通道数
out_channels=256, #每个尺度的输出通道数,每个尺度都一致
num_outs=5), #输出尺度的数量,RCNN中的输出尺度数量为4+1,其中4为主干网络Swin Transformer的四个尺度
3. 検出器の第 2 段階
1段階:提案候補ボックスの抽出 - RPN
rpn の正式名は領域提案ネットワークであり、第 2 段階の高品質のターゲット候補フレームを提供するために使用されます。
①アンカー ジェネレーターは
、指定されたスケール、比率、およびストライドに従って異なるアンカーを生成します。
②アンカー ターゲット ジェネレーター アンカー
ターゲット レイヤーは、どのアンカーがポジティブ サンプル (実際のターゲットを含む) でどのアンカーがネガティブ サンプル (背景のみを含む) であるかを区別するタスクを完了します。具体的な方法は、アンカーとグランド トゥルースの IoU を計算することです。
③RPN 損失
rpn には 2 つのタスクがあります: 多数のアンカーから、どのアンカーが正のサンプルでどのアンカーが負のサンプルであるかを判断する (分類タスク)、正のサンプル アンカーについては、回帰によって実際のターゲットを取得する (回帰タスク)。したがって、損失は、分類ブランチの時間関数と回帰ブランチの損失関数の 2 つの部分で構成されます。
④提案ジェネレーター
が候補フレームを取得する目的は、第 2 段階に高品質の ROI フレームを提供することです。
rpn_head=dict(
type='RPNHead', #采用RPN提取proposal候选框
in_channels=256, #输入特征图中的通道数
feat_channels=256, #特征图的通道数
anchor_generator=dict(
type='AnchorGenerator', #anchor生成器的配置
scales=[8], #就是放缩的尺度,要将宽和高按照各个scale的值放大。scales*strides
ratios=[0.5, 1.0, 2.0], #长短边比例
strides=[4, 8, 16, 32, 64]),#anchor_strides代表感受野的大小,以配置文件中,anchor_strides=[4, 8, 16, 32, 64]为例。
#具体来说,anchor_strides[0]就是指P2层feature map上的一个点对应到原图上的4个像素;
# anchor_strides[1]就是指P3层feature map上的一个点对应到原图上的8个像素;
# 以此类推……正是由于这个特性,anchor_strides也刚好代表了每一个levlel的anchor对应于原图中的基础大小。
# 因此,在AnchorGenerator中,传入的anchor_strides参数被命名为base_size。
bbox_coder=dict(
type='DeltaXYWHBBoxCoder', #训练过程中对anchor框进行编码和解码,采用'DeltaXYWHBBoxCoder' 的框编码器
target_means=[.0, .0, .0, .0], #用于编码和解码框的目标均值
target_stds=[1.0, 1.0, 1.0, 1.0]), #用于编码和解码框的标准方差
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),#分类分支的损失函数配置,采用CrossEntropyLoss损失,在RPN中通常用于二分类吗,仅分类目标和背景,因此基本上使用sigmoid函数
loss_bbox=dict(type='L1Loss', loss_weight=1.0)), #回归分支的损失函数配置,采用L1Loss损失,给损失权重赋值
第 2 段階: 候補領域の特徴を抽出し、それを分類器に送信してカテゴリを識別します—ROI
ROI の正式名称は、Region of Interest で、画像の「関心領域」を指します。
①提案ターゲット生成者は、
rpn によって生成された提案に基づいて一定量を選択します (min_batch: 通常、画像ごとに 256 個の提案を選択します。または、 512件の提案)のROIをトレーニングの第2段階のサンプルとして、min_batch内の陽性サンプルと陰性サンプルの比率を設定します。 ②特徴量クロップと
プーリング
第1段階で得られたROIに対して、ROIの大きさに応じて、トリミングする適切なフィーチャ レイヤーを選択する必要があり、Pooling によって固定サイズのフィーチャ マップが取得されます。このプロセスは ROI Align (ROI アライメント) と呼ばれます。バイリニア補間を使用してピクセル値を取得し、ROI Align が実現されます。
roi_head=dict( #作为检测器的第二步
type='StandardRoIHead',
bbox_roi_extractor=dict( #Bbox感兴趣区域的特征提取器
type='SingleRoIExtractor',
roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),#roi层的配置,采用的ROI对齐,特征图输出大小为7,sampling_ratio指提取ROI特征时的采样率
out_channels=256, #特征的输出通道数
featmap_strides=[4, 8, 16, 32]), #多尺度特征图的步幅,应该与主干的架构保持一致,具体可参考RPN中的strides前四个
bbox_head=dict( #RoIHead 中 box head 的配置
type='Shared2FCBBoxHead',
in_channels=256, #bbox_head的输入通道,与bbox_roi_extractor的输出通道大小一致
fc_out_channels=1024, #全连接FC层的输出特征通道数
roi_feat_size=7, #候选区域(Region of Interest)特征的大小
num_classes=80, #分类的类别数,和你自己的数据集相匹配
bbox_coder=dict(
type='DeltaXYWHBBoxCoder',
target_means=[0., 0., 0., 0.], #用于编码和解码框的目标均值
target_stds=[0.1, 0.1, 0.2, 0.2]), #编码和解码的标准方差。因为框更准确,所以值更小,常规设置时 [0.1, 0.1, 0.2, 0.2]。
reg_class_agnostic=False, #回归是否与类别无关
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),#分类分支的损失函数配置,采用CrossEntropyLoss损失,是否使用sigmoid函数
loss_bbox=dict(type='L1Loss', loss_weight=1.0)), #回归分支的损失函数配置,采用L1Loss损失,给损失权重赋值
4. モデルのトレーニングとテストのためのハイパーパラメーター構成
train_cfg と test_cfg の一部の設定は、RPN と RCNN のサンプル部分のハイパーパラメータ設定に関連しており、具体的なパラメータについては次のように説明されます。
train_cfg=dict( #rpn 和 rcnn 训练超参数的配置
rpn=dict(
assigner=dict( #分配正负样本分配器的配置
type='MaxIoUAssigner', #选用MaxIoUAssigner
pos_iou_thr=0.7, #IOU >= 0.7 作为正样本
neg_iou_thr=0.3, #IOU <= 0.3 作为负样本
min_pos_iou=0.3, #作为正样本的最小IOU阈值
match_low_quality=True, #是否匹配低质量的框
ignore_iof_thr=-1), #忽略 bbox 的 IoF 阈值
sampler=dict( #正负采样器的配置
type='RandomSampler', #选用RandomSampler采样器
num=256, #需要提取样本的数量
pos_fraction=0.5, #正样本占总样本数的比例
neg_pos_ub=-1, #基于正样本数量的负样本上限,超出上限的忽略,-1表示不忽略
add_gt_as_proposals=False), #采样后是否添加 GT 作为 proposal
allowed_border=-1, #对有效anchor进行边界填充,-1表示不填充
pos_weight=-1, #训练期间正样本权重,-1代表不更改
debug=False), #是否设置调试(debug)模式
rpn_proposal=dict( #在训练期间生成 proposals 的配置
nms_pre=2000, #做非极大值抑制(NMS)前box的数量
max_per_img=1000, #做NMS后要保留的box的数量
nms=dict(type='nms', iou_threshold=0.7), #NMS,其阈值为0.7
min_bbox_size=0), #允许的最小 box 尺寸
rcnn=dict(
assigner=dict( #RCNN分配正负样本
type='MaxIoUAssigner',
pos_iou_thr=0.5, #IOU >= 0.5 作为正样本
neg_iou_thr=0.5, #IOU < 0.5 作为负样本
min_pos_iou=0.5, # 将 box 作为正样本的最小 IoU 阈值
match_low_quality=True, #是否匹配低质量的框
ignore_iof_thr=-1), #忽略 bbox 的 IoF 阈值,-1表示不忽略
sampler=dict( #正负采样器的配置
type='RandomSampler', #选用RandomSampler采样器
num=512, #需要提取样本的数量
pos_fraction=0.25, #正样本占总样本数的比例
neg_pos_ub=-1, #基于正样本数量的负样本上限,超出上限的忽略,-1表示不忽略
add_gt_as_proposals=True), #采样后是否添加 GT 作为 proposal
mask_size=28, #mask的大小
pos_weight=-1, #训练期间正样本权重,-1代表不更改
debug=False)), #是否设置调试(debug)模式
test_cfg=dict( #rpn 和 rcnn 测试超参数的配置
rpn=dict(
nms_pre=1000, #做非极大值抑制(NMS)前box的数量
max_per_img=1000, #做NMS后要保留的box的数量
nms=dict(type='nms', iou_threshold=0.7), #NMS,其阈值为0.7
min_bbox_size=0), #允许的最小 box 尺寸
rcnn=dict(
score_thr=0.05, #bbox的分数阈值
nms=dict(type='nms', iou_threshold=0.5), #NMS,其阈值为0.5
max_per_img=100, #做NMS后要保留的box的数量
mask_thr_binary=0.5))) #mask预处的阈值
以下は、完全なモデル ファイルのコードとパラメーターの紹介です。mask_rcnn_swin_fpn.py
# model settings
model = dict(
type='MaskRCNN', #你所采用的检测器类型
pretrained=None,
backbone=dict(
type='SwinTransformer', #主干网络(特征提取网络)采用Swin Transformer,以下为关于Swin Transformer网络参数的选取
embed_dim=96, #输入Swin Transformer第一层的嵌入维度,整个过程为[96, 192, 384, 768]
depths=[2, 2, 6, 2], #Swin Transformer四个阶段W-MSA和SW-MSA的个数
num_heads=[3, 6, 12, 24], #Swin Transformer四个阶段分别对应的多头数
window_size=7, #Swin Transformer整个阶段采用的窗口大小
mlp_ratio=4., #MPL的词向量嵌入维度,默认为4
qkv_bias=True,
qk_scale=None,
drop_rate=0.,
attn_drop_rate=0.,
drop_path_rate=0.2,
ape=False,
patch_norm=True,
out_indices=(0, 1, 2, 3),
use_checkpoint=False),
neck=dict(
type='FPN', #neck特征增强采用FPN(特征金字塔)
in_channels=[96, 192, 384, 768],#每个尺度的输入通道数
out_channels=256, #每个尺度的输出通道数,每个尺度都一致
num_outs=5), #输出尺度的数量,RCNN中的输出尺度数量为4+1,其中4为主干网络Swin Transformer的四个尺度
rpn_head=dict(
type='RPNHead', #采用RPN提取proposal候选框
in_channels=256, #输入特征图中的通道数
feat_channels=256, #特征图的通道数
anchor_generator=dict(
type='AnchorGenerator', #anchor生成器的配置
scales=[8], #就是放缩的尺度,要将宽和高按照各个scale的值放大。scales*strides
ratios=[0.5, 1.0, 2.0], #长短边比例
strides=[4, 8, 16, 32, 64]),#anchor_strides代表感受野的大小,以配置文件中,anchor_strides=[4, 8, 16, 32, 64]为例。
#具体来说,anchor_strides[0]就是指P2层feature map上的一个点对应到原图上的4个像素;
# anchor_strides[1]就是指P3层feature map上的一个点对应到原图上的8个像素;
# 以此类推……正是由于这个特性,anchor_strides也刚好代表了每一个levlel的anchor对应于原图中的基础大小。
# 因此,在AnchorGenerator中,传入的anchor_strides参数被命名为base_size。
bbox_coder=dict(
type='DeltaXYWHBBoxCoder', #训练过程中对anchor框进行编码和解码,采用'DeltaXYWHBBoxCoder' 的框编码器
target_means=[.0, .0, .0, .0], #用于编码和解码框的目标均值
target_stds=[1.0, 1.0, 1.0, 1.0]), #用于编码和解码框的标准方差
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),#分类分支的损失函数配置,采用CrossEntropyLoss损失,在RPN中通常用于二分类吗,仅分类目标和背景,因此基本上使用sigmoid函数
loss_bbox=dict(type='L1Loss', loss_weight=1.0)), #回归分支的损失函数配置,采用L1Loss损失,给损失权重赋值
roi_head=dict( #作为检测器的第二步
type='StandardRoIHead',
bbox_roi_extractor=dict( #Bbox感兴趣区域的特征提取器
type='SingleRoIExtractor',
roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),#roi层的配置,采用的ROI对齐,特征图输出大小为7,sampling_ratio指提取ROI特征时的采样率
out_channels=256, #特征的输出通道数
featmap_strides=[4, 8, 16, 32]), #多尺度特征图的步幅,应该与主干的架构保持一致,具体可参考RPN中的strides前四个
bbox_head=dict( #RoIHead 中 box head 的配置
type='Shared2FCBBoxHead',
in_channels=256, #bbox_head的输入通道,与bbox_roi_extractor的输出通道大小一致
fc_out_channels=1024, #全连接FC层的输出特征通道数
roi_feat_size=7, #候选区域(Region of Interest)特征的大小
num_classes=80, #分类的类别数,和你自己的数据集相匹配
bbox_coder=dict(
type='DeltaXYWHBBoxCoder',
target_means=[0., 0., 0., 0.], #用于编码和解码框的目标均值
target_stds=[0.1, 0.1, 0.2, 0.2]), #编码和解码的标准方差。因为框更准确,所以值更小,常规设置时 [0.1, 0.1, 0.2, 0.2]。
reg_class_agnostic=False, #回归是否与类别无关
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),#分类分支的损失函数配置,采用CrossEntropyLoss损失,是否使用sigmoid函数
loss_bbox=dict(type='L1Loss', loss_weight=1.0)), #回归分支的损失函数配置,采用L1Loss损失,给损失权重赋值
mask_roi_extractor=dict(
type='SingleRoIExtractor',
roi_layer=dict(type='RoIAlign', output_size=14, sampling_ratio=0),
out_channels=256,
featmap_strides=[4, 8, 16, 32]),
mask_head=dict(
type='FCNMaskHead',
num_convs=4,
in_channels=256,
conv_out_channels=256,
num_classes=80,
loss_mask=dict(
type='CrossEntropyLoss', use_mask=True, loss_weight=1.0))),
# model training and testing settings
train_cfg=dict( #rpn 和 rcnn 训练超参数的配置
rpn=dict(
assigner=dict( #分配正负样本分配器的配置
type='MaxIoUAssigner', #选用MaxIoUAssigner
pos_iou_thr=0.7, #IOU >= 0.7 作为正样本
neg_iou_thr=0.3, #IOU <= 0.3 作为负样本
min_pos_iou=0.3, #作为正样本的最小IOU阈值
match_low_quality=True, #是否匹配低质量的框
ignore_iof_thr=-1), #忽略 bbox 的 IoF 阈值
sampler=dict( #正负采样器的配置
type='RandomSampler', #选用RandomSampler采样器
num=256, #需要提取样本的数量
pos_fraction=0.5, #正样本占总样本数的比例
neg_pos_ub=-1, #基于正样本数量的负样本上限,超出上限的忽略,-1表示不忽略
add_gt_as_proposals=False), #采样后是否添加 GT 作为 proposal
allowed_border=-1, #对有效anchor进行边界填充,-1表示不填充
pos_weight=-1, #训练期间正样本权重,-1代表不更改
debug=False), #是否设置调试(debug)模式
rpn_proposal=dict( #在训练期间生成 proposals 的配置
nms_pre=2000, #做非极大值抑制(NMS)前box的数量
max_per_img=1000, #做NMS后要保留的box的数量
nms=dict(type='nms', iou_threshold=0.7), #NMS,其阈值为0.7
min_bbox_size=0), #允许的最小 box 尺寸
rcnn=dict(
assigner=dict( #RCNN分配正负样本
type='MaxIoUAssigner',
pos_iou_thr=0.5, #IOU >= 0.5 作为正样本
neg_iou_thr=0.5, #IOU < 0.5 作为负样本
min_pos_iou=0.5, # 将 box 作为正样本的最小 IoU 阈值
match_low_quality=True, #是否匹配低质量的框
ignore_iof_thr=-1), #忽略 bbox 的 IoF 阈值,-1表示不忽略
sampler=dict( #正负采样器的配置
type='RandomSampler', #选用RandomSampler采样器
num=512, #需要提取样本的数量
pos_fraction=0.25, #正样本占总样本数的比例
neg_pos_ub=-1, #基于正样本数量的负样本上限,超出上限的忽略,-1表示不忽略
add_gt_as_proposals=True), #采样后是否添加 GT 作为 proposal
mask_size=28, #mask的大小
pos_weight=-1, #训练期间正样本权重,-1代表不更改
debug=False)), #是否设置调试(debug)模式
test_cfg=dict( #rpn 和 rcnn 测试超参数的配置
rpn=dict(
nms_pre=1000, #做非极大值抑制(NMS)前box的数量
max_per_img=1000, #做NMS后要保留的box的数量
nms=dict(type='nms', iou_threshold=0.7), #NMS,其阈值为0.7
min_bbox_size=0), #允许的最小 box 尺寸
rcnn=dict(
score_thr=0.05, #bbox的分数阈值
nms=dict(type='nms', iou_threshold=0.5), #NMS,其阈值为0.5
max_per_img=100, #做NMS后要保留的box的数量
mask_thr_binary=0.5))) #mask预处的阈值
MMDetection-MMDetection のデータセット ファイル、トレーニング プラン ファイル、実行情報ファイル、および特定のパラメーターの解釈を使って遊ぶ (2) MMDetection-MMDetection を使って独自の設定ファイルを作成して遊ぶ (3)