Use AutoML for train model
Concept
신경망을 훈련하는데 있어서 최적의 성능을 갖는 하이퍼 파라메터의 조합을 찾는 일은 매우 중요하지만 매우 반복적이며, 많은 시간이 소요되는 작업이다. 우리는 이러한 작업을 사용자의 개입없이 시스템상에서 자동으로 할 수 있도록 하기 위해서 Hyper Parameter Random Search 와 Approximation 을 위한 Genetic Algorithm 그리고 빠른 연산을 위한 복수의 GPU 활용을 위한 분산처리까지 복합적으로 사용하여 사용자의 일을 최소화 하고 있습니다. 실제로 사용자가 해야할 일은 데이터에 대한 인사이트를 가지오 데이터를 정의하고 사용할 알고리즘과 필요하다면 하이퍼 파라메터의 범위를 조정하는 정도의 작업만하면 나머지는 우리의 프레임웍이 자동으로 처리하여 줍니다.
Hyper Parameter Random Search
우리가 하이퍼 파라메터를 탐색하는 방법은 크게 3가지로 나눌수가 있는데, 첫번째는 사용자가 자신의 노하우와 감을 가지고 파라메터를 수작업으로 탐색하는 방법. 두번째는 그리드 서치 방식으로 메트릭스를 구성하고 자동으로 탐색하는 방법. 마지막으로 랜덤으로 하이퍼 파라메터를 탐색하는 방법이 있다. 2012년에 발표된 Random Search for Hyper-Parameter Optimization 을 보면 히든 레이어가 3개 이하인 경우 Grid Search 에 비해서 무조건 월등한 성능을 보여주며, 그보다 복잡한 신경망의 경우 성능이 떨어져 비슷비슷한 결과를 보여준다고 한다. 우리는 랜덤 서치 방식을 채택하여 AutoML에 접목하였다.
Genetic Algorithm
하이퍼 파라메터를 전부 대입하여 딥러닝을 훈련하여 최선의 하이퍼 파라메터를 찾는 다고 생각하면 얼마나 많은 리소스가 소요될지 알 수가 없다. 딥러닝은 기존의 머신러닝 알고리즘 대비 훨씬더 많은 리소스가 필요한 알고리즘으로 전수조사를 한다는 것은 굉장히 비효율적인 접근이 될 것이다. 예를들어 5개의 경우의 수를 갖는 5개의 하이퍼 파라메터를 전수조사로 튜닝을 한다고 생각해보자. 한번의 훈련 및 테스트를 진행하기 위하여 1시간이 소요된다고 생각해 보자. 그러면 전체적으로 소요되는 시간은 5*(5승)*1시간이 될 것이다. 그러면 유전자 알고리즘을 적용한다고 생각해보자. 우리가 수행하려고하는 유전자 알고리즘은 총 5세대, 세대 구성원은 5, 각 세대에서 살아남는 구성원은 2라고 생각해보자. 그러면 총 연산 소요 시간은 5 + 3*4 가 된다. 전수조사에서 찾는 최고의 하이퍼파라메터 셋을 찾을 수는 없지만 그에 근사한 최적의 하이퍼 파라메터를 찾을 수 있다고 기대한다면, 훨씬더 적은 자원을 투자하고 원하는 결과를 얻을 수 있을 것이다.
Gpu Clustering
마지막으로 복수의 GPU 서버를 사용하여 전체 연산 시간을 줄이고자 하였다. 이는 Genetic Algorithm 이 동작하는 방식과 굉장히 효과적으로 접목할 수 있는 개념으로 우리는 GPU 서버의 Job 들을 효과적으로 관리하기 위하여 Celery 라는 솔루션을 내부적으로 연동하고 있다.
APIs – Business Define
import requests import json, os nn_id = 'auto_wcnn037' # put some key value you want to test ####(1) 네트워크 생성 #### resp = requests.post('http://' + url + '/api/v1/type/common/target/nninfo/nnid/' + nn_id + '/', json={ "biz_cate": "MES", "biz_sub_cate": "M60", "nn_title" : "test", "nn_desc": "test desc", "use_flag" : "Y", "dir": "wcnn", "automl_parms" : {}, "config": "N" }) data = json.loads(resp.json()) print("evaluation result : {0}".format(data))
비지니스를 정의하는 작업은 싱글로 수행을 할때와 동일하게 사용자가 정의해주어야 할 필요가 있다. 비지니스를 정의하는 API 는 싱글로 실행할 때와 다른점이 없다.
이때 주의하여야 할 파라메터는 dir Flag 로 어떤 알고리즘을 사용하고자 하는지 지정하는 작업으로 어떤 파라메터를 정의했느냐에 따라 다른 알고리즘이 기동되게 된다.
APIs – See Parameter Format
resp = requests.get('http://' + url + '/api/v1/type/automl/state/rule/graph_id/wcnn/') data = json.loads(resp.json()) print("evaluation result : {0}".format(data))
AutoML 을 사용하여 하이퍼파라메터를 자동으로 서치한다고 하더라도, 하이퍼 파라메터의 범위는 지정을 해주어야 할 필요가 있다. 그리고 정상적으로 동적하게 만들기 위해서는 알고리즘 별로 정해진 형태의 파라메터 포맷을 지정해 줄 필요가 있다. 위의 API 를 통해서 기준으로 정의되어 있는 파라메터 포맷을 조회할 수 있는데, 조심해야하는 것은 graph_id/<type> 부분에 원하는 타입을 지정해 주어야 한다는 점이다.
APIs – Set Parameter range for defined network
{"datasrc": {"type": {"auto": False, "type": "sel", "option": "imgdata"}, "preprocess": {"yolo": {"auto": False, "type": "sel", "option": "N"}, "x_size": {"auto": False, "type": "int", "option": 32}, "y_size": {"auto": False, "type": "int", "option": 32}, "channel": {"auto": False, "type": "int", "option": 3}, "filesize": {"auto": False, "type": "int", "option": 1000000}}}, "evaldata": {"type": {"auto": False, "type": "sel", "option": "imgdata"}, "preprocess": {"yolo": {"auto": False, "type": "sel", "option": "N"}, "x_size": {"auto": False, "type": "int", "option": 32}, "y_size": {"auto": False, "type": "int", "option": 32}, "channel": {"auto": False, "type": "int", "option": 3}, "filesize": {"auto": False, "type": "int", "option": 1000000}}}, "netconf_node": {"param": {"epoch": {"auto": [1, 3, 1], "type": "int", "option": None}, "traincnt": {"auto": [1, 4, 2], "type": "int", "option": None}, "batch_size": {"auto": [1, 2, 1], "type": "int", "option": None}, "predictcnt": {"auto": False, "type": "int", "option": 5}, "predictlog": {"auto": False, "type": "sel", "option": "N"}, "augmentation": {"auto": False, "type": "sel", "option": "Y"}}, "config": {"learnrate": {"auto": [0.0001, 0.1, 0.001], "type": "int", "option": None}, "optimizer": {"auto": False, "type": "sel", "option": "adam"}, "num_classes": {"auto": False, "type": "int", "option": 2}, "layeroutputs": {"auto": [1, 152, 10], "type": "int", "option": 18}, "eval_type": {"auto": False, "type": "str", "option": 'category'}}, "labels": {"auto": False, "type": "list", "option": ['cat','dog']}}}
위에서 조회한 파라메터 값을 수정하여 실제 우리가 정의한 신경망에 set 을 하여준다.
APIs – Genetic Algorithm Hyperparameter
resp = requests.post('http://' + url + '/api/v1/type/automl/state/parm/nnid/' + nn_id + '/', json={ "generation": 3, "population": 3, "survive" : 2 }) data = json.loads(resp.json()) print("evaluation result : {0}".format(data))
신경망의 하이퍼파라메터를 찾기위한 유전자 알고리즘 또한 하아퍼 파라메터를 갖게 된다. 크게 4~5가지 필요한 파라메터가 있을 수 있다.
세대수 : 몇 세대를 진화하여 최적의 하이퍼 파라메터 조합을 찾을 것인가
인구수 : 한 세대에 몇 개의 개체가 존재하는가
생존 : 한 세대에 몇개의 개체가 생존하는가
변형 : 버리는 개체중 몇 퍼센트를 뮤테이션하고 몇 퍼센트를 기존의 우성인자로 조합
클러스터 수 : 최대 사용가능한 GPU 클러스터의 수를 지정한다.
APIs – Run AutoML
resp = requests.post('http://' + url + '/api/v1/type/automl/state/train/nnid/' + nn_id + '/') data = json.loads(resp.json()) print("evaluation result : {0}".format(data))
사전에 필요한 정보에 대한 정의 작업이 끝났으면, AutoML을 실제로 실행하여 준다.
APIs – Monitor Process
resp = requests.get('http://' + url + '/api/v1/type/automl/state/stat/nnid/' + nn_id + '/') data = json.loads(resp.json()) print("[Best] final result of genetic process") for raw in data['best'] : print(raw) print('\n') print("[All] all result by generations") for idx,raw in enumerate(data['bygen']) : print("===Generation : [{0}]===".format(idx)) for idx, l in enumerate(raw) : print(l) print('\n')
Genetic Algorithm 을 실행하면 세대별로 실행이 하나씩 되는데 이 작업의 진행 정보를 위의 API 를 통해서 조회할 수 있다. 정보는 하나의 세대가 종료될 때 업데이트가 됩니다.