AIB Section 2 머신러닝 Part 1
지난 한 달 동안 머신러닝에 대해 배웠다. 배운 내용을 복기하면서 정리해보도록 하겠다. 우선 지금 든 생각인데, 매일 배운 내용을 하나의 포스트로 기록하는 것이 좋을 것 같지만, 이미 지나갔으므로 정리하고 싶은 만큼 정리해보기.
미래를 예측하고 대비하여 추후 이익을 누리려고 대비하는 것은 중요하다. 그래서 어떤 데이터를 보고 어떠한 규칙이 있을 것이라는 것을 생각해서 대입해보면서 결과를 확인해보는 것도 한 가지 방법일 것이다. 그런데 이것은 고전적인 방법이다. 시간이 오래 걸릴 것이고, 미처 확인하지 못 한 부분에 대한 규칙성은 무시될 것이고, 컴퓨터를 수준 높게 활용하지 못 하는 것이다.
머신러닝은 컴퓨터를 활용하여 알고리즘을 통해 컴퓨터가 알아서 규칙을 찾아내어 미래를 예측하는 모델을 생성한다. 사람이 일일이 보는 것보다 시간이 적게 걸릴 것이고, 알고리즘에 따라 복잡한 관계 속에서 규칙을 찾아낼 수도 있을 것이다.
머신러닝에는 지도학습 (supervised), 비지도학습 (unsupervised), 그리고 강화학습(reinforcement)이 있다. 지도학습은 알고 싶은 것이 정해져있을 때, 비지도학습은 그것이 없을 때로 배웠고, 강화학습은 전혀 배운 것이 없는데, 두 학습을 섞은 것 같다. “특정 환경 내에서 컴퓨터의 액션에 보상 혹은 패널티를 주며 예측을 합니다. 가장 많은 보상을 받을 수 있는 전략을 찾아내는 방법입니다.”라고 강의노트가 알려주고 있다. 봐도 모르겠고, 다음주 월요일까지 섹션 리뷰 기간이므로, 내가 게으름을 느끼지 않는다면 찾아봤으면 좋겠다.
섹션 2에서는 지도학습을 다룬다. 알고자 하는 결과인 타겟과 그 타겟을 예측하는데 도움을 줄 수 있는 특성들을 가지고 미래에 있을 특성들에 대한 타겟을 예측하는 것. 특성들로부터 답을 도출해내는 것으로 특성을 독립변수, 타겟을 종속변수라고 부른다.
충분히 많고 다양한 양의 데이터를 학습해야 답을 잘 낼 수 있을 것이다. 나중에 언급할 내용으로 ‘오랫동안’ 학습하지 않아야 답을 잘 낼 수 있는 부분도 있다. 학습한 모델을 검증하면서 성능을 높이는 방향을 찾아보고, 마지막 평가로부터 이를 만족하며 사용할지 다른 방법으로 모델을 다시 구축할지 생각해보아야 한다.
모델을 검증하는 방법은 최소한의 성능을 낼 수 있는 기준모델을 정하고, 그 기준모델과의 평가지표 비교로 성능이 얼마나 더 뛰어난지, 그리고 모델 튜닝으로 내가 정한 모델의 성능을 얼마나 더 올릴 수 있는지 등으로 진행한다. 그리고 타겟의 분포에 대해 적절히 대응함으로써 모델의 성능을 높일 수 있기 때문에 별도의 전처리나 모델 설정도 해준다. 평가지표는 정확하게 맞춘 비율, 잘 설명할 수 있을 확률, 오차 비율 등으로 나타낼 수 있는데, 상황이나 모델 종류에 따라 다른 평가지표를 사용한다. 튜닝은 모델의 방향성을 조정해주어 이전에 보지 못 했던 데이터에 대해 잘 맞출 수 있는 일반화성능을 높이는 것이다.
데이터 셋 자체를 이용해서 일반화성능을 높이는 것으로는 데이터를 훈련, 검증, 평가로 구분하는 것이 있다. 훈련과 검증을 별도로 구분하여 훈련시킨 모델을 검증데이터로 성능을 보거나, 둘을 합쳐서 무작위로 구분하여 평균 성능을 볼 수 있다. 전자는 3-way holdout이라고 하고, 후자는 cross-validation이라고 한다. 물론 맨 끝에 평가 셋의 점수를 별도로 보아야 한다. 그래야 3-way holdout의 세 개로 구분한 것이 되고, CV도 최종 일반화로 평가셋을 이용해야 한다.
일반화 성능과 과대적합/과소적합을 이야기할 수 있다. 과대적합은 모델이 훈련 데이터셋에만 너무 적합하게 되어 검증이나 평가 셋에서 성능이 낮은 것을 말한다. 검증과 평가 오차의 분산이 크다고 볼 수 있다. 일반화를 통해 과대적합을 피할 수 있다. 과소적합은 훈련 셋에서 성능이 좋지 않은 상황으로, 당연히 검증과 평가에서도 성능이 좋지 않다. 이를 편향이 크다고 한다. 일반화를 적당히 하면 과대적합을 피하지만 너무 하려고 하면 과소적합이 생길 수 있다. 일반적으로 복잡도가 크면 (쓸데 없는 특성이 너무 많거나 모델이 너무 세부적으로 데이터를 봄) 과대적합이 일어난다. 반대로는 과소적합이 있고, 또 애초에 데이터가 좋지 않거나 양이 적으면 과소적합이 생긴다.
이제 모델의 종류에 따라 위 내용을 세부적으로 살펴볼 것이다.
수치를 예측하는 모델로 배운 것은 선형회귀 모델이 있었고, 타겟을 이진이나 멀티클래스로 분류하는 모델로는 트리기반 모델이 있었다. 트리기반 모델은 수치도 예측이 가능하다. 다른 종류도 많을 것이고, 각각 장단점이 있을 것인데, 가장 크게는 회귀와 트리기반으로 종류를 생각할 수 있을 것이고, 종류에 따라 별도로 일반화 성능을 높이는 방법도 다르다. 그리고 회귀 문제를 분류문제로 접근할 수 있고, 역으로 분류문제를 회귀문제로 접근할 수도 있다. 예를 들어 수치가 특정 값 이상과 이하로 나누면 이진이 될 것이고, 타겟이 없는 데이터셋 내에서 특성들의 조합으로 분류나 수치형 타겟을 만들어볼 수도 있다. 물론 이때 타겟을 만들어낸 특성들은 삭제해주어야 한다. 타겟이 없는 미래를 예측하는 것이므로, 타겟을 만들어낸 특성 또한 없는 것으로 간주해야 하는 것.
섹션 1에서 경사하강법을 배운 적이 있다. 어떤 것의 최소를 찾는 방법이다. 오차함수에 대해 최소를 찾는다면 오차를 최소로 할 수 있고, 따라서 머신러닝에서 오차를 최소로할 수 있는 모델을 만들 수 있다.
선형회귀는 기본적으로 SSE (sum of squared errors)를 최소화하는 방식으로 모델링을 하여 수치를 예측한다. 실제값과 예측값의 차의 제곱을 최소화하여 이를 더한 것이 최소가 되는 직선을 구하는 것. 다항회귀는 차수가 높을 뿐이지 수학적으로 보면 $ \vec {X} → y $로 대응하는 함수 $ f( \vec {X} ) $가 있을 뿐이라고 생각하고, 다른 종류의 함수로도 피팅도 가능할 것이다.
평가 지표는 MAE, MSE, RMSE, R2가 대표적이다. 데이터 분포에 따라 사용하는 지표가 다를 수 있다. MAE는 이상치에 민감하지 않다. MSE와 RMSE는 제곱하는 부분에서 이상치에 민감하게 된다. R2는 $ SSR \over SST $, 관측치와 평균의 차이 중 예측치와 평균의 차이로, 모델이 데이터를 얼마나 잘 설명하는지의 비율로 볼 수 있고, 공통이다.
이 앞 세 개의 평가지표는 쓰임세가 다르다. 선형회귀에서 규제화를 통해 일반화 성능을 높일 수 있는데, L1 / Lasso regularization과 L2 / Ridge regularization에서 사용하는 오차가 다르다. 둘 다 중요하지 않은 특성의 가중치를 줄이게 된다. L1은 이때 회귀계수 절대값의 합을 줄이는 것을 목표로 하며, 특징으로는 중요하지 않은 특성의 회귀계수가 0이 될 수 있다. L2는 회귀계수 제곱의 합을 생각하며, 중요하지 않은 특성의 회귀계수가 0에 가까워지지만, 0이 되지는 않는다. 둘 다 섞어서 elastic regularization을 할 수도 있다. 특성이 너무 많아서 불필요하다고 느끼면 L1으로 제거, 특성을 제거할 수 없고 이상치에 대한 가중치를 더 줄이고 싶다면 L2를 이용한다고 생각해볼 수 있어서, 관심 있는 평가지표가 달라진다. 그리고 주의할 점은 회귀계수는 숫자고, 스케일링을 하지 않는다면 그 차이가 심하다. 수식에서 단위를 자체적으로 고려하지 않기 때문에 그대로 규제화를 진행한다면 계수가 작은 특성은 단지 숫자가 작기 때문에 규제화 대상이 되어버린다. 따라서 스케일링 필수. $ 오차함수 = 원래 오차함수 + \lambda \sum L_x $ 에서 어느 정도 패널티 ($ \lambda $)를 부과하느냐에 따라 계수 줄이는 강도를 조절할 수 있는 것을 확인할 수 있다.
회귀모델 중 Logistic Regression이 있다. S자 Z자와 비슷한 형태로 되어 값을 아래 값과 위 값으로 구분할 수 있게 된다. 그래서 회귀 모델이지만 수치를 예측하지 않고 분류를 한다. 다만 Linear Regression에서부터 sigmoid 변환을 통해 함수를 얻기 때문에 회귀 모델이다. regularization 또한 가능하다. 그래서 회귀모델과 회귀문제를 구분할 필요가 있다. 회귀모델은 logistic 포함, 회귀문제는 수치형 타겟에 대한 문제이다.
트리 기반 모델이 있다. 나무가 가지를 뻗어나가듯 모델이 특성의 어떤 값을 기준으로 갈래를 나누어 분류하게 된다. 전체 오차를 최대한 줄여줄 수 있는 특성을 선택하여 분기하게 된다. 나누어서 분류하긴 하지만, 숫자가 이보다 큰지, 작은지 기준으로 나눌 수도 있기 때문에 수치형 타겟에 대해서도 사용 가능하다. 사용하는 오차로는 대표적으로 impurity와 entropy가 있다.
Impurity: 분기점에서 혼합된 데이터가 있을텐데, 혼합된 비율이 비슷하면 impurity가 높고, 어느 값이 비율이 높고 다른 값이 비율이 낮으면 impurity가 낮다. impurity를 더 낮춰줄 수 있는 특성을 선택한다.
Entropy: 엔트로피는 정보량이다. 자세히 배우지는 않았지만, 정보량이 많이 감소하면 그만큼 정보를 잘 쓴 것이기 때문에 그 특성을 기준으로 분기한다.
트리 기반 모델 중 가장 단순한 것으로 Decision Tree가 있다. 한 번 모델을 만들 때 선형회귀의 규제화 같은 제한 없이 impurity가 많이 줄어든 것을 선호한다. 따라서 훈련으로 주어진 데이터가 약간만 차이가 있어도 impurity가 줄어드는 정도가 각각 다르다면 전혀 다른 모양의 트리가 만들어지게 된다. 따라서 과대적합의 문제가 크다.
이를 해결하기 위해 앙상블 모델을 사용한다. 트리를 여러 번 만들어서 평균을 내거나, 트리를 점차 강화시키는 방법 등이 있다.
여러 번 독립적인 트리를 만들어서 모아서 보았을 때 회귀문제의 경우 평균값을 계산하고, 분류문제는 더 많은 모델이 선택한 범주로 예측하는 것이 Random Forest이다. 일반화 성능을 더욱 높이기 위해 Bootstrapping을 한다. 따라서 B + AGGregating (모으기)라고 해서 bagging이라고 한다.
트리를 점차 강화시키는 것으로는 Gradient Boosting이 있다. 처음에는 아주 단순한 트리를 만들어서, 이 트리가 예측한 결과가 틀린 것이 있으면 그 틀린 것에 가중을 두어 다음 모델을 만든다. 즉 잔차를 학습하는 것이다. 모델을 계속 반복적으로 만들수록 잔차가 줄어드는 효과를 기대하는 것이다.
평가지표는 Accuracy, Precision, Recall (Sensitivity), F1, ROC (ROC_AUC), P-R (AP score), 그리고 Confusion matrix가 있다. Accuracy는 실제 값을 얼마나 잘 맞추었는지, precision은 예측한 것 중에서 실제 맞춘 비율, recall은 실제 중에 맞게 예측한 비율, F1은 이 둘의 조화평균, ROC는 TPR과 FPR의 그래프로 FPR이 작고 TPR이 큰 것을 확인, P-R은 precision recall이 둘 다 커지는 것을 확인, confusion matrix는 TP, TN, FN, FP를 보는 매트릭스이다. 괄호 친 것은 그 그래프 아래 면적이 큰 것이 좋은 성능이다는 것으로 면적을 수치화한 것이다. 타겟 비율이 일정할 때 Acc, ROC를 보고, 그렇지 않을 때 F1과 P-R을 본다. Confusion matrix는 잘 맞추는지 그렇지 않은지 한 눈에 보는 용도로 항상 보게 된다. 그리고 Precision과 Recall은 도메인마다 중요하게 판단하는 것이 무엇인지에 따라 더 중요한 지표로 판단한다.
지표에 따라 성능을 높이기 위해 eval_metric에 넣거나 하는데, 라이브러리마다 약간씩 차이가 있으므로 확인 필수다. 애초에 점수를 더 높일 수 있는 것은 모델을 순차적으로 만드는 boosting 모델에 해당하는 것이므로 RF와 DT는 이것이 없다. 하지만 별도로 CV를 통해 확인해볼 수 있다. 그리고 모델 한 번에 얼마나 학습할지에 대한 learning rate, 어디까지 분기하고 멈춰서 일반화를 높일지에 대한 max_depth, 몇개가 있어야 분기할지에 대한 파라미터, 칼럼 일부, 측정치 일부 등 다양한 하이퍼파라미터가 있다. 회귀모델에서 규제화를 어느정도 할지에 대한 것으로 패널티 강도를 조절했다면, 트리기반 모델에서는 위 하이퍼파라미터를 조절한다. 라이브러리마다 이름이나 애초에 사용 가능한지 여부가 다를 수 있으니 또한 확인 필수.
불균형의 경우 성능을 높이기 위해 타겟 분포를 조절해준다. undersampling으로 많은 데이터를 손실한다는 것을 감안하여 적은 데이터와 비슷한 개수로 맞춰준다. oversampling으로 적은 데이터를 많은 데이터 개수만큼으로 맞춰준다. SMOTE로 적은 데이터를 범위 내에 interpolate시켜 많은 데이터 개수만큼으로 맞춰준다. SMOTE 후 노이즈가 너무 많은 부분을 undersampling해주는 것 등이 있다. 앙상블 모델로 무작위로 언더샘플링을 여러 번 해볼 수 있다. weight
종류의 하이퍼파라미터를 조정해줄 수도 있다. 또한 ROC/P-R에서 최적의 threshold를 구해 적용해볼 수도 있다. Highly imbalanced data는 별도 기법이 있다고 한다. 한 번 찾아보면 좋을 듯.
회귀 모델과 트리 기반 모델은 각각 장단점이 있다. 회귀 모델은 숫자로 모델을 표현하기 때문에 아주 쉽게 무슨 특성이 얼마만큼 영향을 주는지 확인할 수 있다. 하지만 식이 기본적으로 선형회귀를 기반으로 하고 있기 때문에 선형회귀의 특성상 특성들의 관계가 독립적 (y는 특성들의 선형결합)이어야 한다. 서로 독립적이지 않다면 (y는 특성의 선형결합이 아니라 곱셈 나눗셈 등으로 나타남) 당연히 선형회귀 식으로 나타내면 오차가 커지게 될 것이다. 그래서 EDA에서 그 관계 포착해서 상관관계를 없애버리는 (합치거나 빼거나 어떻게 해서 y를 선형 결합 형태로 나타낼 수 있게, 또는 아주 잘 파악하고 있어서 각각의 변수마다 y를 어떤 식으로 나타내는지 별도 관계로 피팅) 사전작업이 필요하다. 그리고 숫자를 수식화하기 때문에 범주형 타겟을 수치형으로 인코딩할 때 무작위 순서를 부여하더라도 (ordinal encoding) 그 순서를 큰 값/작은 값으로 인식하는 오류가 생긴다. 따라서 이 특성의 어떤 범주 1에 해당하면 범주_1은 1, 범주_not_1은 0 등으로 one-hot encoding을 해주어야 한다. 또 수식화할 때 결측치를 인식할 수 없으므로 결측치를 별도 방법으로 처리해주어야 한다. 그리고 일반적으로 정규분포의 타겟이 성능이 더 좋아질 것이라는 기대로 target count distribution을 정규분포로 맞추기도 한다. 회귀모델은 monotonic하고 분산이 적은 것에 대해 잘 맞추고 수식도 주기 때문에 이 경우 트리 기반보다 나을 수 있다. 강의노트에서 monotonic이라고는 했지만 특성에 따른 타겟 분포가 다항회귀나 특수함수 형태를 띄는 것을 포착한다면 이 경우도 회귀모델이 좋은 성능을 낼 수 있을 것 같다. 물론 특성마다 타겟과의 관계가 다를 수 있으므로 무척 어려울 것이다.
트리 기반 모델은 특성의 크기와 분포에 큰 영향을 받지 않는 것으로 알려져 있다. 첫 번째 강사님이 강의할 때 영향이 없으므로 ordinal encoding이 시간도 더 적고 이걸 사용하라고 하셨다. 하지만 두 번째 강사님은 one-hot encoding을 하라고 하셨다. 이는 분기를 거듭하면 할수록 그 영향이 적어지는 것으로, 과적합을 피하기 위해 max_depth를 조절한다면 그 영향이 클 수도 있다고 이해가 된다. 따라서 ordinal encoding 말고 one-hot encoding을 해볼 필요도 생김. count encoding, target encoding이라는 것도 있는데, 특성의 범주 비율에 따라 수치 부여하거나 타겟의 평균에 따라 (0과 1의 개수의 비율로 이해) 수치를 부여하는 것이다. count는 동일한 비율에 대해서 동일한 숫자가 부여된다는 것이 문제가 되며, 미래 수집할 데이터에 대응하지 못 한다. target은 말 그대로 타겟에서부터 정보를 얻어오기 때문에 data leakage가 어느 정도 있는 셈이며, 그 수치를 부여받은 특성의 전부 다 같은 타겟은 아닐 것의 문제도 있다. target의 문제를 해결하기 위해 특성 출현 빈도도 함께 고려하는 방법이 있는데, 이게 어떻게 도움이 되는지는 잘 이해가 되지 않는다. 또 라이브러리에 따라 결측치를 자체적으로 다른 하나의 값으로 처리하여 모델이 정상적으로 작동할 수 있다. 그리고 특성들 간 관계성이 있어도 이것이 잘 반영되어 좋은 결과를 줄 수 있다. 특성들 간 상호작용이 있을 때 선형회귀보다 트리 기반이 나을 수 있다. 하지만 방대한 데이터 양에 대해 효율적인 학습을 위해 애초에 상관관계를 포착해 처리해줄 수 있으면 좋을 것이다. 모델 해석과도 관련되기 때문이다.
모델이 단순히 결과가 좋다라는 것 외에 왜 그렇게 분석했는지 알아볼 필요가 있다. 고객에게 이를 요구하기 때문이고, 그 결과를 분석해서 성능을 더 높일 수도 있기 때문이다. 회귀 모델의 경우 함수가 나오기 때문에 그 회귀 계수 크기에 따라 중요도를 판단할 수 있고, 증가/감소 방향도 알아볼 수 있다. 트리기반의 경우 특성 중요도를 통해 impurity/entropy/잔차가 얼마나 많이 감소했는지 순으로 특성이 더 중요한 것을 생각해볼 수 있다. 하지만 불순도가 감소하는 것은 애초에 데이터에 노이즈가 많으면 그만큼 더 감소시키려는 횟수가 많을 것이기 때문에 이 점을 유의해야 한다. 가끔 헷갈리는데, Feature Importance의 가장 기본적인 Mean Decrease in Impurity를 Feature Importance라고 부르기도 한다. 어느 특성이 더 중요한지에 대한 의미로 DCI, PI를 포함해 FI라고 부를 수도 있겠다.
모델과 상관 없이 Drop-Column Importance, Permutation Importance, 그리고 Partial Dependency Plot를 볼 수 있다. CI는 특정 특성을 삭제후 재학습, PI는 재학습 없이 특정 특성에 노이즈를 주어 성능이 많이 떨어지는 순으로 중요도를 매긴 것이다. 재학습하지 않은 PI가 더 빠르다. 없기 때문에 성능이 더 올라간다면 그 중요도는 음수로 나타날 것이다. PDP는 다른 특성은 고정시키고 보고자 하는 특성을 변화시켜 결과가 어떻게 달라지는지 보는 그래프이다. 작동 원리를 조금만 더 설명하자면, 하나의 측정치에 대해 보고자 하는 특성의 값을 그 특성 전체 범위에 대해 iteration시켜 그래프를 나타낼 수 있는데, 이를 모든 측정치에 대해 진행해서 그 평균 양상을 보는 것이다. 당연하게도 범위 내에 특정 구간에만 측정치가 많고 나머지는 없거나 하면 그 없는 부분에 대한 예측값이 이상할 것이다. 그리고 이 세 가지 모두 특성들 간 상관관계가 크다면 문제가 있다. DCI의 경우 하나를 삭제해도 다른 하나에서 정보가 있기 때문에 중요도가 크다고 보지 않는 경우도 생김. 그래서 그 상관관계 큰 특성들을 삭제하고 다시 모델링하면 성능 엄청 떨어져 있을 것이다. PI는 상관관계가 큰 데이터인데, 노이즈를 주면 상관관계를 없애버리기 때문에 비현실적인 데이터로 이루어진다는 문제가 생긴다. PDP도 마찬가지이다.
여기까지 내가 생각하기로 중요한 개념을 다 말로 정리한 것 같다. 아마 Part 2에서 라이브러리 목록 작성으로 마무리하지 않을까 싶다.
댓글남기기