데이터 분석가가 반드시 알아야할 모든 것

데이터 전처리와 파생변수 생성

채영sw 2024. 3. 20. 17:36

11-1. 결측값 처리

결측값 : 분석 환경에 따라 '.' , 'NA', 'NaN' 등으로 표시

 

<결측치가 발생하는 특성에 따른 세 가지의 결측>

  • 완전 무작위 결측(MCAR) : 순수하게 결측값이 무작위로 발생한 경우 -> 결측값을 포함한 데이터를 제거해도 편향(bias)가 거의 발생되지 않음
  • 무작위 결측(MAR) : 다른 변수의 특성에 의해 해당 변수의 결측치가 체계적으로 발생한 경우
    • 전국 체인 매출 정보 중, 특정 체인점의 POS기기에 오류가 나서 해당 체인점에 해당하는 매출 정보에 결측값이 많이 나타난 경우
  • 비무작위 결측(NMAR) : 결측값들이 해당 변수 자체의 특성을 갖고 있는 경우
    • 고객정보 데이터에서 '고객 소득' 변수에서 결측값들 대부분이 소득을 공개하기 꺼려해서 결측이 발생한 경우
    • 결측된 값은 그 값이 실제로 무엇인지 확인할 수 없기 때문에 비무작위 결측을 구분하기 어려움

 

 

<결측값 처리 방법>

 

1. 단순 대치법

표본 제거 방법(Completes analysis) : 결측값이 심하게 많은 변수를 제거하거나 결측값이 포함된 행을 제외하고 데이터 분석 ( 가장 간단한 결측값 처리 방법)

-> 상황에 따라 결측값을 무시하면 데이터가 편중되어 편향이 발생할 위험이 있음

 

평균 대치법(Mean Imputation) : 결측값을 제외한 온전한 값들의 평균을 구한 다음, 그 평균 값을 결측값들에 대치하는 것

-> 최빈값, 중앙값, 최댓값, 최솟값 대치 등 유사한 방법이 있음

+) 사용하기 간단하고 결측 표본 제거 방법의 단점을 어느 정도 보완

-) 관측된 데이터의 평균을 사용하기 때문에 통계량의 표준오차가 왜곡되어 축소되어 나타나 p-value가 부정확하게 됨

 

> 표본 제거 방법과 평균 대치법은 완전 무작위 결측이 아닌 경우 적절하지 않은 방법

 

보간법(interpolation) : 데이터가 시계열적 특성을 가지고 있을 때 사용하면 효과적, 주변의 가까운 점으로부터 선형적인 수치 값을 계산해 보간하는 방법

    - 단순 순서 보간법 : 단순히 순서만 고려하는 방식

    - 시점 고려 보간법 : 날짜의 시점을 고려한 방식

 

회귀 대치법(regression imputation) : 해당 변수와 다른 변수 사이의 관계성을 고려하여 결측값을 계산하면 보다 합리적으로 결측값을 처리할 수 있음

    - 추정하고자 하는 결측값을 가진 변수를 종속변수로, 나머지 변수를 독립변수로 하여 추정한 회귀식을 통해 결측값을 대치하는 것

    +) 회귀식을 통해 조건부 평균으로 결측값을 대치

    - ) 결측된 변수의 분산을 과소 추정하는 문제를 가짐

 

확률적 회귀대치법(stochastic regression) : 문제 해결을 위해 인위적으로 회귀식에 확률 오차항을 추가하여 변동성 조정

    - 관측된 값들을 변동성만큼 결측값에도 같은 변동성을 추가해 주는 것

   - ) 여전히 어느 정도 표본오차를 과소 추정하는 문제를 가지고 있음

 

2. 다중 대치법(multiple imputation)

: 단순대치를 여러 번 수행하여 n 개의 가상적 데이터를 생성하여 이들의 평균으로 결측값을 대치하는 방법

  • 대치 단계(imputations step) : 가능한 대치 값의 분포에서 추출된 서로 다른 값으로 결측치를 처리한 n개의 데이터셋 생성
    • 몬테카를로 방법(MCMC) / 연쇄방정식을 통한 다중 대치(MICE)를 사용해 대치값 임의 생성
    • 결측값 비율이 증가할수록 가상데이터도 많이 생성해야 검정력이 증가함
  • 분석 단계(Analysis step) : 생성된 각각의 데이터셋을 분석하여 모수의 추정치와 표준오차 계산
  • 결합 단계(Pooling step) : 계산된 각 데이터셋의 추정치와 표준오차를 결합하여 최종 결측 대치값 산출

