본문 바로가기
Machine Learning

분류 실습(신용카드 사기 데이터)

by rubyda 2020. 5. 3.
728x90

 

캐글에서 제공하는 신용카드 데이터를 사용해서 신용카드 사기 검출을 분류하는 실습을 해보겠습니다. 데이터는 캐글에서 내려받을 수 있습니다.

 


 

 

신용카드 사기 데이터 실습

 

1. 데이터 일차 가공


▷ 필요한 모듈과 데이터를 불러와줍니다.

 

데이터를 살펴본 결과 결측치는 없고 Class레이블만 int형이고 나머지 피처들은 모두 float형인것을 확인하였습니다.

 

▷ 레이블인 Class의 속성을 자세히 봤을때 매우 불균형한 분포를 가지고 있다는 것을 확인하였습니다. 여기서 0은 정상적인 데이터 1은 사기 데이터를 의미합니다. 일반적으로 사기 검출데이터는 적을 수 있기 때문에 이러한 불균형한 분포를 가지게 된것 같습니다.

 

 

- 이렇게 레이블이 불균형한 데이터는 학습을 시키면 예측 성능의 문제가 발생할 수 있습니다. 그 이유는 이상 레이블을 가지는 데이터 건수가 매우 적기 때문에 제대로 다양한 유형을 학습하지 못하는 상태인데 그에 비해 정상 레이블을 가지는 데이터는 매우 많기 때문에 일방적으로 정상 레이블로 치우친 학습을 수행하여 제대로 된 이상 데이터 검출이 어렵게 되는것입니다.

 

- 지도학습의 경우 이러한 상황을 해결하기 위하여 대표적으로 오버 샘플링(Oversampling)언더 샘플링(Undersampling)을 사용합니다. 먼저 실습을 해보기전에 두가지 샘플링 기법에 대해서 정리를 해보도록 하겠습니다.

 

  • 오버 샘플링(Oversampling): 오퍼 샘플링은 이상 데이터와 같이 적은 데이터 세트를 증식하여서 학습을 위한 충분한 데이터를 확복하는 방법입니다. 
  • 언더 샘플링(Undersampling): 언더 샘플링은 많은 데이터 세트를 적은 데이터 세트 수준으로 감소시키는 방식입니다.

 

 

개념을 잡았으니 다시 실습을 해보도록 하겠습니다.

 

 

해당 데이터에서 Time 피처의 경우 데이터 생성 관련한 속성으로 의미가 없어 삭제를 하고, 그리고 원본 데이터를 유지하기 위해서 copy함수를 사용하여 데이터를 복제하기로 하겠습니다.

[위 과정(데이터 복제, 삭제 등)은 오늘 하는 실습에서 여러번 사용되기 때문에 따로 get_preprocess 라는 함수로 만들어서 사용하도록 하겠습니다.]

 

데이터의 맨 마지막 컬럼을 레이블로 나머지는 피처들로 지정을 하였습니다.

 

다음은 train_test_split을 사용해서 테스트 데이터 세트를 전체의 30%dls Stratified 방식으로 분리하도록 하겠습니다.

(위 과정도 get_train_test_data 라는 함수로 만들도록 하겠습니다.)

 

학습 데이터와 테스트 데이터의 레이블 값 분포 비교를 해봤을때 큰 차이 없이 잘 분할이 되었습니다.

 

이제 모델을 만들어 볼텐데 로지스틱 회귀와 LightGBM 기반의 모델을 사용해서 데이터 가공에 따라서 예측 성능이 어떻게 달라지는지 확인하면서 실습을 해보겠습니다.

 

로지스틱 회귀 실행 결과 재현율이 약 0.6081, ROC-AUC가 0.9709정도 나왔습니다.

다음은 LightGBM을 이용해서 모델을 만들어 보겠습니다.

 

이 과정도 get_train_model_eval 이라는 함수로 지정하도록 하겠습니다. 함수는 다음과 같이 생겼습니다.

 

lightgbm 모델은 재현율 0.7568, ROC-AUC 0.9797로 로지스틱 회귀보다는 높은 결과가 나왔습니다.

 

2. 데이터 분포도 변환


이번 예제는 왜곡된 분포도를 가공한 후에 모델을 다시 테스트 해보도록 하겠습니다. 피처들 중 Amount피처는 신용 카드 사용 금액으로 레이블을 구분하는데 있어서 매우 중요한 역할을 할것으로 예상이 되는데요!! 이 피처의 분포도를 한번 확인해보도록 하겠습니다.

데이터를 보면 사용금액이 1000이하인 데이터가 대부분인 꼬리가 긴 형태의 분포 곡선을 가지고 있습니다.

 

선형 모델은 중요 피처들의 값이 정규 분포 형태를 가지는 것을 선호합니다. 그래서 표준 정규 분포 형태로 변환을 해보도록 하겠습니다. 함수는 사이컷런에서 제공하는 StandardScaler 클래스를 사용하도록 하겠습니다.

 

