KNIME에서 하이퍼파라미터 튜닝 실습
KNIME에서 Parameter Optimization Loop Start 노드와 Parameter Optimization Loop End 노드를 활용하여 하이퍼파라미터 tuning하는 방법을 알아보겠다.
KNIME 내에서 Loop의 개념과 Flow Variables에 대한 개념을 알고있어야하는데, 이전 포스팅에 설명해두었다.
2024.08.28 - [KNIME] - [KNIME] Loop 실습(1)
2024.08.28 - [KNIME] - [KNIME] Loop 실습(2)
2024.08.29 - [KNIME] - [KNIME] Loop 실습(3)
활용할 데이터는 KAMP에서 가져온 데이터로, 간단한 전처리는 이미 완료된 데이터이다.
CSV Reader 노드로 데이터를 불러온다.
28,183건의 행과 4건의 열로 이루어져있다.
콘텍트 렌즈의 내측 곡률(IN_RADIUS)과 외측 곡률(OUT_RADIUS)로 도수(REAL_POWER)를 예측하는 Regression 데이터이다.
컬럼명 | 설명 |
MFG_DT | 렌즈 제조 일자 |
REAL_POWER | 도수 |
IN_RADIUS | 내측 곡률 |
OUT_RADIUS | 외측 곡률 |
이 데이터를 Train, Validation, Test Set으로 나누고
Random Forest 모델을 활용하여 Hyper Parameter를 최적화하는 과정을 KNIME으로 실습해보도록 하겠다.
MFG_DT 컬럼은 날짜인데 String 타입으로 되어있으므로 String to Date&Time 노드를 활용하여 타입을 변경한다.
(String to Date&Time 노드에 대한 설명은 여기에 있다.)
옵션창 켜서 대상이 되는 MFG_DT만 Include에 남겨주고
New type은 날짜만 있으므로 Date로 설정한다.
Date format은 "yyyy-MM-dd" 로 직접 설정해주거나 Guess data type and format을 눌러도 된다.
(가끔 Guess data type and format이 안먹힐 때가 있으므로 Date format에 대한 기본적인 이해가 있는게 좋다.)
그리고 MFG_DT 컬럼을 기준으로 오름차순 정렬해준다.(Sorter 노드 사용)
이제 Train, Validation, Test set을 나눌건데 일단
1. Train, Test Set을 먼저 나누고
2. 그 다음에 Train set을 다시 Train set과 Validation set으로 나누도록 하겠다.
해당 데이터는 제조일자가 존재하는 시계열 데이터이다. 만약 Random 하게 데이터를 나누면 미래 데이터를 학습하여 과거 데이터를 예측하는 꼴이 되어버려 현실에 적용할 수 없는 모델이 된다.
따라서 어떤 시점을 기준으로 이전 시점을 train set으로, 이후 시점을 test set으로 데이터를 나누도록 한다.
데이터가 2020-01-02부터 2021-04-25 까지 존재하므로 20년도 데이터를 train set으로, 21년도 데이터를 test set으로 활용하겠다.
Date&Time-based Row Filter 노드로 먼저 train set을 나눠준다.
MFG_DT 컬럼에 대해
시작 시점(Start)을 2020-01-01부터
종료 시점(End)은 날짜(Date&Time)로 지정해도되고(2020-12-31), 혹은 기간(Duration)으로 지정해도 된다.
기간으로 지정 시에는 2020년 1월 1일부터 1년으로 1y로 입력한다.
동일하게 Test set도 나눠주기 위해 Date&Time-based Row Filter 노드를 사용한다.
MFG_DT 컬럼에 대해 시작 날짜는 2021-01-01 부터로 설정하고,
End 날짜는 따로 지정해주지않으면 남은 모든 기간의 데이터로 인식된다.
이제 하이퍼파라미터 튜닝을 위해 train set을 다시 train set과 validation set으로 나눠준다.
train set을 나눈 Date&Time-based Row Filter 노드에 이번에는 Partitioning 노드를 붙여준다.
(똑같이 Date&Time-based Row Filter 노드를 사용해도 무방하다.)
train set 내에서 다시 train set과 validation set을 나눠주는데, 8:2 비율로 나눠주고(Relative : 80)
시계열 데이터이므로 random하게 나누지 않고 위에서부터 순서대로(Take from top) 데이터를 나눈다.
First partition이 80%로 지정한 train set이고 옆에 Second partition이 나머지 20%인 validation set에 대한 결과이다.
Partitioning 노드 오른쪽에서 위에 삼각형이 First partition(train set)이며, 아래 삼각형이 Second partition(validation set)을 의미한다.
이제 train set에 Random Forest Learner(Regression) 노드를 연결하고
validation set에 Random Forest Predictor(Regression) 노드를 연결한다.
그리고 Random Forest Predictor(Regression)에 Numeric Scorer 노드를 연결하여 예측값에 대한 성능도 확인할 수 있도록 한다.
데이터는 삼각형으로 연결하고 모델은 사각형으로 연결한다.
Learner 모델을 Predictor 노드에 연결해주어야 학습시킨 모델을 활용하여 validation set에 대한 예측을 수행할 수 있다.
Learner 노드의 옵션창으로 들어가서 Target Column을 REAL_POWER로 설정한다.
변수는 나머지 IN_RADIUS, OUT_RADIUS 모두 사용하는걸로 하겠다.
그리고 아래 Tree Options와 Forest Options가 바로 Hyper parameter이다.
즉, 모델이 스스로 학습하는 값이 아니라 학습 전, 사람이 직접 설정해주어야 하는 값이다.
Tree Options에 있는 Limit number of levels(tree depth)는 tree의 깊이를 정해주는 값이고
Minimum node size는 자식 노드가 최소 n 개 이상의 데이터를 가질 때만 노드를 분할하겠다 에서 n을 정해주는 값이고
Forest Options에서 Number of models는 몇 개의 tree 모델을 앙상블 할 지 정해주는 값이다.
참고로 Tree option 중에 노드가 분할되기 위해 필요한 최소 샘플 수에 대한 옵션을 설정 해 줄 수 있는데 이 값은 Minimum node size의 최소 두 배 이상 값을 무조건 가져야 한다.
(위 옵션창에는 이 값을 설정해주는게 없는데 이따 하이퍼파라미터 튜닝 시 이 이유로 에러가 난다.
KNIME 커뮤니티에 올라온 글에 의하면 해당 노드를 다른 노드에서 발전시켜 만들었는데, 그때 제대로 수정이 이루어지지 않았던 것 같다고 한다.)
이제 Parameter Optimization Loop Start 노드와 Optimization Loop End 노드로 최적의 하이퍼파라미터값을 찾는다.
Flow Variables로 값들을 주고 받는 노드라서 빨간색 점끼리 연결한다.
Learner 노드에 하이퍼파라미터 값을 전달해야 하므로 Start 노드와 Learner 노드를 연결하고
성능을 최대화 할 수 있는 최적의 하이퍼파라미터를 찾는 것이 목적이므로 성능을 계산하는 Scorer에 Loop End 노드를 연결한다.
Parameter Optimization Loop Start 노드의 옵션창을 열어 + Add new parameter를 눌러 최적화 하고 싶은 파라미터들을 등록한다.
네 가지 파라미터를 등록한다.
1. nTrees : 앙상블 할 tree 갯수
2. treeDepth : tree 깊이
3. mcs : minimum child size
4. mns : minimum node size
이름이 헷갈릴 수 있는데 mcs가 Learner 옵션창에서 minimum node size를 의미하며(자식 노드가 최소 n 개 이상의 데이터를 가질 때만 노드를 분할하겠다 에서 n)
mns가 노드가 분할되기 위해 필요한 최소 샘플 수를 의미한다.
Start value, Stop Value, Step size는 몇 부터 몇까지, 몇 씩 건너뛰며 값을 탐색할거냐는 의미이다.
아래 이미지에서 nTrees를 10부터 200까지 30씩 건너뛰며 탐색하겠다고 설정해주었으므로
10, 40, 70, 100, ..., 190을 탐색한다.
트리 갯수가 몇개인지, 깊이가 몇 인지 등 모두 소숫점을 가질 수 없으므로 Integer? 에 체크해준다.
각 파라미터를 탐색 할 때 어떤 방식으로 탐색할지를 Strategy settings에서 설정해 줄 수 있다.
네 가지 파라미터 모두 Hillclimbing으로 설정해주었다.
네 가지 방식에 대한 간단한 설명은 다음과 같다.
그리고 mns 값은 mcs 값의 무조건 두 배 이상이어야 하므로 해당 조건을 Math Formula (Variable) 노드로 설정해주겠다.
(어떤 데이터에 대한 수식이 아니라 Flow Variable에 대한 수식이므로 그냥 Math Formula 노드가 아니라 뒤에 (Variable)가 붙은 노드를 사용한다.)
Loop Start 노드를 실행하고 해당 노드를 연결한다.
Math Formula (Variable) 노드 옵션창에 들어가서 mns 값을 다음과 같이 대체한다.
if문을 사용하여 만약 mns 값이 이미 mcs 값의 두 배 이상이면 mns 값을 그대로 사용하고, 그렇지 않으면 mns 값을 mcs*2 값으로 대체한다는 수식이다.
if($${Imns}$$ >= $${Imcs}$$*2, $${Imns}$$, $${Imcs}$$*2)
새로운 변수를 생성하는게 아니라 mns 값을 대체하는 것이므로 아래 Replace Variable로 설정하고
해당 값은 정수의 값만 가지므로 Conver to Int 옵션을 체크한다.
이제 이렇게 설정한 하이퍼파라미터값을 Flow Variables로 Learner 노드에 전달한다.
Learner 노드 옵션창을 켜서 위에 Flow Variables 탭으로 넘어간다.
maxLevels에 treeDepth, minNodeSize에 mns, minChildSize에 mcs, nrModels에 nTrees를 설정한다.
(mns는 Options 창에 설정하는게 없지만, mcs만 설정하고 mns는 설정하지 않으면 에러가 나니 꼭 둘 다 설정해주어야 한다.)
이제 Loop End 쪽을 설정해주어야 하는데
최적의 하이퍼파라미터 조건이 성능 최대화이므로 어떤 성능값을 사용할 건지 정해주어야 한다.
그 전에 Numeric Scorer에 Target컬럼과 Prediction 컬럼을 설정해주고 계산된 성능값을 Flow variables로 넘겨주겠다는 옵션을 체크한다.
이제 Parameter Optimization Loop End 옵션창을 켜 어떤 성능지표를 최적화에 사용할지 설정한다.
R^2나 adjusted R^2의 경우는 값이 클 수록 성능이 잘 나오는 것이므로 maximized로 설정해주고, 나머지는 값이 작아야 성능이 잘 나오는 것이므로 minimized로 설정한다.
mean squared error를 목적함수로 설정하고 minimized하도록 설정하겠다.
이제 모든 준비가 완료되었다. Loop End 노드를 실행한다.
(Random Forest Learner(Regression) 노드나 Math Formula (Variable)의 결과창 중 Flow Variables를 누르면 실시간으로 현재 실행되고있는 하이퍼파라미터 값을 확인 할 수 있다.)
Loop End 노드의 결과창 중 첫 번째 결과창(Best parameters)는 탐색한 조합들 중 최적의 조합을 보여준다.
nTrees가 118이고, treeDepth가 11이고, mcs가 10이고 mns가 17일 때 Objective value(mean squared error) 값이 0.388로 최적의 조합이라는 뜻이다.
단, nTrees를 10부터 200까지 30단위로 탐색하라고 설정했으나,
최적값이 10, 40, 70, ..., 190 중 하나가 아니라 118인 이유는 Hillclimbing 기법이 가장 초기값은 random하게 결정하는데, 그 때 설정된 초기값으로부터 30씩 건너뛰며 탐색했기 때문이다.
또한 mns값은 mcs값의 최소 두 배 이상이어야 하는데 mcs값이 10이고 mns값이 17인 이유는
사실은 모델에 적용된 mns값은 20으로 Math Formula (Variable) 노드에 의해 보정된 값이나, 맨 처음 Parameter Optimization Loop Start 노드에서 전달한 값이 17이기 때문이다.
즉, 최종적으로 모델에 적용된 mns값은 20이다.
Loop End 노드의 결과창 중 두 번째 탭은 모든 탐색 결과를 보여준다.
다른 조합일 때의 결과도 함께 확인할 수 있다.
이제 이렇게 찾은 최적의 하이퍼파라미터 조합을 맨 처음에 나눴던 최종 Test Set에 적용하여 성능을 확인한다.
Train Set과 Validation Set을 합친 데이터로 학습해도 되고, Train Set에만 학습해도 된다.
Train Set과 Validation Set을 합친 위에 Date&Time-based Row Filter 노드에 Random Forest Learner(Regression) 노드를 연결하고
Test Set인 아래 Date&Time-based Row Filter 노드에 Random Forest Predictor(Regression) 노드를 연결한다.
성능 확인을 위해 Predictor 노드에 Numeric Scorer 노드도 연결한다.
그리고 KNIME 측의 개발 실수로 minChildSize는 옵션창에서 설정할 수 있으나, 노드가 분할되기 위해 필요한 최소 샘플 수(minNodeSize)는 Flow Variables로밖에 설정 할 수 없어서
Integer Configuration 노드를 추가하여 Learner 노드에 연결해준다.
Integer Configuration 노드 옵션창으로 들어가서 mns 파라미터를 설정한다.
Parameter Name을 mns로, Default Value를 찾은 최적값인 20으로 입력한다.
Learner 노드 옵션창 들어가서 찾은 최적의 하이퍼파라미터값들을 설정해준다.
mns는 Flow Variables로 넘겨준다.
Learner, Predictor, Socrer 노드 모두 실행시키고 성능을 확인한다.
최종 데이터에 대한 성능을 확인할 수 있다.
'KNIME' 카테고리의 다른 글
[KNIME] Loop 실습(3) (0) | 2024.08.29 |
---|---|
[KNIME] Loop 실습(2) (0) | 2024.08.29 |
[KNIME] Loop 실습(1) (4) | 2024.08.28 |
[KNIME] String to Date&Time 노드 실습(format 설정) (4) | 2024.08.27 |
[KNIME] 엑셀(xlsx) 파일 읽기 :: Excel Reader (0) | 2024.08.27 |