다중 대치법의 프로세스

 

<결측값 처리 실습>

더보기
import missingno as msno
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np


df = pd.read_csv("/bike_sharing_daily.csv")
df.head()
df.info()
df.isnull().sum()

msno.matrix(df)
plt.show()
msno.bar(df)
plt.show()

def is_emptystring(x):
  return x.eq('').any()
df.apply(lambda x:is_emptystring(x))

#모든 칼럼이 결측값인 행 제거
df_drop_all = df.dropna(how='all')
#세 개 이상의 칼럼이 결측값인 행 제거
df_drop_3 = df.dropna(thresh=3)
#특정 칼럼(temp)이 결측값인 행 제거
df_drop_slt = df.dropna(subset=['temp'])
#한 칼럼이라도 결측치가 있는 행 제거
df_drop_any = df.dropna(how='any')

df_drop_any.isnull().sum()

1. 결측값 확인

atemp 칼럼의 세 번째 칼럼에서 결측값 확인 가능

hum 칼럼이 연속적으로 결측값을 많이 가지고 있는 것을 확인할 수 있음

 

2. 결측값 표본 제거

확인 결과 모든 캄럼에 빈 문자열 값 없음

 

dropna() 함수 : 결측값의 관측치 제거에 사용

  • how = 'all' 옵션 : 모든 칼럼의 값이 결측값인 행 제외
  • how = 'any' 옵션 : 한 캄럼이라도 결측값인 행 제외
  • subset 옵션 : 특정 칼럼의 결측값을 기준으로 관측치 제거(여러 개의 칼럼 지정 가능)

3. 특정값, 평균값, 중앙값, 최빈값 등 대치

더보기
#결측값 기본 대치 방법들

#특정값(0)으로 대치 - 전체 칼럼
df_0_all = df.fillna(0)
#특정값(0)으로 대치 - 칼럼 지정
df_0_slt = df.fillna({'temp':0})
#평균값 대치 - 전체 칼럼
df_mean_all = df.fillna(df.mean())
#평균값 대치 - 칼럼 지정
df_mean_slt = df.fillna({'temp':df['temp'].mean()})
# 중앙값 대치 - 전체 컬럼
df_median_all = df.fillna(df.median())
# 중앙값 대치 - 컬럼 지정
df_median_slt = df.fillna({'temp':df['temp'].median()})
# 최빈값 대치 - 전체 컬럼
df_mode_all = df.fillna(df.mode())
# 최빈값 대치 - 컬럼 지정
df_mode_slt = df.fillna({'temp':df['temp'].mode()})
# 최댓값 대치 - 전체 컬럼
df_max_all = df.fillna(df.max())
# 최댓값 대치 - 컬럼 지정
df_max_slt = df.fillna({'temp':df['temp'].max()})
# 최솟값 대치 - 전체 컬럼
df_min_all = df.fillna(df.min())
# 최솟값 대치 - 컬럼 지정
df_min_slt = df.fillna({'temp':df['temp'],'hum':df['hum'].min()})


df_min_slt.isnull().sum()

fillna() 옵션 : 기본적인 결측값 대치에 활용

 

4. 보간법 적용 대치

더보기
# 전 시점 값으로 대치 - 컬럼 지정
df1 = df.copy()
df1['temp'].fillna(method ='pad' ,inplace=True)
# 뒤 시점 값으로 대치 - 전체 컬럼
df.fillna(method ='bfill')
# 뒤 시점 값으로 대치 - 결측값 연속 한번만 대치
df.fillna(method='bfill', limit=1)
# 보간법 함수 사용하여 대치 - 단순 순서 방식
ts_intp_linear = df.interpolate(method='values')