▷ 정규분포로 변환한 새로운 피처 amount_2를 피처명을 Amount_scaled로 가지게 변경을 한 후 맨 앞 칼럼으로 가져오도록 하였습니다. 그리고 기존의 Amount 피처는 삭제를 시켜주어야 합니다.

[get_preprocess 함수에서 위의 식을 추가하여 업데이트 하도록 하겠습니다.]

 

get_train_test_data 함수를 써서 데이터를 분할시켜줍니다. 그리고 각각 학습을 시키고 평가를 해보겠습니다.

 

 

성능 평가 결과 로지스틱 회귀와 LightGBM 모델 모두 변환 전과 비교해봤을때 성능이 크게 좋아지진 않았습니다.

 

 

이번에는 로그 변환을 해보도록 하겠습니다. 원래의 값들을 log값으로 변환시켜서 큰 값을 작은 값으로 변환해주기 때문에 왜곡을 개선할 수 있습니다. 로그 변환은 log1p()함수를 사용해서 적용할 수 있습니다.

 

그 다음 앞에 방법과 동일하게 get_train_test_data함수와 get_eval 함수를 써서 모델을 만들고 평가를 해보겠습니다.

[get_preprocess 함수에서 위의 식을 추가하여 업데이트 하도록 하겠습니다. ]

 

 

평가 결과 두 모델 모두 성능이 조금씩 개선이 되었습니다. 이 데이터는에서는 정규화 보다는 로그 변환이 더 성능이 좋아지게 함을 알 수 있었습니다.

 

3. 이상치 제거 하기


이상치 데이터(Outlier)는 데이터 세트 중에서 벗어나게 되는 말 그대로 이상 값을 가진 데이터 입니다. 이러한 이상치가 있는 상태에서 모델을 학습하게 되면 성능에 많은 영향을 미치게 됩니다. 그렇기 때문에 이러한 이상치 데이터들을 파악하고 제거해 나가며 개선하는 것이 중요합니다.

 

이상치를 찾는 방법에는 IQR(Inter Quantile Range) 방법이 있습니다. IQR은 사분위값을 이용하는 방법으로 일반적으로 박스 플롯을 사용해서 시각화를 할 수 있습니다. 여기서 사분위는 전체 데이터 세트를 값이 높은 순서대로 정렬해서 1/4씩 분할하여 구간을 나누는 것입니다. 

 

IQR로 이상치를 판단할 때는 일반적으로 IQR에 1.5를 곱해서 나온 범위를 이용해서 최댓값과 최솟값을 결정한 후 이 값들을 초과하거나 미달하는 데이터를 이상치로 판단합니다. IQR을 시각화한 그래프가 바로 박스 플롯입니다. 

 

이상치를 제거하기 전에 결정값과 상관성이 높지 않은 피처들을 파악하기 위해서 heatmap을 통해 시각화 후 파악해보도록 하겠습니다.

시각화 결과 Class 피처와 음의 상관관계가 높은 피처는 V14, V17로 나타났습니다. 두가지 중 V14에 대해서 이상치를 판단하여 제거해보도록 하겠습니다.

 

percentile()를 사용해서 1/4분위, 3/4분위 값들을 구하고 이를 활용해서 IQR을 계산하게 됩니다. 그리고 그 값에 1.5를 곱하여 최댓값과 최솟값을 구하고 이보다 크고 작은 경우를 이상치로 판단하도록 하였습니다.

 

이상치 인덱스를 출력해봤을때 다음과 같이 나왔습니다.

이제 이 이상치들을 제거할텐데 앞에서 계속 활용했던 get_preprocess() 함수를 업데이트(이상치를 제거하는 부분) 하여 제거를 하고 예측 성능 평가까지 실행해보도록 하겠습니다.

 

▷ 평가 결과 두 모델 모두 예측 성능이 향상되었습니다. 로지스틱은 재현율이 60.81에서 67.12로 증가하였으며 LightGBM의 경우 76.35에서 82.88로 증가하였습니다.

 

 

 

모델의 성능을 향상시키는 방법에는 다양한 방법들이 존재합니다. 그중에서도 요번 예제 데이터에서는 데이터의 분포와 이상치를 통해서 모델의 성능이 향상되는것을 확인하였습니다. 위 실습에서는 피처 하나만 가지고 이상치를 제거했지만 다른 피처들도 이상치를 파악하고 제거한다면 더욱더 좋은 결과가 나오지 않을까 하는 생각이 들었습니다. 

 

 

 

Reference


파이썬 머신러닝 완벽가이드

'Machine Learning' 카테고리의 다른 글

의사결정 나무 실습  (0) 2020.05.07
K-NN 알고리즘  (0) 2020.05.05
LightGBM  (3) 2020.04.28
XGBoost 실습 - 사이킷런 래퍼 -  (0) 2020.04.27
XGBoost 실습 - 파이썬 래퍼 -  (0) 2020.04.27