정신 차려보니 구글 해커톤 1등이 되어있었다. - Part 2
데이터 엔지니어의 좌충우돌 구글 해커톤 도전, 그 마지막 이야기안녕하세요! 페이히어 데이터 엔지니어 구이헌입니다.
지난 1부 글은 어떠셨나요? 1부에 이어 모델 선정 과정과 파라미터 튜닝 과정에 대해 설명 해볼까합니다. 2부에서는 문제를 해결 과정에서 제가 고민했던 흔적들을 보여드리고, 기술적인 부분을 최대한 쉽게 다뤄볼까 합니다.
🏋️♀️머신러닝은 만능일까? 알맞은 모델을 골라보자.
전 지금까지 여러 딥러닝과 머신러닝 모델들을 잠깐 다룬 적이 있으나, 이러한 머신러닝 모델들이 만능이라고 생각하지 않습니다.
뛰어난 머신러닝 모델을 만들고자 한다면, 깨끗하게 정제된 데이터와 튜닝이 아주 잘 되어야만 하죠.
이번 과제에서 힌트로 제공된 로지스틱 회귀, 랜덤 포레스트, 부스티드 트리 3가지 모델들을 두고 많은 고민을 했습니다. 처음에 저는 인기가 많고, 캐글경연대회에서 많은 우승을 거머쥔 ‘XGBoost’ 모델을 사용할까 했었습니다. 왜냐하면 ‘XGBoost’는 기존 Gradient Tree Boosting 알고리즘에 과적합(overfitting)을 방지하는 기능들이 내장되어 있기 때문이죠!
머신러닝을 하면 마주치게 되는 과적합 문제를 방지하는 기능이 있네요? 하지만 저는 XGBoost 모델을 과감하게 버렸습니다. 왜 그랬을까요?
아래 XGBoost 모델에 대해 간단하게 알아보고, 몇 가지 단점을 함께 살펴보시죠.
🛠 XGBoost(Extreme Gradient Boosting)는 부스팅(boosting) 알고리즘을 기반으로 한 머신 러닝 모델입니다. 부스팅은 약한 학습기(weak learner)를 여러 개 결합하여 강력한 학습기(strong learner)를 만드는 앙상블(ensemble) 방법 중 하나입니다. XGBoost 모델은 이전 학습기의 예측 오차(residual)를 줄이는 새로운 학습기를 반복적으로 추가하여 모델을 학습합니다.
하지만 부스팅 모델은 몇 가지 단점들이 있습니다. XGBoost 모델 역시 아래와 같은 단점을 가집니다.
-
- 과적합: XGBoost 모델은 과적합(overfitting)되기 쉽습니다. 따라서 적절한 규제(regularization)를 사용하여 모델의 일반화 성능을 향상시키는 것이 중요합니다.
-
- 하이퍼파라미터 튜닝: XGBoost는 다양한 하이퍼파라미터를 가지고 있으며, 이들을 적절하게 조정하지 않으면 예측 성능이 저하될 수 있습니다. 하이퍼파라미터 튜닝에는 시간과 노력이 필요합니다.
-
- 메모리 사용량: XGBoost는 대규모 데이터셋에서 높은 성능을 보이지만, 메모리 사용량이 많이 필요합니다. 따라서, 메모리 제약이 있는 환경에서는 사용이 어렵습니다.
-
- 해석의 어려움: 부스팅 모델은 여러 개의 약한 학습기를 결합하여 강한 학습기를 만드는 과정에서 각 학습기의 역할이 모호해집니다. 따라서 모델의 해석이 어렵습니다.
물론 XGBoost 모델은 과적합 방지 기능이 있지만, 1번의 단점과 함께 구글링하다 보면 치명적인 단점을 찾을 수 있습니다. 많은 데이터에서는 좋은 예측 성능을 보이지만, 결정적으로 “작은 데이터에 대해선 과적합 가능성이 있다.” 는 것이죠.
현재 우리는 6000여 개의 레코드(행)를 가지고 있습니다. 6000여 개의 데이터는 과연 많은 데이터 일까요?
또한, 과적합을 방지하기 위해 하이퍼파라미터 튜닝에 시간과 노력을 들여야합니다. 저는 20분의 시간을 로그인 문제로 날려버렸으니, 간단하고 빠르게 처리할 모델이 필요했습니다.
저는 두 가지의 이유로 부스팅 모델을 과감하게 포기하고 다른 모델을 사용하였습니다. 제 주변에 XGBoost를 선택한 다른 분들은 한 번의 학습에 10분이 넘어가네요. 여기저기 곡소리도..? 들리고 있구요! 🥲
저의 선택은요? 로지스틱 회귀입니다!
그렇다면 저는 어떤 모델을 사용했을까요?
이진 분류에서 가장 많이 사용하는 머신러닝 모델로는 로지스틱 회귀를 많이 사용합니다.
로지스틱 회귀에 대해서 간략하게 설명하자면,
🛠 로지스틱 회귀는 이진 분류 문제에서 예측값을 0 또는 1로 출력하는 모델로, 입력 데이터의 선형 결합을 시그모이드 함수를 이용하여 0과 1 사이의 값으로 변환합니다. 로지스틱 회귀는 선형 모델로서 구현이 간단하며, 빠른 속도와 해석력이 우수하다는 장점이 있습니다. 또한, 로지스틱 회귀는 선형 모델 중에서도 성능이 우수한 모델로 알려져 있습니다.
그렇군요, 빠른 속도와 간단한 구현 또한 우수한 성능, 제가 찾던 모델입니다.
그렇다면 빅쿼리를 이용하여 로지스틱 모델을 구현하는 코드를 보여 드릴게요.
‘churned‘을 예측 값(종속변수)으로, 모델 타입은 ‘logistic_reg’(로지스틱 회귀)를 사용하였습니다. 그리고 제가 찾았던 유효한 독립변수들을 함께 넣어주었습니다.
2시간 40분 중 20분은 로그인 문제로 날려버렸고, 유의미한 값을 찾기 위해 1시간의 시간을 소요했습니다. 저에게 남은 건 1시간 20분, 로지스틱 회귀 모델까지 골랐습니다.
시간이 촉박한 만큼, 빠른 속도를 자랑하는 로지스틱 회귀를 잘 이용해야겠죠? 이제부터 파라미터 튜닝을 통해 여러 번 학습을 하며 성능을 최대한 높일 수 있도록 집중해야겠네요!
😉 하이퍼 파라미터 튜닝, 우리 어렵게 생각하지 말아요.
머신러닝을 하다 보면 튜닝 과정이 중요하다고 하죠. 하지만 무엇을? 어떻게? 튜닝한다는 걸까요?
하이퍼 파라미터 튜닝의 의미를 찾으면, 아래와 같은 글을 찾을 수 있습니다.
🛠 모델을 최적화하기 위해 하이퍼 파라미터를 조정하는 과정
‘hyperparameter optimization’이라고도 함
조금 쉽게 풀어볼까요?
하이퍼 파라미터를 조정하는 과정, 이 말은 파라미터(함수) 값을 변경하면서 조정하는 과정을 말합니다. 그렇다면 무엇을 위해서요? 최적화하기 위해서죠!
최적화는 즉, 모델의 성능을 높이는 과정을 말합니다. 그럼 무슨 파라미터가 있나요? 무엇을 건드려야 할까요?
구글 클라우드에서는 이에 대한 공식 문서를 제공해 주고 있습니다. 구글 클라우드 공식 문서를 들어가면 다양한 파라미터들을 볼 수 있을 거예요.
공식 문서에서 코드를 가져와봤습니다. 상당히 많죠?
가장 흔하게 쓰는 튜닝 기법이 무엇일까요?
요즘 핫한 ChatGPT에 물어보겠습니다. (판사님! 해커톤에서는 ChatGPT를 사용하지 않았습니다.🤌) 재미를 위해 물어본 것이니 참고해 주세요!
오! L2 규제와 학습률, 반복 횟수가 나오네요!
이 단어들은 머신러닝 기본서에서도 자주 보이죠. 실제로 많은 파라미터를 사용하지 않고, 일부 파라미터 조정만으로도 좋은 성능을 가진 모델을 만들 수 있습니다.
공식 문서에서 나오는 많은 함수 중, 제가 사용한 함수는 LS_INIT_LEARN_RATE
, L2_REG
이렇게 2개입니다. 실제로 저의 경험을 바탕으로 사용했던 튜닝 기법들을 이용했습니다.
제가 작성한 코드를 같이 볼까요?
아래 제 코드에도 INIT_LEARN_RATE
, L2_REG
가 보이시죠? 이것이 초기 학습률과 규제(Regularization)을 뜻합니다.
초기 학습률과 L2 규제의 수치를 0.001, 0.01, 0.1, 0.2
과 같이 바꾸어 보면서 테스트를 진행했습니다.
모델명을 보면 hackathon.logistic7이라고 적혀있죠? 여기서 7의 의미는 로지스틱 회귀 모델을 7번의 테스트를 해보았다는 뜻입니다. (테스트는.. 훠~얼씬 더 많이 했습니다.)
하이퍼 파라미터 튜닝은 이렇게 여러 번의 테스트를 통해 모델이 좋은 성능을 가지도록 하는 과정이라고 생각하면 쉽습니다.
실제로 일일이 바꿔 보면서 하지 않고도, 그리드 서치(Grid Search), 랜덤 서치(Random Search), 베이지안 최적화(Bayesian Optimization)와 같은 여러 하이퍼파라미터 조합을 통해 최적의 조합을 찾는 방법들이 있습니다. 이 방법들을 하나씩 설명하면 글이 너무 길어질 것 같아, 이런 것들이 있다는 것만 알려 드리고 규제에 대한 설명으로 넘어가 볼게요!
야.. 넌 빠져있어 (feat.Regularization)
모든 파라미터들에 대해 하나씩 설명드리고 싶지만, ChatGPT에서 봤던 규제에 대한 내용을 간략하게 수학식 하나없이! 설명하고자 합니다.
실제 정규화, 규제 등으로 불리는 Regularization(이하 규제.)의 수행 방식은 제목처럼 빠져있어! 하면서 제외시키는 것은 아닙니다. 제가 처음 머신러닝을 접했을 때, 쉬운 이해를 위해 저렇게 외웠거든요.
“규제 방식이 저런 느낌이구나?”하고 이해하면 좋을 거 같습니다.
다른 사람이 “규제가 뭐야?” 하고 물어봤을 때, “넌 빠져있어..”라고 말할 순 없겠죠. 그렇다면, 규제라는 것은 무엇일까요? 그리고 왜 필요할까요?
L1 규제, L2 규제에 대해 간략히 설명해 보도록 할게요.
우선 규제를 적절하게 한다는 것은 매우 어렵습니다. 적정 수준을 맞추기도 힘들지만, 모델이 훈련하는 속도를 늦출 수도 있죠. 하지만 규제를 사용하는 이유는, 전반적으로 머신러닝 모델의 성능을 향상시킬 때에 강력한 기술이기 때문이죠. 위에서도 계속해서 나왔던 단어라 이미 예상하고 계시겠지만, 이 글의 처음부터 지금까지 이야기 해오던 것이 있습니다.
머신러닝을 경험하고 공부하신 분이라면 신경 쓰이는 것 중 하나가 바로! 과적합(overfitting)이죠. 즉, 과적합(overfitting) 문제를 해결하고자 여러 방법들 중 하나입니다.
과적합 해결 방법으로는 학습 데이터양을 늘리거나, 배치 정규화, 모델의 복잡도를 줄이는 등 여러 가지 방법이 있습니다. 이번 글에서는 규제에 대해서만 이어서 이야기 해볼게요.
이미지 출처 : https://en.wikipedia.org/wiki/Overfitting
과적합은 위 사진의 초록색 선처럼 모델이 훈련 데이터를 너무 잘 학습한 나머지, 결과적으로 새로운 데이터로도 제대로 된 학습이 되지 않습니다.
이런 문제에서 규제는 손실 함수에 페널티를 주어 과적합을 방지하는 것을 도와주고, 이로 인해 사진의 검정선처럼 모형이 더 단순해지고 좋아집니다.
그렇다면 이제 궁금증이 생깁니다.
1️⃣ 그럼 L1 규제와 L2 규제, 이 두 개의 차이는 무엇일까요? L1 규제는 어디에 쓰이나요?
L1 규제과 L2 규제는 모두 과적합(overfitting)을 방지하기 위한 정규화(규제) 기법입니다.
그러나 그들 간에는 중요한 차이점이 있습니다. L1 규제는 모델의 가중치(weight)들의 절댓값에 비례하는 비용 함수에 페널티를 줌으로써 규제를 합니다.
L1 규제는 쉽게 이러한 효과들을 기대하는데,
-
- 불필요한 변수(feature)의 가중치(weight)의 무게가 작도록 만들거나
-
- 심지어 0이 되도록 하면서, 몇 개의 중요한 가중치들만 남게 됩니다.
이러한 과정들을 거쳐 해당 변수(feature)를 제거하고 모델의 복잡도를 줄이면서, sparsity(희소성)를 증가시킵니다.
제목과 비슷하게 일부 가중치 0에 가까워지도록 하여 제외시키고 모델의 과적합을 방지하고, 중요한 의미를 가진 값을 살리면서 모델의 정확성에 기여합니다.
2️⃣ 그럼 L2 규제는 어디에 쓰이나요?
L2 규제(regularization)은 가중치의 제곱에 비례하는 비용 함수에 페널티를 추가합니다.
이 방식은 가중치가 작아지도록 만들지만 반드시 0으로 수렴하게 하는 건 아닙니다.
L2 규제 기법은 모델의 가중치를 전반적으로 줄이기 때문에, 모델이 noise라고 불리는 이상치(outlier)에 덜 민감하게 만들어 주어 안정적인 학습을 도와 성능을 향상시키는 데 좋습니다. 그래서 L2규제는 이상치(outlier)에 대해선 L1규제보다 둔감(Robust)합니다. 따라서 이상치에 큰 영향을 받지 않도록 해야 하는 경우에 사용합니다.
저의 소스코드를 다시 보면, L2_REG(L2 규제)를 사용했습니다. 이제 그 이유는 여러분도 충분히 설명할 수 있으시겠죠?
저는 피어슨 상관계수를 통해 의미 있는 변수를 추출하여 모델 학습에 사용하였습니다. 그렇다면 L1보다 L2가 훨씬 유리할 겁니다. 실제로 테스트를 할 때, 점수가 조금 더 높게 나왔고요.
전략적인 측면으로, 제가 유의미하다고 생각했던 변수들이상치에 덜 민감해진다면? 그리고 적정한 가중치를 더해 모델을 학습한다면, 더욱더 좋은 모델이 나올 거라 생각했습니다.
튜닝이 어렵다면? 모델을 쌓아보세요! 🤞
아래 사진과 같이 경연 대회에서는 Private 리더보드의 점수는 5번의 제출 중 2가지를 선택하여 제출합니다. 위에서 설명한 파라미터 튜닝 방법 외에도 좋은 방법이 있습니다. 저는 당연히 처음 선택한 모델 로지스틱 회귀를 제출했습니다.
하지만! 두 번째 모델은 특별한 것을 제출했습니다. 과연 무엇을 제출했을까요?
바로 스태킹 앙상블(Stacking Ensemble) 기법을 이용한 모델입니다! 스태킹 앙상블은 여러 개의 다른 머신러닝 모델을 조합하여 최종 예측을 만드는 앙상블 기법입니다.
저는 로지스틱 회귀 모델과 많은 캐글 우승자가 사용했던 XGBoost 모델을 함께 사용하여 앙상블 했습니다.
우선 스태킹 앙상블은 두 단계로 이루어집니다. 아래 사진과 같이 첫 번째 단계에서는 다양한 머신 러닝 모델들을 학습시키고, 두 번째 단계에서는 이러한 모델의 예측 결과를 사용하여 최종 예측 모델을 학습시킵니다.
이미지 출처 : https://www.varista.ai/en/knowledge/ensemble-learning/
저의 경우 기존 파라미터 튜닝 과정을 거친 로지스틱 회귀 모델과 함께, 파라미터 튜닝 과정을 따로 하지 않은XGBoost 모델로 구성하였습니다. 제가 제출한 것들 중 두 번째로 높은 성능을 보여주었네요.
BigQuery ML의 스태킹 앙상블은 아래 코드와 같이 쉽게 사용할 수 있습니다. 주석에 적혀있듯이, 첫 번째와 두 번째 모델의 예측값을 합쳐 평균을 냅니다.
그렇다면 스태킹 앙상블을 사용하는 이유는 무엇일까요?
다양한 모델을 조합하여 성능을 향상시킬 수 있고, 개별 모델의 약점을 보완할 수 있기 때문입니다. 그렇기에 스태킹 앙상블을 잘 사용한다면, 좋은 성능을 보여주는 모델을 만들 수 있습니다.
🥇 그래서 결과는?
기대를 안 하고 시간에 쫓겨 부랴부랴 제출했는데, 최종 스코어는 0.68715점으로 제목과 같이 1등을 했습니다.
저의 중간 순위는 10위로 마쳤고, 높은 순위는 아니었습니다. 아무래도 공식 리더보드에서는 30%의 테스트 데이터로 평가해서 낮게 나온 것 같습니다.
순위 발표되자마자 저도 모르게 만세를 불렀습니다. 정신 차려보니 정말 1등이었거든요!✌️ (정신이 없는 나머지 소감과 함께 풀이 전략을 설명할 때에, Logistic Regression이 아니라 Linear Regression으로 적어서.. 전략 발표할 때 당황했습니다.)
블로그를 쓰면서 해커톤 순간을 되돌아보니, 아쉬움이 큽니다. 문제 해결해야하니, 데이터를 위한 EDA 과정이나 파라미터 튜닝 과정에서 놓친 부분들이 많은 것 같아서요.
놓친 부분과 별개로 아직까지 저는 머신러닝에 대해 부족한 부분들이 있고, 공부할 것들이 산더미처럼 쌓여있죠. 더욱더 스스로 발전하기 위해서도 열심히 공부해야겠죠?🥹
프로그래머이자 공상 과학 소설가인 Daniel Keys Moran의 명언으로, 데이터 엔지니어의 좌충우돌 구글 해커톤 도전기를 마무리할까 합니다.
출처 : https://www.azquotes.com/quote/603299
💡 정보 없이 데이터를 가질 수 있지만, 데이터 없이 정보를 가질 수는 없다.
페이히어에서는 쌓여가는 데이터 속에서 숨은 가치를 발견하고, 고객들이 더욱 사랑하는 서비스, 그리고 새로운 미래를 만들고자 하는 동료들을 기다리고 있습니다.
긴 글을 읽어 주셔서 감사합니다 :)