概要
まだまだ日本語情報が少ない物体検出フレームワーク"MMDetection"について、学んだことを記録していこうと思います。間違い等ありましたらぜひコメントで教えてください。よろしくお願いします。
前回:既存モデルの学習編
今回はMMDetectionでモデルを設計する上で欠かせない config について、その基礎をまとめたいと思います。
config ファイルとは
MMDetectionでは、モジュールを組み合わせることでモデルを設計します。モデルの設計(と学習方法)はmmdetecion/configs/*/*.py
に記述し、これをconfigファイルと呼びます。
configのファイル名はモデルの概要が理解できる様に命名されています。
命名規則についてはこちらで触れているのでご確認ください。
config ファイルの読み込み
configファイルはMMCVライブラリの Config クラスのメソッドConfig.fromfile
を用いて読み込むことで、ひとつの辞書としてロードすることができます。ソースコードはこちら。
それでは、実際にconfigファイルを作って、読み込みを行ってみます。
1. configファイルの作成
a = 10
b = '20'
c = dict(c_1: 1, c_2: 2)
2. configファイルのロード
インタラクティブモードでpythonを起動して以下のように入力します。
>>> from mmcv import Config
>>>
>>> cfg = Config.fromfile('./my_config_a.py')
>>> cfg
Config (path: ./my_config_a.py): {'a': 10, 'b': '20', 'c': {'c_1': 1, 'c_2': 2}}
config ファイルが読み込まれて辞書に変換されていることが確認できます。
config の記法
上述したように、config ファイルはConfig.fromfile
メソッドでロードすると一つの辞書に変換されます。これはconfig ファイルをオブジェクトとして読み込み、そのアトリビュートを辞書型に変換して返すことで実現しています。
従って、クラスの中にアトリビュートを追加する感覚で書けば大丈夫です。
1. keyとvalueの追加
key = value
という形で1行ごとに追加することができます。
# 1行ごとに key = value の形で追加していく
a = 10
b = '20'
c = dict(c_1=1, c_2=2) # value に辞書を持たせることも可能
2. configファイルの継承
_base_ = '[継承するconfigファイルへのパス]'
と最初の行に追加することで、既存のconfigファイルを元に、新しくkeyとvalueを追加したconfigファイルを作成することができます。
2.1. 継承の基本
# my_config_a.py の内容を継承
_base_ = 'my_config_a.py'
c = dict(c_3='config_b') # 辞書のkey:valueも追加できる
d = 'config_b'
>>> from mmcv import Config
>>>
>>> cfg = Config.fromfile('./my_config_b.py')
>>> cfg
Config (path: my_config_b.py): {'a': 10, 'b': '20', 'c': {'c_1': 1, 'c_2': 2, 'c_3': 'config_b'}, 'd': 'config_b'}
my_config_a.pyの内容はそのままに、新しく{'c': {'c_3': 'config_b'}}
と{'d': 'config_b'}
が追加されていることがわかります。
2.2. 継承したvalueの修正
keyとvalueの追加だけでなく、継承したvalueを修正することもできます。
# my_config_a.py の内容を継承
_base_ = 'my_config_a.py'
a = 30 # a = 10 から修正
d = 'config_b'
>>> from mmcv import Config
>>>
>>> cfg = Config.fromfile('./my_config_b.py')
>>> cfg
Config (path: ./my_config_b.py): {'a': 30, 'b': '20', 'c': {'c_1': 1, 'c_2': 2}, 'd': 'config_b'}
継承したconfigファイルの内容が修正されていることがわかります。
2.3. 継承した辞書のkeyを削除
さらに、_delete_=True
を用いることで継承したdictのkeyをリセット(消去)することもできます。
# my_config_a.py の内容を継承
_base_ = 'my_config_a.py'
c = dict(
_delete_=True, # 継承した辞書cのkey(c_1, c_2)を削除
c_3 = 3, c_4 = 4)
d = 'config_b'
>>> from mmcv import Config
>>>
>>> cfg = Config.fromfile('./my_config_b.py')
>>> cfg
Config (path: my_config_b.py): {'a': 10, 'b': '20', 'c': {'c_3': 3, 'c_4': 4}, 'd': 'config_b'}
継承した辞書cのキーがリセットされていることがわかります。
2.4. 複数のconfigファイルを継承
_base_
にconfigファイルへのパスをリストとして渡すことで、複数のconfigファイルを継承することができます。
このとき、configファイル間のkeyの重複は許されません。
# my_config_a.py と重複しないように修正
d = 'config_b'
# my_config_a.py, my_config_b.py の内容を継承
_base_ = ['my_config_a.py', 'my_config_b.py']
e = 'config_c'
>>> from mmcv import Config
>>>
>>> cfg = Config.fromfile('./my_config_c.py')
>>> cfg
Config (path: my_config_d.py): {'a': 10, 'b': '20', 'c': {'c_1': 1, 'c_2': 2}, 'd': 'config_b', 'e': 'config_c'}
ふたつのconfigが継承されていることがわかります。
3. valueへのアクセス
ロードしたconfigのvalueへのアクセスは、対応するkeyを名前に持つアトリビュートの呼び出しと同様に行えます。
>>> from mmcv import Config
>>>
>>> cfg = Config.fromfile('./my_config_a.py')
>>> cfg.a
10
>>> cfg.b
'20'
>>> cfg.c
{'c_1': 1, 'c_2': 2}
>>> cfg.c.c_1 # valueに辞書を持つ場合も同様にアクセス可能
1
>>> cfg.c.c_2
2
おまけ
configファイルではいくつかの事前定義された変数が利用可能なので、簡単に紹介します。
-
'{{ fileDirname }}'
:configファイルのディレクトリまでのパス -
'{{ fileBasename }}'
:configファイル名 -
'{{ fileBasenameNoExtension }}'
:configファイル名から拡張子を除いたもの -
'{{ fileExtname }}'
:configファイルの拡張子
a = 10
fileBasename = '{{ fileBasenameNoExtension }}'
fileExtname = '{{ fileExtname }}'
>>> from mmcv import Config
>>>
>>> cfg = Config.fromfile('./my_config_d.py')
>>> cfg.fileBasename
'my_config_d'
>>> cfg.fileExtname
'.py'