[Algorithms] 머신러닝에서 SMOTE 라이브러리를 통해 데이터 불균형 해소하기: 데이터 수 증가 및 감소
포스트 난이도: HOO_Middle
# 데이터 수가 중요한 거지 데이터의 균형이 왜 중요한가요?
Machine learning (ML)를 돌리다 보면 충분한 수의 데이터가 마련되지 않는 경우가 있다. 특히 산출하려는 결과가 하나가 아닌 여러 기준을 둔 채 나눠서 산출하려고 한다면 각 기준에 맞는 데이터 수가 필요하다. 예를 들어서 우리가 예측 모델을 만든다고 한다면, 예측하는 값의 기준을 대, 중, 소로 나눈다거나 아니면 카테고리를 가지고 분류를 한다고 했을 때 각 기준에 맞는 충분한 데이터 수가 필요하다.
"데이터 수만 많으면 되는 건가요?"라고 오해할 수도 있지만 여기서 한가지 더 중요한 점은 "균형 있는 데이터 수"가 필요하다. 균형 있는 데이터 수라는 건 산출하려는 기준에 비슷한 숫자의 학습 데이터 수를 말한다. 인공지능은 마치 어린아이와 같기 때문에 어린아이라고 가정하면 이해하기가 수월하다. 예를 들어서 사칙연산을 처음 배우는 제임스라는 아이에게 덧셈 문제만 10개를 풀게 하고 뺄셈은 1개 그리고 곱셈이나 나눗셈도 1개만 풀어보게 한다면 당연히 제임스는 덧셈을 잘 풀지만 뺄셈은 잘 풀지 못한다. 물론 덧셈과 뺄셈은 연관성이 있기 때문에 어느 정도 풀어내긴 하겠지만 곱셈과 나눗셈은 뺄셈의 경우보다 훨씬 많이 틀릴 수밖에 없다. ML도 마찬가지이다. 우리는 현재 데이터기반 인공지능을 사용하기 때문에 당연히 불균형한 데이터 학습은 특정 산출에 대한 정확도가 높을 뿐 다른 것은 낮은 정확도를 나타내게 된다.
"그게 왜 문제인데요? 한쪽 결과만 일단 잘나오면 좋은 건 아닌가요?"라고 할 수도 있지만 그렇지 않다. 마치 학습량이 많은 기준의 정확도가 높게 나온 것처럼 보이지만 막상 구체적으로 따져보면 다른 기준들이 모호하기 때문에 웬만한 건 잘 학습된 기준으로 결과가 산출된 것을 살펴볼 수 있다. 이게 무슨 말이냐면, 하나만 알고 열은 모른다.라는 속담을 생각해 보면 된다. 다시 제임스라는 어린아이로 인공지능을 가정해 보자. 제임스는 오렌지를 좋아해서 매일 오렌지를 먹다 보니 오렌지라는 단어를 배우게 되었다. 오렌지의 텍스쳐와 맛, 모양, 향 등을 정확히 알고 있다. 어느 날 제임스가 귤을 보거나, 아니면 상큼한 향이 나는 라임이나 레몬을 봤지만 다른 과일들에 대해서 접한 적이 많지 않다 보니 모든 과일을 오렌지라고 부른다. 제임스는 본인이 알고 있는 "오렌지" 기준과 다르다는 걸 알지만 다른 과일에 대해서 모르다 보니 가장 비슷하게 잘 알고 있는 오렌지라고 과일들을 부르는 것이다. 이게 바로 불균형한 데이터 학습이 초래하는 잘못된 결과이다.
결과적으로 인공지능을 학습하는데 있어 "빅데이터"도 중요하지만 비슷한 Scale의 데이터를 학습시키는 것이 중요하다. 한쪽으로 편중되지 않도록 Balance를 유지하여 학습했을 때 정확한 값이 나온다는 것이다.
# 데이터 수를 늘려주기도 하지만 줄여줄 수도 있다.
머신러닝 (ML)에서 데이터 불균형 문제를 해소하기 위한 방법으로 SMOTE를 사용한다. SMOTE는 불균형 데이터셋에서 소수 클래스의 데이터를 합성하여 데이터를 증가시키거나 감소시킬 수 있다. 이 방법은 기존 소수 클래스 데이터를 기반으로 새로운 가상 데이터를 생성하여 데이터 불균형 문제를 해결할 수 있다.
여기서 많은 개발자 브로들이 오해하고 있는 부분 중 하나가 SMOTE는 데이터 수를 증가시켜주는 역할만 한다고 생각한다. 하지만 SMOTE SMOTE의 주요 목적은 데이터 수의 밸런스를 유지해주는 것이기에, 데이터 수를 늘려주기도 하지만 반대로 데이터 수를 줄여줄 수도 있다. 이로 인해 불균한 데이터수를 맞춰서 학습해주는 역할을 수행하게 된다. SMOTE를 처음 다루기 시작한 브로들이 이러한 착각을 하고 있는 가장 큰 이유는 데이터 수를 줄이는 경우로 SMOTE를 사실상 많이 사용하지 않기 때문이다. 일단 ML을 돌린다는 것 자체가 데이터 수가 충분히 확보되지 않았기 때문인데 데이터 수를 늘리기 위해 쓰지 다른 기준의 데이터를 줄여주기에 위해서 사용하는 경우가 드물기 때문이다.
# from imblearn.over_sampling import SMOTE
우선 SMOTE를 사용하기 위해서는 imblearn이라는 라이브러리를 설치해야 한다.
pip install imbalanced-learn
이후에 아래와 같이 모듈을 불러서 사용할 수 있다. 나도 아래와 같은 방법으로 사용한다.
from imblearn.over_sampling import SMOTE
SMOTE를 사용할 경우 인스턴스를 생성해줘야 한다. 아래의 예시는 random_state를 생성한 예이다.
smote = SMOTE(random_state=42)
ML의 다른 라이브러리처럼 x는 특성 데이터, y는 타겟 데이터로 선언이 가능하다.
X_resampled, y_resampled = smote.fit_resample(X, y)
SMOTE를 적용한 후에 클래스 분포가 어떻게 바뀌었는지를 아래의 출력으로 확인이 가능하다.
print("SMOTE 적용 전 클래스 분포:", dict(zip(*np.unique(y, return_counts=True))))
print("SMOTE 적용 후 클래스 분포:", dict(zip(*np.unique(y_resampled, return_counts=True))))
# 정리
이제는 ML의 사용이 정말 쉬워졌다. 처음 인공지능에 대한 관심을 가지고 라이브러리도 없는 상황에서 시작한 나에게 있어서 인공지능 개발이 쉽다는 말은 아무리 검색해도 나오지 않던 시기였다. 하지만 이제는 정말 CS 전공이 아니더라도 누구나 간단한 머신러닝과 인공지능을 사용할 수 있도록 많은 라이브러리들이 생겨났다.
내가 말하고 싶은 점은 본인이 CS 전공자이면서 인공지능 개발자를 꿈꾼다면 좌절하지 말고 별거 아니라고 생각하는 부분마저도 세심하게 다루면 충분히 인공지능 개발자로서의 가치를 찾을 수 있다는 것이다. SMOTE를 외워서 사용하는 게 아니라 어떤 상황에서 응용을 할 수 있는지, 조절이 가능한 부분에서 어떻게 조절해서 정확도를 높여줄 지에 대해서 높은 이해도를 가지고 있어야 한다는 것이다.
언제든지 궁금한 내용이나 질문이 있다면 댓글이나 블로그 하단의 링크드인을 통해서 메세지를 보내주길 바란다.
개발자를 꿈꾸는 브로들 모두 화이팅이다!