반응형

이상치 제거는 데이터 분석에서 매우 중요하다. 특히, 요즘에는 어떤 모델을 사용하나 보다, 어떤 데이터로 학습할지가 모델 성능에 더 중요한 요소가 된 만큼, 이상치 제거는 그 중요성이 더욱 커졌다. 이상치 제거 방법은 정말 많지만, 자주 사용하는 몇 가지 방법을 알아보기로 한다.


이상치(Outlier) 란?

  • 이상치란 일반적인 데이터 분포를 따르지 않는 값으로, 다른 데이터와 차이가 매우 큰 값을 가진 데이터 포인트를 의미한다. 
  • 이상치가 생기는 요인은 데이터 수집 과정에서 오류가 발생하거나, 데이터 자체가 이상치를 포함하고 있는 경우, 변경점 발생으로 인한 데이터 분포 변화 등이 존재한다.
  • 이상치는 상대적인 개념이다. 즉, 어떤 데이터를 어떻게 분석하고, 어느 기준으로 이상치를 판별할 것이냐에 따라, 이상치 데이터들이 달라진다.

이상치(Outlier) 제거 방법

1. 사분위수(Quartiles) 방법

  • 사분위수 방법은 데이터분포와 값의 크기를 이용하여, 대략적인 이상치 구간을 설정해주는 방법이다.
  • 간단하고, 직관적이여서, 이상치 제거에서 많이 활용된다.
  • 통계적인 값을 기반으로 해서, 1D 데이터에서도 쉽게 활용 가능하다. 
  • 방법은 다음과 같다. 
    • 데이터를 값 기준으로 정렬한 후, 데이터의 분포에 따라 4등분하여, 각 부분의 값을 각각 1사분위, 2사분위, 3사분위, 4사분위로 나타낸다. (하위 0~25%, 25~50%, 50~75%, 75~100%)
    • 1사분위 수(값 기준 하위 25%되는 값)와 3사분위 수(값 기준 상위 25%되는 값)을 찾는다.
    • 3사분위 수와 1사분위 수의 차로 IQR(Interquartile Range)을 구한다. 
    • 일반적으로 1사분위 수와 3사분위 수에서 IQR의 특정 배수(일반적으로 1.5) 이상 벗어난 값들을 이상치로 판정하고 제거해준다.

  • 파이썬 코드 구현
import numpy as np

def outlier_remove(data, threshold=1.5):
	q1, q3 = np.percentile(data, [25, 75]) # 1사분위수, 3사분위수 계산
	IQR = q3 - q1 # IQR 계산

	lower_bound = q1 - (threshold * IQR) # Outlier 판단 Lower Bound 계산
	upper_bound = q3 + (threshold * IQR)  #Outlier 판단 Upper Bound 계산
    
	filtered_data = [x for x in data if x >= lower_bound and x <= upper_bound]
	outlier = [x for x in data if x not in filtered_data]
    
	return filtered_data, outlier, q1, q3, iqr, lower_bound, upper_bound

if __name__ =='__main__':
	X = np.random.normal(0, 1000, 1000)
	filtered_data, outlier, q1, q3, IQR, lower_bound, upper_bound = outlier_remove(X)

 
2. Z-score 방법

  • Z-score 방법은 데이터의 평균과 표준편차를 이용해, 이상치를 제거하는 방법이다. 
  • Z-score 방법은 데이터의 분포가 정규분포를 따른다는 가정이 필요하다. 
  • 통계적인 값을 기반으로 해서, 1D 데이터에서도 쉽게 활용 가능하다.
  • 방법은 다음과 같다.
    • 데이터 포인트들의 평균과 표준편차를 구한다.
    • 각 데이터 포인트의 Z-score (Z = |x - μ|/ σ)를 구한다. Z-score는 데이터 포인트가 평균과의 거리가 몇 sigma 범위에 있는지를 의미한다.
    • Z-score가 특정 threshold(일반적으로 3) 이상인 값들은 이상치로 판정하고, 제거해준다.

  • 파이썬 코드 구현
import numpy as np

def outlier_remove(data, threshold=3):
    z_scores = np.abs(data - np.mean(data)) / np.std(data) # Z-score 계산
    
    filtered_data = data[z_scores < threshold]
    outlier = data[z_scores>threshold]
    
    return filtered_data, outlier

if __name__ == '__main__':
    X = np.random.normal(0, 1000, 1000)
    filtered_data, outlier = outlier_remove(X)

 

+ Recent posts