실제로 사용되는 큰 데이터셋을 사용할 때, 소수 클래스가 존재한다면 AI가 올바르게 훈련하지 못할 수 있습니다. 특히나, 그 소수 클래스가 이외의 클래스들보다 중요한 데이터일 경우, 이는 재현율(Recall)이 낮아지는 가치가 없는 모델이 될 가능성이 높습니다. 오늘은 이를 해결하기 위한 SMOTE와 SMOTEENN 샘플링 기법을 설명하려고 합니다.
목차
1. SMOTE 개념 및 특성
2. SMOTEENN 개념 및 특성
3. 코드 적용
4. 분석
#1 SMOTE (Synthetic Minority Over-sampling Technique) 개념 및 특성
SMOTE란 데이터를 학습하는 머신러닝 분야에서 불균형 데이터셋 문제를 해결하기 위해 널리 사용되는 오버샘플링(Over-sampling) 기법입니다. 이는 소수 클래스의 데이터를 인위적으로 생성하여 데이터의 균형을 맞춤으로써 모델의 예측 성능을 향상시킵니다. 불균형 데이터 문제를 꼭 해결해야하는 이유는 무엇일까요?
소수 클래스 탐지 불가
실제로 우리가 데이터 분석을 할 때, 데이터의 클래스 비율이 현저하게 차이 나는 경우가 많습니다. 예를 들어, 의료 분야에서는 결과가 정상일 때 보다 질병인 경우가 많고, 제조업에서 불량품 검출을 할 때 불량인 제품의 수가 극소수일 수가 있습니다. 이들은 소수 클래스(질병, 불량)의 데이터가 전체의 극히 일부에 불과합니다. 이러한 불균형 데이터로 모델을 학습시키면, 모델은 다수 클래스에 편향되어 예측하는 경향을 보입니다. 즉, 대부분의 데이터를 '정상'으로만 판단해도 높은 정확도(Accuracy)를 보이게 되지만, 정작 중요한 소수 클래스는 제대로 탐지하지 못하는 심각한 문제가 발생합니다.

위의 <그림 1>에서는 Imbalanced Data에서 빨간색 클래스의 수가 파란색 클래스의 수에 비해 너무 적습니다. 이 상태로 데이터를 훈련하게 되면, 파란색 클래스에 편향되어 예측을 하기 때문에, 모든 예측을 '파란색일 것이다!'라고 예측을 해도 정확도는 굉장히 높게 나올 것입니다. 따라서 <그림 1>의 Over-sampling처럼 빨간색 클래스의 숫자를 파란색 클래스의 숫자와 비슷하도록 개수를 늘려줘야 합니다.
SMOTE 작동 방식
무작정 클래스를 복제해서 오버샘플링(Over-sampling)을 하게 되면 어떻게 될까요? 같은 데이터를 계속해서 복제를 하게 되면 모델이 해당 데이터에 과적합을 야기할 수도 있습니다. 그렇기 때문에, SMOTE 샘플링은 K-최근접 이웃 알고리즘을 사용하여 중복되지 않는 평균적인 데이터를 생성하도록 되어있습니다.
다음 수식을 봅시다.

위의 수식은 SMOTE 샘플링을 할 때, 생성할 데이터를 구하는 공식입니다. 소수 클래스의 데이터 중 임의의 데이터(𝒙ᵢ)를 하나 선택하고, 그 데이터와 같은 클래스의 데이터를 가장 가까운 k개를 선택합니다. 그 k개 중 임의의 데이터(𝒙𝘫)를 하나 선택하여, 선분(𝒙ᵢ - 𝒙𝘫)을 그린 후, 그 위의 임의의 점을 난수(0~1)인 람다(ƛ)를 이용하여 구합니다. 이러한 방식을 계속하여 반복하면, 소수 클래스의 수가 중복없이 발생하는 효과를 얻을 수 있게 됩니다.
그냥 balanced_weight='balanced'를 이용해서 모델링하면 가능하지 않는가?
맞습니다! 클래스 수에 역수를 취해서 가중치를 만드는 방법 또한 소수 클래스의 숫자를 늘려줍니다. 그러나 우리가 건강이나 위해한 데이터를 예측을 할 때에는 재현율(Recall)을 끌어올려 FN(False Negative) 데이터의 수를 최소화시켜주어야 합니다. balanced_weight 옵션은 모델링을 할 때, 간편하게 생성할 수 있으나, SMOTE가 재현율을 증가시켜주기에는 더욱 효과적입니다. 그러나, 재현율이 충분히 높은 경우에는 balanced_weight 옵션을 사용하는 것이 정확도(Accuracy), F1-점수에 더욱 도움이 될 수 있습니다.
SMOTE 샘플링 기법은 또한 단점이 여럿 존재합니다.
SMOTE의 단점
소수 클래스 데이터 주변에 다수 클래스 데이터가 인접해 있을 경우, 두 클래스의 경계가 모호해지는 지점에 새로운 데이터를 생성하게 됩니다. 이는 노이즈를 발생시키며 오히려 분류 성능을 저해할 수 있습니다. 이 노이즈를 해결하기 위해서는 다수 클래스와의 경계선에 위치한 소수 데이터에 대해서만 새로운 데이터를 생성하는 BorderlineSMOTE 기법과, 기존 SMOTE에 ENN(Edited Nearest Neighbor)을 결합하여 언더샘플링(Under-sampling)하는 SMOTEENN 기법이 존재합니다. 이번 글에서는 SMOTEENN에 대해서 더욱 자세히 알아보겠습니다.
#2 SMOTE (SMOTE + Edited Nearest Neighbors) 개념 및 특성
SMOTE만 사용하게 되면 FN(False Negative) 데이터는 줄일 수 있지만, 노이즈가 발생하여 FP(False Positive) 데이터의 수가 폭증하게 되고, 결국에는 정밀도(Precision)가 하락하게 됩니다. 그렇기 때문에 노이즈 데이터의 폭증을 완화해주는 ENN 알고리즘을 추가적으로 사용하는데, 이는 SMOTE 후에 K-최근접 이웃 알고리즘을 활용하여 언더샘플링(Under-sampling) 합니다.

