인공지능/머신러닝

# [EDA] 데이터 불균형 해결을 위한 SMOTE oversampling

ForrestPark 2024. 12. 17. 16:12

📌 본 포스팅은 오버샘플링을 통한 데이터 불균형 해결 내용을 다룹니다.
📌 [참고] 데이콘


1. 데이터 불균형

1.1 데이터 불균형 모델 학습의 균형

  • 한 클랫의 데이터가 다른 클래스에 비해 훨씬 많을 때 발생함. ex) 은행 사기 탐지 시스템에서 정상거래는 많지만 사기거래는 적은 경우 모델이 사기 거래를 제대로 인식하지 못할 수있음. 모델 성능 저하, 일반화 능력 감소, 부정적 결과 초래
  • 데이터가 불균형하면 다양한 상황을 제대로 학습 불가. 특정 유형 데이터만 많이 보면 다른 중요한 유형 간과 혹은 잘못 이해
  • 소수 클래스 과소평가 사기거래를 찾는게 아니라 그냥 모든 거래를 정상으로 분류 할수 있음. 이럴경우 99 퍼 예측률 나옴.
  • 불균형으로 인한 과적합이 나올수 잇음. 정상거래에 완전히 과적합 되어서 사기 거래는 모두 틀리게 될 수있음.
  • 일반화 능력 저하( 현실 적응 불가 ) 학습한 내용을 새로운 보지 못한 데이터에도 잘 적용하는 능력

2. over sampling -> 소수 클래스 증가

  • 가상의 금융 거래 데이터셋 , 사기거래 탐지 모델, 오버샘플링을 사용하는 데이터 불균형 문제 해결
  • 오버샘플링 개념, 단순무작위 복제와 SMOTE(Synthetic Minority Over-sampling Technique)
  • undersampling : 다수 클래스의 샘플을 줄이는 방식. , oversampling: 소수 클래스 샘플을 인위적으로 늘림. 상황에따라 둘을 섞어서 적용함.

2.1 오버 샘플링 종류

  • 단순 무작위 복제 : 가장 기본적 방식. from imblearn.overs_sampling import RandomOverSampler
    • 간단하고 쉬움, 빠름, 데이터 분포를 유지하면서 샘플 수만 증가. 클래스 특성을 변형하지 않고 보존.
    • 과적합의 위험: 동일한 데이터륿 반복하기떄문에 훈련데이터에 과도하게 최적화 되는 과적함.
    • 새롭고 다양한 정보를 추가하지 않고 복제 -> 다양성이 증가하지 않음.
    • 실제 상황에서 소수 클래스가 다양한 형태로 나타날 경우. 복잡한 패턴 모델링 하는데 한계가 잇ㅇ므.
  • SMOTE : 새로운 손님을 만들어 내는것 처럼 기존 데이터를 바탕으로 새로운 데이터 포인트를 합성함.
    • 합성 소수 오버샘플링 , 소수 클래스의 오버샘플링을 통해 균형 잡힌 데이터 를 만듬.
    • 기존 소수 클래스 인스턴스간의 특성을 보간함. => 새로운 합성 샘플을 생성
      방법:
        1. 이웃 선택 : 소수 클래스의 인스턴스를 선택, 이 인스턴스와 가장 가까이 있는 소수 클래스 인스턴스들 중에서 하나 이상을 이웃으로 선택함. 이웃-> 선택한 원본 인스턴스와 비슷한 특성을 가진 데이터포인트임
        1. 임의의 이웃을 선택: 이중에 하나의 이웃을 무작위 선택, 다양성을 보장하기 위해 무작위성을 도입.
        1. 특성 차이 계산: 선택된 이웃과 원본 인스턴스 간 각 특성값 의 차이를 계산(ex: 데이터 포인트의 각 변수 값) => 새로운 데이터 포인트를 생성시 사용되는 간격, 벡터가 됨.
        1. 새 인스턴스 생성 : 계산된 특성 차이에 0과 1 사이에 무작위수(랜덤 스칼라값) 을 곱함. , 새로운 합성 인스턴스가 원본 인스턴스와 선택된 이웃 사이의 중간 점에 위치하도록 함. -> 무작위 수를 곱함으로 써 생성된 새 인스턴스는 원본 인스턴스와 정확히 동일하지 않고 약간의 변화를 가지게 됨.
        1. 합성 인스턴스 추가 : 원본 인스턴스의 특성값에 추가되어 최종 인스턴스 생성.
    • 데이터 다양성 증가, 일반화된 학습 수행 가능, 과적합 위험을 줄여줌.
    • 기존 데이터패턴이 이상할떄 잘못된 샘플 생성 위험, 계산 복잡성으로 인한 리소스 와 시간필요, 변수가 많은 데이터나 복잡한 데이터는 smote 적용 어려움.

3. Oversampling 함수 제작 및 사용


## 4-1 : ROS 와 SMOTE 를 활용한 오버샘플링 -> 데이터 균일화 
def step_4_1_Oversampling(train_x,train_y, ros =False, smote =False,feature_select=[]):
    """
    #1.     
    ## train_x_ros, train_y_ros= step_4_1_Oversampling(train_x,train_y, ros=True)
    ## step_4_MLOutput_target_ratio(pd.concat([train_x_ros, train_y_ros],axis=1), target_col=target,graph_show=False)
    #2.
    ## train_x_smote, train_y_smote  = step_4_1_Oversampling(train_x,train_y, smote=True,feature_select=[])
    ## step_4_MLOutput_target_ratio(pd.concat([train_x_smote, train_y_smote],axis=1), target_col=target,graph_show=False)

    """
    print(r_cy("\n======================= step_4_1_Oversampling ======================="))
    import pandas as pd
    if ros:
        from imblearn.over_sampling import RandomOverSampler
        ros = RandomOverSampler(random_state= 42)
        X_resampled, y_resampled = ros.fit_resample(train_x,train_y)

        #결과 
        print(red(" - Random Over Sampling 을 적용하여 불균일을 처리합니다"))
        train_resampled = pd.concat([X_resampled,y_resampled],axis =1)
        return X_resampled, y_resampled 
    if smote:
        from imblearn.over_sampling import SMOTE
        smote = SMOTE(random_state =42)
        X_smote, y_smote =smote.fit_resample(train_x,train_y)
        # SMOTE 결과 
        print(red(" - Synthetic Minority OverSampling Technique(smote )을 적용하여 불균일을 처리합니다"))
        train_smote = pd.concat([X_smote, y_smote ],axis =1)

        import matplotlib.pyplot as plt, seaborn as sns
        import warnings ; warnings.filterwarnings('ignore')
        plotSetting()
        ## 피처 선택 
        if len(feature_select) !=0:
            feature1= feature_select[0]
            feature2=feature_select[1]
        else:
            feature1 = train_x.columns[0] #'이전 거래와의 시간 간격'
            feature2 =  train_x.columns[1] #'거래 금액'
        # 원본 데이터 분포 시각화 
        plt.figure(figsize= (16,5))
        plt.subplot(1,2,1)
        sns.scatterplot(x = train_x.loc[:,feature1], y = train_x.loc[:,feature2], hue =train_y)
        plt.title("Original Data")

        # SMMOTE 방법으로 오버샘플링 데이터 시각화 
        plt.subplot(1,2,2)
        sns.scatterplot(x = X_smote.loc[:,feature1], y  = X_smote.loc[:,feature2], hue= y_smote)
        plt.title("SMOTE oversampled DATA")
        plt.show()
        return X_smote, y_smote