# dteday 컬럼 시계열 객체 변환
df['dteday'] = pd.to_datetime(df['dteday'])

# 시점에 따른 보간법 적용
df_i = df.set_index('dteday') 
df_time = df_i.interpolate(method='time')

df_time.isnull().sum()

method 옵션 pad/bfill 설정 : 전 시점이나 뒤 시점의 값과 동일한 값으로 대치하는 보간법

시점 인덱스를 사용하기 위해서는 시간형 칼럼을 시계열 객체로 변환한 후 인덱스로 설정해줘야 함.

interpolate() 함수 : 시점의 정도를 고려한 대치값 적용

 

4. 다중 대치법 적용

더보기
#dteday 칼럼 제거
df_dp = df.drop(['dteday'], axis=1)
#다중 대치 알고리즘 설정
imputer=IterativeImputer(imputation_order='ascending',
                         max_iter=10,random_state=42,
                         n_nearest_features=5)
#다중 대치 적용
df_imputed = imputer.fit_transform(df_dp)
#판다스 변환 및 칼럼 설정
df_imputed = pd.DataFrame(df_imputed)

df_imputed.columns = ['instant','season','yr','mnth','holiday'
                    ,'weekday','workingday','weathersit','temp'
                    ,'atemp','hum','windspeed','casual','registered','cnt']

df_imputed.isnull().sum()

sklearn의 impute 패키지 : 다중 대치

대치가 필요 없는 dteday 칼럼을 제거해준 후 다중 대치 알고리즘 적용

다중 대치를 적용할 때는 넘파이 배열로 변환되기 때문에 다시 판다스 데이터프레임으로 변환해줘야함.


 

11-2. 이상치 처리

이상치(outlier) : 일부 관측치의 값이 전체 데이터의 범위에서 크게 벗어난 아주 작거나 큰 극단적인 값을 갖는 것

-> 데이터의 모집단 평균이나 총합을 추정하는 것에 문제를 일으키며, 분산을 과도하게 증가시켜 분석이나 모델링의 정확도를 감소시키기 때문에 제거하는 것이 좋음.

-> 전체 데이터의 양이 많을수록 튀는 값이 통곗값에 미치는 영향력이 줄어듦 - 이상치 제거 필요성 낮아짐

이상치로 인한 회귀선 왜곡 예

데이터 분석 모델의 예측력 약화

 

<이상치 처리 방법>

1. 이상치 값을 결측값으로 대체한 다음 결측값 처리

2. 해당 이상치를 제거(trimming)

-> 추정치의 분산은 감소하지만 실젯값을 과장하여 편향을 발생시킴

3. 관측값 변경(value modification) : 하한 값과 상한 값을 결정한 후 하한 값보다 작으면 하한 값으로 대체하고 상한 값보다 크면 상한 값으로 대체

4. 가중치 조정(weight modification) : 이상치의 영향을 감소시키는 가중치를 줌

 

<이상치 식별 기준과 방법>

  • 데이터 분포 확인을 통해 이상치가 얼마나 포함되어 있는지 가늠 가능
  • 박스플롯 상에서 분류된 극단치를 그대로 선정하는 방법
  • 임의로 허용범위를 설정하여 이를 벗어나는 자료를 이상치로 정의하는 방법
    • 평균(중위수)로 부터 n 표준편차 이상 떨어져 있는 값을 이상치로 봄
    • 보통의 경우 n 은 3, 분포가 비대칭인 데이터의 경우 -n +n 표준편차 값 다르게 설정하기도 함
    • 평균은 이상치에 통계량이 민감하게 변하기 때문에, 중위수와 중위수 절대 편차(MAD) 사용이 더 효과적
  • 해당 데이터 변수들의 의미와 비즈니스 도메인을 먼저 이해하고 이상치가 생긴 원인을 논리적으로 생각해야함
    • 이상치를 변수화하여 이상치에 대한 설명력 추가

이상치의 변수화 예시

 

<이상치 처리 실습>

더보기
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

df = pd.read_csv("/heart_2020_cleaned.csv")
df.head()
df['BMI'].describe()

