이진분류는 두 개의 범주 또는 클래스로 데이터를 분류하는 작업
주로 두 가지 클래스를 0과 1, 또는 True와 False로 나타내며, 이들 중 어느 한 쪽에 속할 가능성을 예측하는 것이 목표
이직여부를 한번 예측해보자
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데이터를 각각 불러온다.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
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:]
레이블 인코딩을 사용하여 문자형(카테고리형) 데이터를 수치형으로 변환하는 과정
train과 test 데이터셋에 있는 모든 문자형 변수를 한 번에 인코딩한 뒤, 다시 train과 test로 나눔
LabelEncoder 임포트: LabelEncoder는 문자형 데이터를 숫자로 변환하는 데 사용되는 클래스
데이터 병합: pd.concat([train, test])를 통해 train과 test 데이터를 세로로 결합
- train과 test에 있는 문자형 컬럼의 값들이 서로 다른 범주를 가질 수 있기 때문
- 두 데이터를 결합하여 각 컬럼의 범주를 일관성 있게 인코딩
문자형 컬럼 선택: 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부터 시작하는 정수 값으로 변환
n_train = len(train)을 통해 원래 train 데이터셋의 길이를 저장train = combined[:n_train]: combined 데이터셋의 첫 n_train만큼을 다시 train으로 할당
test = combined[n_train:]: 나머지 부분은 test로 할당하여 원래의 test 데이터셋을 복구
RobustScaler를 사용해 train과 test 데이터의 숫자형(수치형) 변수에 대해 스케일링을 수행
RobustScaler는 이상치(outliers)에 영향을 덜 받으면서 데이터를 정규화하는 데 유용
from sklearn.preprocessing import RobustScaler
scaler = RobustScaler()
RobustScaler는 이상치의 영향을 줄이면서 데이터를 변환하는 스케일러n_cols = train.select_dtypes(exclude='object').columns
select_dtypes(exclude='object')를 통해 문자형 컬럼을 제외한 모든 숫자형 컬럼 선택 RobustScaler는 수치형 데이터에만 적용할 수 있기 때문에, 이 단계에서 수치형 컬럼만 선별train = scaler.fit_transform(train)
test = scaler.fit_transform(test)
fit_transform을 통해 train과 test 데이터를 각각 스케일링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로 분리한다.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 지표로 평가하는 과정
RandomForestClassifier는 여러 개의 결정 트리를 결합하여 분류 성능을 향상시키는 앙상블 학습 모델하이퍼파라미터 설정:
max_depth=15: 각 결정 트리의 최대 깊이를 15로 제한하여 트리의 과적합을 방지n_estimators=500: 총 500개의 트리를 학습 트리 수가 많을수록 예측 성능이 안정적이지만, 학습 시간이 길어 짐모델 학습: fit() 메서드를 사용하여 학습 데이터 X_tr와 타깃 변수 y_tr을 학습
예측 확률 계산: predict_proba() 메서드는 각 클래스에 속할 확률을 반환 X_val 검증 데이터에 대해 예측 확률을 계산하고, rf_pred에 저장
rf_pred는 2차원 배열로, rf_pred[:, 0]은 클래스 0(예: 음성)의 확률을, rf_pred[:, 1]은 클래스 1(예: 양성)의 확률을 의미roc_auc_score 임포트 및 AUC 계산:
roc_auc_score()는 ROC AUC(Receiver Operating Characteristic - Area Under Curve) 점수를 계산하는 함수y_val: 검증 데이터의 실제 타깃 값.rf_pred[:, 1]: 랜덤 포레스트 모델이 예측한 클래스 1에 대한 확률ROC AUC 점수 출력: roc_auc는 모델의 ROC AUC 점수로, 0.5~1.0 사이의 값을 가지며, 1.0에 가까울수록 성능이 좋음
ROC AUC는 클래스 간 분류 능력을 평가하는 중요한 지표로, 특히 불균형 데이터에서 유용
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도 다양한 하이퍼 파라미터가가 있음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