이진분류란?

이진분류두 개의 범주 또는 클래스로 데이터를 분류하는 작업

주로 두 가지 클래스를 0과 1, 또는 True와 False로 나타내며, 이들 중 어느 한 쪽에 속할 가능성을 예측하는 것이 목표

이직여부를 한번 예측해보자

목표

  1. EDA 분석
  2. 데이터 전처리
  3. 머신러닝

데이터 불러오기

import pandas as pd
train = pd.read_csv(r"../bigdata_analyst_cert-main/bigdata_analyst_cert-main/part2/ch6/hr_train.csv")
test = pd.read_csv(r"../bigdata_analyst_cert-main/bigdata_analyst_cert-main/part2/ch6/hr_test.csv")
  • train, test데이터를 각각 불러온다.

EDA 탐색석 데이터 분석

데이터 정보 확인

train.info()

out:

#   Column                  Non-Null Count  Dtype  
---  ------                  --------------  -----  
 0   enrollee_id             15326 non-null  int64  
 1   city                    15326 non-null  object 
 2   city_development_index  15326 non-null  float64
 3   gender                  11750 non-null  object 
 4   relevent_experience     15326 non-null  object 
 5   enrolled_university     15012 non-null  object 
 6   education_level         14961 non-null  object 
 7   major_discipline        13045 non-null  object 
 8   experience              15272 non-null  object 
 9   company_size            10539 non-null  object 
 10  company_type            10383 non-null  object 
 11  last_new_job            14984 non-null  object 
 12  training_hours          15326 non-null  int64  
 13  target                  15326 non-null  float64
dtypes: float64(2), int64(2), object(10)
  • info()를 통해 데이터 확인

결측치 확인하기

train.isnull().sum()
test.isnull().sum()

out:

train
enrollee_id                  0
city                         0
city_development_index       0
gender                    3576
relevent_experience          0
enrolled_university        314
education_level            365
major_discipline          2281
experience                  54
company_size              4787
company_type              4943
last_new_job               342
training_hours               0
target                       0

...
  • isnull().sum()으로 결측치 확인

카테고리별 갯수 확인

train.nunique()
test.nunique()

out:

enrollee_id               15326
 city                        123
 city_development_index       93
 gender                        3
 relevent_experience           2
 enrolled_university           3
 education_level               5
 major_discipline              6
 experience                   22
 company_size                  8
 company_type                  6
 last_new_job                  6
 training_hours              241
 target                        2
 dtype: int64,
 enrollee_id               3832
 city                       113
 city_development_index      87
 gender                       3
 relevent_experience          2
 enrolled_university          3
 education_level              5
 major_discipline             6
 experience                  22
 company_size                 8
 company_type                 6
 last_new_job                 6
 training_hours             235
 ...

타겟 확인하기

train['target'].value_counts()

out:

0.0    11517
1.0     3809
  • 타겟 확인

set을 이용한 카테고리 차이 비교

cols = train.select_dtypes(include='object').columns
for col in cols:
    set_train = set(train[col])
    set_test = set(test[col])
    same = (set_train == set_test)
    if same:
        print(col, "\t 카테고리 동일함")
    else:
        print(col, "\t 카테고리 동일하지 않음")

out:

city 	 카테고리 동일하지 않음
gender 	 카테고리 동일함
relevent_experience 	 카테고리 동일함
enrolled_university 	 카테고리 동일함
education_level 	 카테고리 동일함
major_discipline 	 카테고리 동일함
experience 	 카테고리 동일함
company_size 	 카테고리 동일함
company_type 	 카테고리 동일함
last_new_job 	 카테고리 동일함

데이터 전처리

타겟데이터 추출

target = train.pop('target')
  • pop을 이용하여 train데이터의 target을 추출

결측치 처리

train = train.fillna("X")
test = test.fillna("X")
  • fillna로 결측치에 문자열 X를 넣는다.

레이블 인코딩