#BMI 칼럼의 박스플롯 시각화를 통한 이상치 확인
plt.figure(figsize=(8,6))
sns.boxplot(y='BMI', data = df)
plt.show()

데이터 불러오기

더보기
#BMI 칼럼의 이상치 제거
Q1 = df['BMI'].quantile(0.25)
Q3 = df['BMI'].quantile(0.75)
IQR = Q3-Q1
rev_range = 3 #제거 범위 조절 변수 설정
#이상치 범위 설정
filter = (df['BMI'] >= Q1 - rev_range * IQR) & (df['BMI'] <= Q3 + rev_range * IQR)
df_rmv = df.loc[filter]

print(df['BMI'].describe())
print(df_rmv['BMI'].describe())

#이상치 제거 후 박스 플롯 시각화
plt.figure(figsize=(8,6))
sns.boxplot(y='BMI', data = df_rmv)
plt.show()

최댓값 감소, 관측치 1318개 제거 확인 가능

IQR 3 기준의 이상치를 제거한 후 박스 플롯의 이상치가 많이 줄어든 것을 확인할 수 있음

더보기
#이상치 IQR*3 값으로 대치
#이상치 대치 함수 설정
def replace_outlier(value):
  Q1 = df['BMI'].quantile(0.25)
  Q3 = df['BMI'].quantile(0.75)
  IQR = Q3 -Q1
  rev_range = 3

  if ((value < (Q1 - rev_range * IQR))): 
        value = Q1 - rev_range * IQR
  if ((value > (Q3 + rev_range * IQR))): 
       value = Q3 + rev_range * IQR
  return value

df['BMI'] = df['BMI'].apply(replace_outlier)
print(df['BMI'].describe())


이상치 상하한선 값으로 대치 ( 상황에 따라 평균이나 중앙값 등으로 대치 가능)

기준을 정의하고 if 문을 사용하여 해당 관측치 값이 이상치 기준을 넘어서면 상하한선으로 대치되도록 함.


11-3. 변수 구간화(Binning)

변수 구간화(Binning) : 데이터 분석의 성능을 향상시키거나 해석의 편리성을 위해 이산형 변수를 범주형 변수로 변환

-> 비즈니스적 상황에 맞도록 변환시킴으로써 데이터의 해석이나 예측, 분류 모델을 의도에 맞도록 유도할 수 있음!

변수 구간화 예시

평활화(smoothing) : 이산 값을 단순한 이산 값으로 변환시키는 기법

-> 변수의 값을 일정한 폭이나 빈도로 구간을 나눈 후, 각 구간 안에 속한 데이터 값을 평균, 중앙값, 경곗값 등으로 변환

머신러닝 기법:

    - 클러스터링: 타깃 변수 설정 필요 없이 구간화할 변수의 값들을 유사한 수준까리 묶어줄 수 있음

    - 의사결정나무: 타깃 변수를 설정해, 구간화할 변수의 값을 타깃 변수 예측에 가장 적합한 구간으로 나누어줌.

    - WOE(Weight of Evidence) / IV(Information Value) : 로지스틱 회귀분석에서 파생된 개념으로 종속변수 대비 독립 변수의 예측력이 얼마나 강한지 나타내는 지표

 

<변수 구간화 실습>

더보기
!pip install xverse
from xverse.transformer import WOE
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

df = pd.read_csv("/heart_2020_cleaned.csv")
df.head()

#BMI 칼럼의 분포 확인
df['BMI'].describe()

#BMI 칼럼 분포 시각화
%matplotlib inline
sns.displot(df['BMI'], height = 5, aspect = 3)

기본 구간화와 WOE 기반 구간화 및 분포 그래프 등을 시각화하기 위해 필요한 패키지들 임포트

 

12~94 사이의 값을 가지고 있는 것 확인 가능

오른 꼬리 분포로 20~40 사이에 대부분의 관측치가 분포해 있고 60 이상부터는 관측치 희소

더보기
#임의로 단순 구간화
df1 = df.copy() #데이터셋 복사
# 구간화용 빈 컬럼 생성 - 생략해도 되지만 바로 옆에 붙여 보기 위함
df1.insert(2, 'BMI_bin', 0) 

