피마 인디언 당뇨병 예측
이번 글에서는 kaggle에서 제공하는 피마 인디언 당뇨병 데이터셋을 이용하여 당뇨병 여부를 판단하는 예측 모델 수립, 여러가지 성능 지표를 이용하여 모델의 성능을 평가한다.
피마 인디언 당뇨병 데이터 세트는 다음 피처로 구성된다.
- Pregnancies: 임신 횟수
- Glucose: 포도당 부하 검사 수치
- BloodPressure: 혈압
- SkinThickness: 팔 삼두근 뒤쪽 피하지방 측정값
- Insulin: 혈청 인슐린
- BMI: 체질량지수
- DiabetesPedigreeFunction: 당뇨 내력 가중치 값
- Age: 나이
- Outcome: 클래스 결정 값(0또는 1)

먼저 모델 구현 및 성능 평가를 위한 라이브러리를 import하고, 데이터를 불러와 확인한다.

레이블이 불균등하게 분포하므로 Stratify를 이용하여 학습셋과 테스트셋에 클래스 별로 골고루 분포하게 해야 한다는 것을 알 수 있다.

info()를 이용하여 null값의 개수, 피처의 데이터 타입을 확인하였다.
※이용할 데이터 프레임을 분석하기 위해서 describe()도 자주 사용한다. 다만 사용의 목적이 다르다.

- info() -> null값 개수, 피처의 데이터 타입, 데이터의 용량을 확인하기 위해 사용
- describe() -> 수치형 column의 통계학적 수치(min, max, 4분위값, mean, std 등)를 계산하기 위해 사용

데이터를 train_test_split을 이용하여 학습셋과 테스트셋으로 나누었다. 여기서 stratify = y를 이용하여 클래스의 분포가 균일하게 나누어 주었다.

get_clf_eval2()는 실제 클래스값(y_test), 예측 클래스값(pred), 예측 클래스 확률(pred_proba)를 이용하여 여러가지 성능지표를 계산하도록 작성하였다.

LogisticRegression 모델을 이용하여 학습하고 성능을 평가하였다. 여기서 재현율의 향상을 목표로 precision recall plot을 그렸다.

임계값을 0.42정도로 조정한다면 두 지표의 값이 비슷한 값을 나타내겠지만, 두 지표 모두 낮은 값을 나타낸다. 따라서 describe()를 이용하여 값들을 살펴보았다.

min값이 0인 데이터들을 확인할 수 있다. BloodPressure, skinThickness, Insulin 등 여러 값들이 0일 수 없는 데이터이지만 존재한다는 것은 누락값들을 0으로 처리했기 때문이라는 의심을 할 수 있다. 이를 그래프로 살펴보았다.


Glucose column의 값 분포를 살펴본 결과 0값이 5개 정도 분포한 것을 확인할 수 있다. 0 주변의 값은 없는데 0만 5개 있다는 것은 자연적인 분포가 아닌, 누락값을 0으로 처리했다는 것을 알 수 있다. 다음은 여러 지표들에서 0의 비율이 어느정도 되는지 확인해 보았다.

glucose 같은 경우 0.65%로 낮은 비율이나, Insulin, SkinThickness의 경우 매우 많은 비율을 차지하고 있어 해당 값들을 0이아닌 적절한 값으로 변경할 필요가 있다. 따라서 해당 값들을 평균값으로 대체하였다.

zero_features의 평균값을 mean_zero_features 변수에 저장하였다. 총 5개의 feature이므로 mean_zero_features는 5개의 값을 가지는 Series의 형태로 저장되었다. replace를 이용하여 0값을 평균값으로 변경하였다.
※mean_zero_features는 index로 zero_features의 column, 값은 평균값을 가지고 있다. 이를 replace에 이용한 결과 mean_zero_features의 index에 해당하는 column의 0값을 그 column의 평균값으로 replace하였다. 즉, mean_zero_features가 참조표와 같은 역할을 하여 replace하였다.

로지스틱 회귀의 경우 일반적으로 숫자 데이터에 표준화를 적용하면 더 좋은 성능을 나타내기 때문에 StandardScaler()를 통해 스케일링을 진행하였다. 전처리를 마친 데이터를 다시 로지스틱 회귀를 이용하여 예측하고 성능을 측정하였다. 성능 수치가 이전에 비해 좋아진 것을 확인할 수 있다.
다음으로 분류 결정 임계값의 변화에 따라 어떻게 성능 지표가 변화하는지 확인하기 위해 get_eval_by_threshold()를 작성하였다.

get_eval_by_threshold()는 실제 클래스, 예측 클래스의 1일 확률, 임계값 리스트를 입력하면 binarizer를 통해 임계값을 기준으로 0과 1로 나눈 후 custom_predict에 저장하고, get_clf_eval()을 이용하여 성능을 계산하는 함수이다.


임계값이 0.48일 경우 F1 score가 0.6931로 가장 높은 값을 보인다.
#이 글은 권철민 작가님의 [파이썬 머신러닝 완벽가이드]를 통해 공부한 내용을 바탕으로 정리하였습니다.