from sklearn.preprocessing import LabelEncoder
combined = pd.concat([train, test])
cols = train.select_dtypes(include='object').columns
for col in cols:
    le = LabelEncoder()
    combined[col] = le.fit_transform(combined[col])
n_train = len(train)
train = combined[:n_train]
test = combined[n_train:]
  • 레이블 인코딩을 사용하여 문자형(카테고리형) 데이터를 수치형으로 변환하는 과정

  • traintest 데이터셋에 있는 모든 문자형 변수를 한 번에 인코딩한 뒤, 다시 traintest로 나눔

  • LabelEncoder 임포트: LabelEncoder는 문자형 데이터를 숫자로 변환하는 데 사용되는 클래스

  • 데이터 병합: pd.concat([train, test])를 통해 traintest 데이터를 세로로 결합
    - traintest에 있는 문자형 컬럼의 값들이 서로 다른 범주를 가질 수 있기 때문
    - 두 데이터를 결합하여 각 컬럼의 범주를 일관성 있게 인코딩

  • 문자형 컬럼 선택: train 데이터에서 object 타입(문자형)의 컬럼만 선택
    LabelEncoder는 숫자형 데이터에 적용할 수 없기 때문에 문자형 컬럼을 대상으로 선택

for col in cols:
    le = LabelEncoder()
    combined[col] = le.fit_transform(combined[col])
  • 컬럼별 레이블 인코딩: cols에 있는 각 컬럼마다 레이블 인코딩수행
    • LabelEncoder 객체인 le를 만들고, 각 컬럼에 대해 fit_transform을 수행하여 텍스트 값을 숫자 값으로 변환
    • combined[col] = le.fit_transform(combined[col])은 각 컬럼의 문자형 데이터를 숫자형으로 인코딩하여 combined 데이터셋에 적용

LabelEncoder는 문자열 범주를 0부터 시작하는 정수 값으로 변환

  • train과 test 다시 나누기: n_train = len(train)을 통해 원래 train 데이터셋의 길이를 저장
    • train = combined[:n_train]: combined 데이터셋의 첫 n_train만큼을 다시 train으로 할당

    • test = combined[n_train:]: 나머지 부분은 test로 할당하여 원래의 test 데이터셋을 복구


      스케일링

RobustScaler를 사용해 traintest 데이터의 숫자형(수치형) 변수에 대해 스케일링을 수행
RobustScaler이상치(outliers)에 영향을 덜 받으면서 데이터를 정규화하는 데 유용

from sklearn.preprocessing import RobustScaler
scaler = RobustScaler()
  1. RobustScaler 임포트 및 객체 생성: RobustScaler는 이상치의 영향을 줄이면서 데이터를 변환하는 스케일러
    주로 중앙값(Median)과 IQR(Interquartile Range)을 기반으로 변환을 수행하여 이상치에 민감하지 않도록 데이터를 조정
n_cols = train.select_dtypes(exclude='object').columns
  1. 숫자형 변수 선택: select_dtypes(exclude='object')를 통해 문자형 컬럼을 제외한 모든 숫자형 컬럼 선택 RobustScaler는 수치형 데이터에만 적용할 수 있기 때문에, 이 단계에서 수치형 컬럼만 선별
train = scaler.fit_transform(train)
test = scaler.fit_transform(test)
  1. 스케일링 적용: fit_transform을 통해 traintest 데이터를 각각 스케일링
    • fit_transform데이터의 중앙값과 IQR을 계산하여 데이터를 변환
    • train에 대해 fit_transform을 먼저 적용하여 train 데이터에 맞춘 스케일링 기준을 설정
    • test에도 fit_transform을 사용하고 있는데, 이 부분은 주의가 필요
      보통 train에서 계산된 스케일링 기준(fit)을 transform을 통해 test에 적용
      train에만 fit_transform, test에는 transform을 사용하는 것이 더 적절

RobustScaler의 원리

RobustScaler는 데이터를 중앙값을 0으로 맞추고 IQR(25~75% 범위)을 1로 스케일링
데이터의 이상치에 민감하지 않도록 돕는 방법