df1.loc[df1['BMI'] <= 20, 'BMI_bin'] = 'a'
df1.loc[(df1['BMI'] > 20) & (df1['BMI'] <= 30), 'BMI_bin'] = 'b'
df1.loc[(df1['BMI'] > 30) & (df1['BMI'] <= 40), 'BMI_bin'] = 'c'
df1.loc[(df1['BMI'] > 40) & (df1['BMI'] <= 50), 'BMI_bin'] = 'd'
df1.loc[(df1['BMI'] > 50) & (df1['BMI'] <= 60), 'BMI_bin'] = 'e'
df1.loc[(df1['BMI'] > 60) & (df1['BMI'] <= 70), 'BMI_bin'] = 'f'
df1.loc[df1['BMI'] > 70, 'BMI_bin'] = 'g'

df1.head()

#구간화 변수 분포 시각화
sns.displot(df1['BMI_bin'], height = 5, aspect = 3)

#cut 함수를 사용하여 임의로 구간화
df1.insert(3, 'BMI_bin2', 0) #구간화용 빈 칼럼 생성

df1['BMI_bin2'] = pd.cut(df1.BMI, bins=[0,20,30,40,50,60,70,95]
                         , labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g'])

df1.head()

#BMI_bin2 구간별 관측치 수 집계
df1.BMI_bin2.value_counts().to_frame().style.background_gradient(cmap='winter')

변수 구간화
기존의 형태와 유사
판다스의 cut() 함수를 사용하면 간단하게 구간화를 수행할 수 있음
20~30 B 구간 관측치 가장 많음

더보기
#qcut() 함수 사용하여 자동 구간화
df1.insert(4, 'BMI_bin3', 0)
df1['BMI_bin3'] = pd.qcut(df1.BMI, q=7, labels=['a', 'b', 'c', 'd', 'e', 'f', 'g'])

df1.head()

#BMI_bin3 구간 별 관측치 수 집계
df1.BMI_bin3.value_counts().to_frame().style.background_gradient(cmap='winter')

#BMI_bin3 칼럼 분포 시각화
sns.displot(df1['BMI_bin3'], height = 5, aspect = 3)

qcut() 함수 : 구간별로 포함되는 관측치의 수가 유사한 구간화를 적용하기 위해 사용

-> 나누고자 하는 범주의 수와 각 범주의 명칭만 설정해 주면 자동으로 구간화 적용

 

범주별 관측치의 수가 유사한 수준으로 배정됨

긴 꼬리 분포를 가진 캄럼의 경우 동일한 간격으로 구간화 할 경우, 포함되는 관측치가 희소한 범주가 생겨 모델의 성능을 감소시킬 수 있기 때문에 이와 같은 구간화 방식이 유용하게 사용됨.

 

분포가 일정하게 이루어진 것 확인 가능

더보기
#WOE를 사용한 변수 구간화
df2 = df.copy()
#xverse 함수 적용을 위한 더미변수 변환
df2=pd.get_dummies(df)
#구간화할 칼럼 X, 기준 칼럼 y 지정
X = df2[['PhysicalHealth']]
y = df2[['KidneyDisease_Yes']]
#차원 축소
y = y.T.squeeze()
#WOE 모델 설정 및 적용
clf = WOE()
clf.fit(X, y)
#구간 기준점 및 WOE 값 테이블 생성
a = clf.woe_df
#IV 테이블 생성
b = clf.iv_df

a.head()
b.head()

WOE 를 활용하여 종속변수에 대한 독립변수가 최적의 예측력을 가질 수 있도록 구간화

-> 종속변수 1과 0의 가변수로 전처리 필요

-> 독립변수 설정, 종속변수 칼럼 지정

-> WOE() 함수를 사용해 최적 범주 기준 산츨


11-4. 데이터 표준화와 정규화 스케일링

표준화(Standardization) / 정규화(Normalization) 스케일링: 독립 변수들이 서로 단위가 다르거나 편차가 심할 때 값의 스케일을 일정한 수준으로 변환시켜주는 것

 

표준화 : 각 관측치의 값이 전체 평균을 기준으로 어느 정도 떨어져 있는지 나타낼 때 사용

+) 서로 다른 변수 간 값의 크기를 직관적으로 비교할 수 있음

