Object Detection - Config 만들기
27 Sep 2021 | Deep Learning강의를 아직 제대로 수강하고 정리하지 않았다.
일단 베이스라인 코드를 구현하려고 노력했고, 그에 대한 정리를 해야겠다.
Object Detection을 위한 High level 프레임워크
detectron2와 mmdetection 두 가지로, pytorch를 상당히 높은 레벨로 포장한 라이브러리가 있다.
멘토님이 말해주신 스위치를 켰다 껏다 하는 행위를 하기에 정말 알맞는… 물론 좋은 라이브러리이고 상당히 좋은 성능을 보이는 것은 맞지만, 낭만이없다 낭만이…
그나마 detectron2가 좀 더 자유롭다고 하여, 그 부분으로 일단 해보자! 라고 생각했다.
하지만 Baseline 코드가 내가 보기엔 hard-coding되어있다고 생각했다. 그래서 내 나름대로 Config 파일을 만들기로 결심하였다.
configparser
json파일로도 설정할 수 있겠지만, Python Runtime 내에서는 이게 더 편한것같다.
간단하게 사용법을 적어놓고 가야겠다.
import configparser
## 새로 만들기
config = configparser.ConfigParser()
config['general'] = {}
config['general']['~~~'] = ~~~
config['general']['~~~'] = ~~~
config['hyperparam'] = {}
config['hyperparam']['~~~'] = ~~~
뭐 이런식으로 일단 Runtime 내에서 설정을 해준다. 개인적으로 이렇게 간단히 만들어주는건 노트북 내에서 설정하는게 제일 좋은것같다.
## 저장
with open('config.ini', 'w', encoding='utf-8') as configfile:
config.write(configfile)
## 불러오기
config = configparser.ConfigParser().read('config.ini', encoding='utf-8')
이렇게 파일로 만들어서 사용할 수 있다.
## section 확인
for section in config.sections():
print(section)
i = iter(config[section])
while i:
try:
key = next(i)
value = config[section][key]
print(" ",key,":", value)
except StopIteration:
break
이 코드를 적용하면 마치 Json파일의 형태처럼 무슨 값이 들어있는지 세팅할 수 있다.
하지만 주의해야할 점은 모든 값이 문자열 형태로 들어간다는 것이다.
그래서 Config를 불러오는 클래스에서는 따로 정제를 해주어야 한다.
# load_config.py
import configparser
import re
from easydict import EasyDict as edict
import os
from datetime import datetime, timedelta
def _refineVal(x):
key,val = x
if val.isdigit():
val = int(val)
elif re.match(r'^-?\d+(?:\.\d+)$', val):
val = float(val)
elif re.match("^\(",val):
val = tuple(map(int,(val[1:-1].split(","))))
elif key in "classes":
val = [x for x in val.split(" ")]
elif key in "resume":
val = True if val in "True" else False
return key, val
def _refineOutputPath(isTrain, outputDir, customName):
subPath = "train" if isTrain else "eval"
nowTime = datetime.now() + timedelta(hours=9)
cnt = 0
while True:
addedName = f'{nowTime.strftime("%m-%d")}_{customName}_{cnt:02}'
path = os.path.join(outputDir,addedName,subPath)
cnt+=1
if not os.path.exists(path) :
return path
def makeDictByConfig():
parser = configparser.ConfigParser()
parser.read('config/config.ini', encoding='utf-8')
cfgDict = edict()
for sect in parser.sections():
item = [_refineVal(x) for x in parser.items(sect)]
cfgDict[sect] = dict(item)
cfgDict.path.output_dir = _refineOutputPath(True, cfgDict.path.output_dir, cfgDict.name.custom_model)
cfgDict.path.output_eval_dir = _refineOutputPath(False, cfgDict.path.output_eval_dir, cfgDict.name.custom_model)
return cfgDict
나는 이런식으로 중복된 이름일 때 폴더에 자동으로 번호를 매겨주어 모델을 구분하고, 각종 문자열을 정제하는 함수를 만들어서 사용했다.
그렇게 한다면 main문이나, 다른 아무데서나
def main():
# Call Initialization File
customDict = makeDictByConfig()
# Set Seed
setSeed(customDict.hyperparam.seed)
# Register Dataset
registerDataset(
datasetName = customDict.name.train_dataset,
jsonPath = customDict.path.train_json,
imageDirPath = customDict.path.image_root,
numOfClasses = customDict.general.classes
)
registerDataset(
datasetName = customDict.name.test_dataset,
jsonPath = customDict.path.test_json,
imageDirPath = customDict.path.image_root,
numOfClasses = customDict.general.classes
)
뭐 이런식으로 직관적으로 사용할 수 있다.
추후 Config파일을 Output 폴더 내에 저장하여, 값을 손쉽게 볼 수 있게 만들 예정이다.