
1. 이상치 감지하기
아주 예외적인 샘플을 구별하고 싶을때 사용한다.
일반적인 방법은 데이터가 정규분포를 따른다고 가정하고 이런 가정을 기반으로 하여 데이터를 둘러싼 타원이 그린다.
타원 안의 샘플을 정상치(레이블1)로 분류하고, 타원 밖에 샘플은 이상치(레이블-1)로 분류한다.
# 라이브러리 임포트
import numpy as np
import pandas as pd
# 이상치 감지
from sklearn.covariance import EllipticEnvelope
#분류용 가상 데이터 생성
from sklearn.datasets import make_blobs
#@title **모의 데이터 생성 : make_blobs**
features1, _ = make_blobs(n_samples=10,
n_features=2,
centers=1,
random_state=1)
# 데이터 확인
features1, type(features1), features1.shape
(array([[-1.83198811, 3.52863145],
[-2.76017908, 5.55121358],
[-1.61734616, 4.98930508],
[-0.52579046, 3.3065986 ],
[ 0.08525186, 3.64528297],
[-0.79415228, 2.10495117],
[-1.34052081, 4.15711949],
[-1.98197711, 4.02243551],
[-2.18773166, 3.33352125],
[-0.19745197, 2.34634916]]), numpy.ndarray, (10, 2))
# 첫 번째 샘플을 극단적인 값으로 변경
features1[0,0] = 10000
features1[0,1] = 10000
# 바뀐 features1를 데이터프레임으로 확인
features1_df = pd.DataFrame(features1)
features1_df
0 | 1 | |
---|---|---|
0 | 10000.000000 | 10000.000000 |
1 | -2.760179 | 5.551214 |
2 | -1.617346 | 4.989305 |
3 | -0.525790 | 3.306599 |
4 | 0.085252 | 3.645283 |
5 | -0.794152 | 2.104951 |
6 | -1.340521 | 4.157119 |
7 | -1.981977 | 4.022436 |
8 | -2.187732 | 3.333521 |
9 | -0.197452 | 2.346349 |
#@title **이상지 감지 객체 생성 : EllipticEnvelope**
outlier_detector = EllipticEnvelope(contamination=.1)
contamination 매개 변수를 지정하여 이상치 비율을 정한다. 하지만 실제로는 알지못하고, contamination는 데이터가 얼마나 깨끗한지 '추측'하는것으로 볼 수 있다. 데이터에 이상치가 적다면 contamination 값을 작게 지정하면 된다. 데이터에 이상치가 많다고 느껴진다면 값을 크게 설정한다.
#@title **개별 특생에서 사분위를 사용해 극단적인 값 구별**
# 샘플 전체에서 개별 특성 생성 (전체 행을 잡고, 0번째 컬럼)
feature = features1[:,0]
# 개별 특성 데이터프레임으로 확인
feature_df = pd.DataFrame(feature)
feature_df
0 | |
---|---|
0 | 10000.000000 |
1 | -2.760179 |
2 | -1.617346 |
3 | -0.525790 |
4 | 0.085252 |
5 | -0.794152 |
6 | -1.340521 |
7 | -1.981977 |
8 | -2.187732 |
9 | -0.197452 |
# 이상치 인덱스 반환하는 함수 생성
def indicies_of_outliers(x):
# 지정된 축을 따라 데이터의 25번째 백분위수를 계산합니다. 배열 요소의 75번째 백분위수를 반환합니다.
q1, q3 = np.percentile(x, [25, 75])
# IQR 데이터 : 1사분위와 3사분위 사이의 거리
iqr = q3, q1
# 보통 이상치 범위로 정의:
# 1사분위보다 1.5 IQR 이상 작은 값
lower_bound = q1 - (iqr * 1.5)
# 3사분위보다 1.5 IQR 큰 값
upper_bound = q3 + (iqr * 1.5)
# np.where : 조건 만족하는 위치 인덱스 찾기
return np.where(x > upper_bound) | (x < lower_bound))
→ 이상치를 감지하는 최선의 방법은 없다. 일련의 도구들은 저마다 장단점을 가진다. 최선의 전략은 여러 가지 방법을 시도해보고 종합적으로 결과를 살펴봐야한다.
2.이상치 삭제하기
이상치가 존재하면 이를 다루기에는 세가지 방법이 존재한다. 그 중 하나는 삭제하기이다.
# 판다스로 데이터프레임 생성
houses = pd.DataFrame()
houses['Price'] = [534433, 39233, 293222, 4322032]
houses['Bathrooms'] = [2, 3.5, 2, 116]
houses['Square_Feet'] = [1500,2500,1500,48000]
# houses 데이터 프레임 확인
houses
Price | Bathrooms | Square_Feet | |
---|---|---|---|
0 | 534433 | 2.0 | 1500 |
1 | 39233 | 3.5 | 2500 |
2 | 293222 | 2.0 | 1500 |
3 | 4322032 | 116.0 | 48000 |
# 샘플 필터링
houses[houses['Bathrooms'] < 20]
Price | Bathrooms | Square_Feet | |
---|---|---|---|
0 | 534433 | 2.0 | 1500 |
1 | 39233 | 3.5 | 2500 |
2 | 293222 | 2.0 | 1500 |
3.이상치 표시 및 특성의 하나로 포함
# 불리언 조건을 기반으로 특성을 만듭니다.
houses["Outlier"] = np.where(houses["Bathrooms"] < 20,0,1)
# 데이터 확인
houses
Price | Bathrooms | Square_Feet | Outlier | |
---|---|---|---|---|
0 | 534433 | 2.0 | 1500 | 0 |
1 | 39233 | 3.5 | 2500 | 0 |
2 | 293222 | 2.0 | 1500 | 0 |
3 | 4322032 | 116.0 | 48000 | 1 |
4. 이상치의 영향이 줄어들도록 특성 변환
# 로그 특성
houses["Log_Of_Sqaure_Feet"] = [np.log(x) for x in houses["Square_Feet"]]
# 데이터 확인
houses
Price | Bathrooms | Square_Feet | Outlier | Log_Of_Sqaure_Feet | |
---|---|---|---|---|---|
0 | 534433 | 2.0 | 1500 | 0 | 7.313220 |
1 | 39233 | 3.5 | 2500 | 0 | 7.824046 |
2 | 293222 | 2.0 | 1500 | 0 | 7.313220 |
3 | 4322032 | 116.0 | 48000 | 1 | 10.778956 |
이상치 다루는데 있어 이상치 감지하는 것과 마찬가지로, 언제나 적용할 수 있는 정해진 좋은 처리 방법은 없다. 대신 두 가지 측면에서 처리 방법을 고려해봐야 한다.
- 어떤 것을 이상치로 간주할 것인지
- 이상치를 다루는 방법이 머신러닝의 목적에 맞아야 한다.
이상치가 있다면 왜 그 데이터가 이상치이고, 최종 목적을 생각해야한다. 이상치라고 결정하지 않는 것 자체가 암묵적인 결정일 수도 있다.
이상치가 평균과 분산에 영향을 끼치기 때문에 이상치가 있다면 표준화는 적절하지 않다. 이럴땐 RobutScaler와 같이 이상치에 민감하지 않은 스케일링 방법을 써준다.
'파이썬 > 머신러닝' 카테고리의 다른 글
머신러닝 기본 회귀 모델과 기본 분류 모델의 평가방법 - score(), predict() (0) | 2022.11.23 |
---|---|
모델 평가란? 로지스틱회귀에서 KFold 교차검증 사용해보기 (0) | 2022.11.21 |
서킷런 sklearn으로 수치형 데이터 전처리 [스케일링 - 표준화, 로버스트, MinMax, 정규화] (1) | 2022.11.16 |
머신러닝 데이터 학습 유형 - 지도학습 / 비지도학습 (0) | 2022.11.15 |
머신러닝은? (1) | 2022.11.09 |
댓글