각 관측치 값에서&nbsp; 평균을 빼 준후 표준편차로 나눠줌

정규화 : 데이터의 범위를 0부터 1까지로 변환하여 데이터 분포를 조정하는 방법

+) 전체 데이터 중에서 해당 값이 어떤 위치에 있는지 파악하는 데 유용

(해당 값 - 최솟값) / (최댓값 - 최솟값)
기존에는 달라보이던 변수 X1. X2가 변환 후 유사한 모습으로 보이는 것을 확인할 수 있음

 

RobustScaler : 이상치에 민감하다는 기본 표준화, 정규화 방식의 단점을 보완한 스케일링 기법

- 데이터의 중앙값을 0으로 잡고 25%, 75% 사분위수와의 IQR 차이를 1이 되도록 하는 스케일링 기법

+) 이상치의 영향력을 최소화하여 성능 우수

 

<데이터 표준화와 정규화 스케일링 실습>


11-5. 모델 성능 향상을 위한 파생 변수 생성

파생변수(Derived variable) : 원래 있던 변수들을 조합하거나 함수를 적용하여 새로 만들어낸 변수

- 데이터 구간화, 표준화 및 정규화 등도 일종의 파생변수

- 로그나 제곱근 등을 취해 변동성을 완화시키거나 지수함수를 사용하여 분산을 증폭시킬 수도 있음

- 시점을 고려해 과거 시점 대비 변화 정도를 파생변수로 만들 수도 있음

-> 데이터의 특성을 이용하여 분석 효율을 높이는 것이기 때문에 전체 데이터에 대한 파악이 중요할 뿐만 아니라 해당 비즈니스 도메인에 대한 충분한 이해가 수반되어야 함.

파생변수 생성 예시

<유의할 점>

- 기존의 변수를 활용해서 만들어낸 변수이기 때문에 다중공선성 문제가 발생할 가능성이 높음

    -> 파생변수를 만든 후, 상관분석을 통해 변수 간의 상관성을 확인해야 함

    -> 상관성에 따라 파생변수를 그대로 사용할지, 기존 변수를 제외하고 파생변수만 사용할지 결정

더보기

다중공선성 문제 : 독립변수들 간에 강한 상관관계가 나타나 데이터 분석 시 부정적인 영향을 미치는 현상

 

<파생 변수 생성 실습>


11-6. 슬라이딩 윈도우 데이터 가공

슬라이딩 윈도우(Sliding window) : 본래 실시간 네트워크 패킷 데이터를 처리하는 기법

-> 현재 시점으로부터 ±M 기간의 데이터를 일정 간격의 시간마다 전송하는 방식

- 각각의 데이터 조각(window) 들이 서로 겹치며 데이터가 전송됨

데이터를 겹쳐 나눔으로써 전체 데이터가 증가하는 원리를 차용한 것이 슬라이딩 윈도우 데이터 가공의 핵심

 

데이터가 충분하지 않거나, 학습 데이터의 시기와 예측 데이터의 시기와의 시점 차이가 커 예측력이 떨어지는 경우 슬라이딩 윈도우 방법을 활용하면 많은 분석 데이터셋을 확보하고 학습데이터의 최근성을 가질 수 있음.

슬라이딩 윈도우 기법을 통한 관측치 확보 - 1명의 고객으로 7개의 분석용 데이터를 얻을 수 있음

 

<슬라이딩 윈도우 실습>


11-7. 범주형 변수의 가변수 처리

가변수(Dummy variable) 처리 : 범주형 변수를 0과 1의 값을 가지는 변수로 변환해 주는 것

-> 범주형 변수는 사용할 수 없고 연속형 변수만 사용가능한 분석기법을 사용하기 위함

-> 이진변수(binary variable) / 불리언 변수(Boolean variable) 라고도 함

 

- 범주가 3개 이상인 경우 -> 범주가 늘어날수록, 변수의 수 늘림 ( 범주의 개수보다 하나 적게 가변수를 만들아야 함)

- 아무 범주에도 해당 없음도 그 자체로 하나의 범주