검증 데이터 분할

from sklearn.model_selection import train_test_split
X_tr, X_val, y_tr, y_val = train_test_split(train, target, test_size=0.2, random_state=0)
  • train데이터와 test데이터를 8:2로 분리한다.

머신러닝 학습

RandomForest 머신러닝 학습

from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(max_depth=15, n_estimators=500)
rf.fit(X_tr,y_tr)
rf_pred = rf. predict_proba(X_val)

from sklearn.metrics import roc_auc_score
roc_auc = roc_auc_score(y_val, rf_pred[:,1])
roc_auc

out: 0.7841196426313792

이 코드는 랜덤 포레스트 모델을 사용하여 분류 문제를 푼 후, 모델의 예측 성능을 ROC AUC 지표로 평가하는 과정

  1. RandomForestClassifier 임포트
  • RandomForestClassifier는 여러 개의 결정 트리를 결합하여 분류 성능을 향상시키는 앙상블 학습 모델
  • 랜덤 포레스트는 각 트리를 독립적으로 학습하고, 트리들의 예측을 투표 방식으로 합산해 최종 결과를 도출
  1. 하이퍼파라미터 설정:

    • max_depth=15: 각 결정 트리의 최대 깊이를 15로 제한하여 트리의 과적합을 방지
    • n_estimators=500: 총 500개의 트리를 학습 트리 수가 많을수록 예측 성능이 안정적이지만, 학습 시간이 길어 짐
  2. 모델 학습: fit() 메서드를 사용하여 학습 데이터 X_tr와 타깃 변수 y_tr을 학습

  3. 예측 확률 계산: predict_proba() 메서드는 각 클래스에 속할 확률을 반환 X_val 검증 데이터에 대해 예측 확률을 계산하고, rf_pred에 저장

    • rf_pred는 2차원 배열로, rf_pred[:, 0]은 클래스 0(예: 음성)의 확률을, rf_pred[:, 1]은 클래스 1(예: 양성)의 확률을 의미
  4. roc_auc_score 임포트 및 AUC 계산:

    • roc_auc_score()는 ROC AUC(Receiver Operating Characteristic - Area Under Curve) 점수를 계산하는 함수
    • y_val: 검증 데이터의 실제 타깃 값.
    • rf_pred[:, 1]: 랜덤 포레스트 모델이 예측한 클래스 1에 대한 확률
      ROC AUC는 클래스 1의 확률을 기준으로 모델이 분류를 얼마나 잘 수행하는지를 측정
  5. ROC AUC 점수 출력: roc_auc는 모델의 ROC AUC 점수로, 0.5~1.0 사이의 값을 가지며, 1.0에 가까울수록 성능이 좋음
    ROC AUC는 클래스 간 분류 능력을 평가하는 중요한 지표로, 특히 불균형 데이터에서 유용

XGBoost 머신러닝

from xgboost import XGBClassifier
xb = XGBClassifier(n_estimators=300, learning_rate=0.1, max_depth=6, random_state=0)
xb.fit(X_tr, y_tr)
xb_pred = xb.predict(X_val)

from sklearn.metrics import roc_auc_score
roc_auc = roc_auc_score(y_val, xb_pred)
roc_auc

out: 0.6947054939806425

  • XGBoost도 다양한 하이퍼 파라미터가가 있음

RandomForest + XGBoost

from sklearn.ensemble import StackingClassifier
from sklearn.linear_model import LogisticRegression
base_estimators=[('xgb',xb),('rf',rf)]
stack_model = StackingClassifier(estimators = base_estimators, final_estimator=LogisticRegression(), cv=5)
stack_model.fit(X_tr, y_tr)

stack_pred_proba = stack_model.predict_proba(X_val)[:, 1]
auc_score = roc_auc_score(y_val, stack_pred_proba)
auc_score

out: 0.7855132725544457

  • 앙상블 모델로, 모델들을 스텍처럼 섞거나 쌓을 수 있다.
profile
gpt로 다시 배우는 개발

0개의 댓글