====== Detectron2 ======
* 設定ファイルベースで学習とかやるフレームワーク?
* 決定的?
* DDP の抽象化?
* [[https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5| Colab Tutorial]] をやっていくのが一番早い
===== 概要 =====
* 設定の作成
* コマンドライン引数
* 設定ファイル
* 設定をもとに実行
* どの順で関数が実行されるか?
* 学習インスタンスの生成
* Trainer
==== 設定ファイルについて ====
以下のライブラリを順に継承して ''CfgNode'' クラスが作成されており、それをベースにしている。
^ ''CfgNode''の継承ツリー ^^
| [[https://github.com/rbgirshick/yacs/blob/master/yacs/config.py|yacs]] |'' yacs/yacs/config.py'' |
| [[https://github.com/facebookresearch/fvcore/blob/main/fvcore/common/config.py|fvcore]] | ''fvcore/fvcore/common/config.py'' |
| [[https://github.com/facebookresearch/detectron2/blob/main/detectron2/config/config.py|detectron2]] | ''detectron2/detectron2/config/config.py'' |
設定内容(CfgNodeの中身)については
* [[https://github.com/facebookresearch/detectron2/blob/main/detectron2/config/defaults.py|detectron2/detectron2/config/defaults.py]] で書き込まれる。
その後、
* ''.merge_from_file()''
* ''.merge_from_list()''
で調整して設定を作成する。
=== DDP の抽象化 ===
* DDP をうまくやってくれる
* ''detectron2.engine.launch'' から ''torch.multiprocessing'' をいじってやってくれる。
==== コマンドライン引数について ====
以下のやつは ''argparse.ArgumentParser'' と同じ
from detectron2.engine import default_argument_parser
default_argument_parser().parse_args()
==== 子プロセス ====
''detectron2/detectron2/utils/comm.py'' [[https://github.com/facebookresearch/detectron2/blob/main/detectron2/utils/comm.py|→]] で定義されている関数を使って子プロセスの諸々の情報を知ることができる。
import
from detectron2.utils import comm
=== GPU の ID を知る ===
comm.get_local_rank()
===== 学習 =====
==== 学習インスタンス Trainer ====
* ''detectron2/engine/defaults.py'' の ''DefaultTrainer'' から始まる。\\ こいつに config を渡して ''.train()'' でやっていく。 from detectron2.engine import DefaultTrainer
^ ''DefaultTrainer'' ^^
| ''detectron2/detectron2/engine/train_loop.py'' [[https://github.com/facebookresearch/detectron2/blob/main/detectron2/engine/train_loop.py|→]] | ''class TrainerBase'' |
| ''detectron2/detectron2/engine/defaults.py'' [[https://github.com/facebookresearch/detectron2/blob/main/detectron2/engine/defaults.py|→]] | ''class DefaultTrainer'' |
DefaultTrainer の持っている ''.build_model()'' からモデルが作成される。\\
この ''.build_model()'' は ''detectron2/modeling/meta_arch/build.py'' の ''build_model()'' 関数の拡張。
=== コンストラクタ呼び出し時のふるまい ===
global : trainer = DefaultTrainer(config)
DefaultTrainer: super().__init__()
TrainerBase : self._hooks = []
TrainerBase : self.iter = 0
TrainerBase : self.start_iter = 0
DefaultTrainer:
...
DefaultTrainer: model = self.build_model(cfg)
...
DefaultTrainer: model = create_ddp_model(model, broadcast_buffer=False)
^ ''TrainerBase'' ^^^
| ''_%%_init_%%_'' | inst. | superlly called |
| ''register_hooks'' | inst. | |
| ''before_train'' | inst. | |
| ''after_train'' | inst. | |
| ''before_step'' | inst. | |
| ''after_step'' | inst. | |
| ''train'' | inst. | superlly called |
| ''run_step'' | inst. | just to be overrided |
| ''state_dict'' | inst. | superlly called |
| ''load_state_dict'' | inst. | superlly called |
| |||
^ ''DefaultTrainer'' ^^^
| ''_%%_init_%%_'' | inst. | override |
| ''resume_or_load'' | inst. | |
| ''build_hooks'' | inst. | |
| ''build_writers'' | inst. | |
| ''train'' | inst. | override |
| ''run_step'' | inst. | override |
| ''state_dict'' | inst. | override |
| ''load_state_dict'' | inst. | override |
| ''build_model'' ^ class | |
| ''build_optimizer'' ^ class | |
| ''build_lr_scheduler'' ^ class | |
| ''build_train_loader'' ^ class | |
| ''build_test_loader'' ^ class | |
| ''build_evaluator'' ^ class | |
| ''test'' ^ class | |
| ''auto_scale_workers'' ^ static | |
=== Trainer の重要メンバ ===
''DefaultTrainer'' のメンバ。
* ''_trainer'' は SimpleTrainerクラス。
TrainerBase を継承して DefaultTrainer が作成されている。
同じように SimpleTrainer も TrainerBase を継承して作成されている。
なので DefaultTrainer と SimpleTrainer は親子関係はないが、DefaultTrainer の ''_trainer'' というメンバは
SimpleTrainer なことがある。
* SimpleTrainer のメンバが直接触るべきモデル
* ''model'' : ''GeneralizedRCNN'' とか
* ''model.backbone'' :
==== モデルデータベース Registry ====
Registry に登録されているモデルから拡張して作るのが普通っぽい。
# import
from detectron2.modeling.meta_arch.build import META_ARCH_REGISTRY
^ ''Registry'' ^^
| ''detectron2/detectron2/utils/registry.py'' [[https://github.com/facebookresearch/detectron2/blob/main/detectron2/utils/registry.py|→]] | ''Registry'' |
| ''fvcore/fvcore/common/registry.py'' [[https://github.com/facebookresearch/fvcore/blob/main/fvcore/common/registry.py|→]] | ''Registry'' |
''detectron2/detectron2/modeling/meta_arch/'' にあるモジュールで ''@META_ARCH_REGISTRY.register()'' というデコレータを使用して
いろいろなモデルアーキテクチャを登録している。\\
コードから登録されているアーキテクチャを追跡することは面倒だが、 ''@META_ARCH_REGISTRY'' デコレータが付いているものを確認すると以下のようになっている。
detectron2/modeling/meta_arch/retinanet.py RetinaNet
detectron2/modeling/meta_arch/panoptic_fpn.py PanopticFPN
detectron2/modeling/meta_arch/semantic_seg.py SemanticSegmentor
detectron2/modeling/meta_arch/rcnn.py GeneralizedRCNN
ProposalNetwork
''BACKBONE_REGISTRY''
detectron2/modeling/backbone/resnet.py build_resnet_backbone
detectron2/modeling/backbone/fpn.py build_resnet_fpn_backbone
build_retinanet_resnet_fpn_backbone
=== モデルが生成される過程 ===
# detectron2/detectron2/engine/defaults.py
# class DefaultTrainer method __init__
model = self.build_model( cfg ) # CfgNode
# detectron2/detectron2/engine/defaults.py
# class DefaultTrainer method build_model
model = build_model(cfg)
# detectron2/detectron2/modeling/metar_arch/build.py
# detectron2.modeling function build_model
meta_arch = cfg.MODEL.META_ARCHITECTURE
model = META_ARCH_REGISTRY.get(meta_arch)(cfg)
# detectron2/detectron2/utils/registry.py : redirect
# detectron2.utils.registry class Registry : redirect
# fvcore/fvcore/common/registry.py
# fvcore.common.registry class Registry method get
ret = self._obj_map.get(name) # _obj_map はただの dict、 ret は nn.Module
# detectron2/detectron2/modeling/meta_arch/rcnn.py
# class GeneralizedRCNN method __init__ with @configurable
# detectron2/detectron2/config/config.py
# detectron2.config function configurable
from_config_func = type(self).from_config
explicit_args = _get_args_from_config(from_config_func, *args, **kwargs)
# detectron2/detectron2/config/config.py
# function _get_args_from_config
ret = from_config_func(*args, **kwargs)
# detectron2/detectron2/modeling/meta_arch/rcnn.py
# class GeneralizedRCNN method from_config
backbone = build_backbone(cfg)
# detectron2/detectron2/modeling/backbone/build.py
# function build_backbone
backbone_name = cfg.MODEL.BACKBONE.NAME
backbone = BACKBONE_REGISTRY.get(backbone_name)(cfg, input_shape)
==== R-CNN ====
''detectron2/modeling/meta_arch/rcnn.py'' の ''forward'' を見る。
だいたいこんな感じ
GeneralizedRCNN
images <- self.preprocess_image( batched_inputs )
features <- self.backbone( images.tensor )
proposals, proposal_losses <- self.proposal_generator( images, features, gt_instances )
_, detector_losses <- self.roi_heads( images, features, proposals, gt_instances )
===== データセット =====
==== 自作データセット定義方法 ====
=== 完全自作の形式 ===
from detectron2.data import DatasetCatalog
DatasetCatalog.register('MyDataset', my_function )
=== 特定の形式で登録する ===
''detectron2.data.datasets'' にある関数
* ''register_coco_instances''
* ''register_coco_panoptic''
* ''register_coco_panoptic_separated''
* ''register_lvis_instances''
* ''register_pascal_voc''
=== 取り出し ===
''detectron2.data.common.AspectRatioGroupedDataset'' の ''%%_%%_iter%%_%%_'' を見るべし
=== カスタムなデータローダーの定義 ===
デフォルトでは ''detectron2/data/dataset_mapper.py'' の ''DatasetMapper'' が使われるため画像はファイルから読み込むしかできない。
データセットに合った特定の読み込み方を指定するには custom dataloader を作成する必要がある。
* [[https://github.com/facebookresearch/detectron2/blob/cbbc1ce26473cb2a5cc8f58e8ada9ae14cb41052/docs/tutorials/datasets.md|custom dataset]]
* [[https://github.com/facebookresearch/detectron2/blob/cbbc1ce26473cb2a5cc8f58e8ada9ae14cb41052/docs/tutorials/data_loading.md|custom data loader]]
これらを見る限り、 ''DefaultTrainer'' の ''build_train_loader'' などのメソッドをオーバーライドするのが正攻法。