- 어떤 범주를 제거해도 상관없으나 일반적으로 종속변수에 대한 영향력이 가장 적은 범주 제거 (제거된 범주 : baseline)

(baseline 범주의 종속변수에 대한 영향력은 0으로 맞춰지며, baseline 범주 대비 다른 범주들의 영향력 산출)

-> 변수 간의 독립성(independency)을 위해 하나의 범주 가변수를 제거해줌

회귀선의 기울기는 바뀌지 않고 절편만 바꿔 평행하게 움직이도록 만듦 -> 'A형'의 종속변수에 대한 영향력(계숫값)이 +0.5리면 회귀선의 절편이 0.5 만큼 증가

 

<범주형 변수의 가변수 처리실습>


11-8. 클래스 불균형 문제 해결을 위한 언더샘플링과 오버샘플링

 클래스 불균형(Class disparity) 문제가 발생하는 경우가 많음 -> 예측 정확도 떨어짐

ex) 이진분류 모델에서 1의 비율이 매우 적을 경우

 

<데이터 불균형 문제를 해결하는 방법>

  • 모델 자체에 중요도가 높은 클래스에 정확도 가중치를 주어, 특정 클래스의 분류 정확도가 높아지도록 조정해주는 것
    • 가중치 밸런싱(Weight balancing) : 손실(Loss)을 계산하여 손실이 최소화되도록 학습하는데, 중요도가 높은 클래스를 잘못 분류하면 더 큰 손실을 계산하도록 조정해 주는 것 (10% 비중의 클래스를 잘못 분류하면 90%의 손실 가중치, 상대적으로 덜 중요한 90% 비중의 가중치를 잘못 분류하면 10% 손실 가중치 주도록 설정)
  • 불균형 데이터 자체를 균형이 맞도록 가공한 다음 모델을 학습하는 것
    • 언더샘플링 : 큰 비중의 클래스의 데이터를 줄이는 것(큰 비중의 클래스 데이터를 작은 비중의 클래스 데이터만큼만 추출하여 학습시킴)
      • 랜덤 언더샘플링 : 작은 비중의 클래스와 관측치 비율이 유사해질 때까지 무작위로 큰 비중의 클래스의 관측치를 제거하는 단순한 방식
      • EasyEnsemble : 일종의 앙상블 기법. 큰 비중의 클래스를 N 개의 작은 비중의 클래스와 동일한 크기의 데이터셋으로 분리 후, 동일한 작은 비중의 데이터셋에 큰 비중의 데이터만 바꿔가면서 모델을 만듦
      • CNN(Condensed Nearest Neighbor) : K-근접이웃(KNN) 모델을 차용한 언더샘플링 방법. 비중이 큰 클래스의 관측치 중 비중이 적은 클래스와 속성값이 확연히 다른 관측치들은 제거하는 것
    • 오버샘플링 : 작은 비중의 클래스 데이터를 늘리는 것(비중이 작은 클래스의 관측치 수와 동일하도록 작은 비중의 클래스의 관측치들을 증가시킴)
      • 랜덤 오버샘플링 : 작은 클래스의 관측치를 단순히 무작위로 선택하여 반복 추출하는 방식
      • Synthetic Minority Over-Sampling Technique(SMOTE) : KNN 기법을 사용하여 비중이 작은 클래스의 관측치의 K 최근접 이웃 관측치들을 찾아서, 해당 관측치와 K 개의 이웃 관측치들 사이의 값을 가진 새로운 관측치들을 생성

 -> 오버샘플링을 적용할 때에는 먼저 학습 셋과 테스트 셋을 분리한 다음에 적용해야 함. (과적합 방지)

 -> 학습된 모델의 예측력을 검증할 때 사용하는 테스트 셋에는 오버샘플링을 적용하지 않은 순수한 데이터를 사용해야 함.

언더샘플링과 오버샘플링 개념 예시

 

<언더샘플링과 오버샘플링 실습>


11-9. 데이터 거리 측정 방법

데이터 거리 측정 : 관측치 A를 기준으로, B와 C 중 어느 관측치가 더 가까이 있는가를 판단하기 위한 것