<그림 2>를 보면 SMOTE의 결과, 소수 클래스였던 파란색 클래스의 데이터들이 빨간색 클래스 데이터들 사이로 침투한 것을 볼 수 있습니다. 파란색과 빨간색 데이터의 경계가 모호해져 분류 성능이 급락하게 됩니다. 반면 SMOTEENN의 결과, 빨간색 클래스의 데이터들 사이로 침투했던 파란색 클래스 데이터들, 즉 노이즈 데이터를 언더샘플링하여 제거함으로써 분류 성능이 향상되었습니다.
ENN 작동 방식
모든 데이터 중 임의의 데이터를 하나 선택하고, 그 데이터를 주변에 있는 K개의 이웃 데이터들과 비교를 합니다. K개의 이웃 중 어떤 클래스가 점유율이 높은지 알아내고, 선택했던 임의의 데이터가 해당 클래스인지 비교합니다. 결과가 일치하면 유지, 불일치하다면 노이즈로 간주하고 데이터셋에서 제거합니다. 이로써 클래스 간 경계가 더 뚜렷해지게 됩니다.
SMOTEENN에도 단점이 존재하는가?
완벽하다고 생각되는 알고리즘이지만, 모든 경우에 사용하는 것은 아닙니다. 거의 모든 샘플을 비교하는 것이기 때문에, 계산량이 굉장히 큽니다. 따라서, BorderlineSMOTE나 가중치를 통해 클래스의 균형을 맞추는 방법을 때에 따라 고려를 해야합니다.
#3 코드 적용
pm25_pipeline = ImbPipeline([
('poly', PolynomialFeatures(degree=2, include_bias=False)),
('smoteenn', SMOTEENN(smote=SMOTE(k_neighbors=3, random_state=42))),
('scaler', StandardScaler()),
('model', get_logistic_model())
])
위의 코드는 초미세먼지 농도를 예측하는데 실제로 사용했던 파이프라인 코드입니다. SMOTEENN() 함수의 인자에 smote 객체를 지정해서 넣어줬는데, SMOTE의 k값을 3으로 지정한 객체를 전달했습니다.(원래의 디폴트 값은 5)
이외에도, n_neighbors 값을 변경한 ENN 객체나 샘플링 전략(sampling_strategy) 옵션을 추가, random_state를 추가할 수 있습니다.
모델 실험에서는 random_state를 꼭 지정해서 테스트해야 결과가 달라지는 현상을 방지할 수 있습니다.
#4 분석
머신러닝 모델을 개발하다보면 데이터 불균형이라는 문제에 자주 직면하게 됩니다. 특히 우리가 예측하고자 하는 건강과 직결되는 문제에는 치명적인 경우가 존재할 수 있으므로, 이 문제를 무시한다면 가치없는 모델이 되어버릴 수도 있습니다. 우리의 궁극적인 목표는 단순히 높은 정확도 점수를 얻는 것이 아니라, 현실 세계에서 활용가능성이 있고 신뢰할 수 있는 예측을 하는 모델을 만드는 것이므로, 비용과 데이터 특성을 잘 고려해서 SMOTE, SMOTEENN 기법을 선택해서 활용해야 합니다.
이미지 출처
https://www.datasciencecentral.com/wp-content/uploads/2021/10/2808331754.png
'Computer Science' 카테고리의 다른 글
| MSA 환경에서 SNS + SQS, Apache Kafka를 활용하여 시스템 결합도 낮추기 (0) | 2025.12.28 |
|---|---|
| AWS VPC Endpoint를 활용한 보안 및 비용 최적화 (0) | 2025.12.26 |
| B+트리를 활용하여 DB 인덱싱하기 (0) | 2024.07.23 |
| 대규모 데이터베이스 성능 향상을 위한 샤딩 알고리즘 (0) | 2024.07.14 |
| 데이터베이스 정규화와 성능 최적화 전략 (0) | 2024.07.04 |