박가방

2. 모델링 간단 요약 - (이진 분류) 본문

데이터 마이닝/딥러닝

2. 모델링 간단 요약 - (이진 분류)

박가방 2023. 3. 22. 11:09

회사 이직률 예측 - 분류(0 , 1)

 

1. 환경 준비

 

 ① 라이브러리

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.metrics import *
from sklearn.preprocessing import MinMaxScaler

from keras.models import Sequential
from keras.layers import Dense
from keras.backend import clear_session
from keras.optimizers import Adam

 ② 학습 곡선 함수

# 학습곡선 함수
def dl_history_plot(history):
    plt.figure(figsize=(10,6))
    plt.plot(history['loss'], label='train_err', marker = '.')
    plt.plot(history['val_loss'], label='val_err', marker = '.')

    plt.ylabel('Loss')
    plt.xlabel('Epoch')
    plt.legend()
    plt.grid()
    plt.show()

 ③ 데이터 로딩

# data 읽기
path = "https://raw.githubusercontent.com/DA4BAM/dataset/master/Attrition_train_validation.CSV"
data = pd.read_csv(path)

#np.where함수를 사용하여 삼항연산자를 통해 Yes 를 1 NO를 0 
data['Attrition'] = np.where(data['Attrition']=='Yes', 1, 0)
data.head(10)

 

④ 불필요한 열 제거

# 불필요한 변수 제거
data.drop('EmployeeNumber', axis = 1, inplace = True)

 

2. 데이터 전처리

 

①결측치 조회

②데이터 정리

# target 설정
target = 'Attrition'

# 데이터 분리
x = data.drop(target, axis = 1)
y = data.loc[:, target]

③가변수화

- 먼저 data.info()를 통해 object 열을 찾아준 후 모든 열에 대해 가변수화를 진행하였다.

# 가변수화
dum_cols = ['BusinessTravel','Department','Education','EducationField','EnvironmentSatisfaction','Gender', 
            'JobRole', 'JobInvolvement', 'JobSatisfaction', 'MaritalStatus', 'OverTime', 'RelationshipSatisfaction',
            'StockOptionLevel','WorkLifeBalance' ]

x = pd.get_dummies(x, columns = dum_cols ,drop_first = True)
x.head()

 

④데이터 분할

# 학습데이터 ==> train : val
# test_size & train_size = 0.??? -> 비율로 분할, = 1보다 큰 자연수 - 개수로 분할
x_train, x_val, y_train, y_val = train_test_split(x, y, test_size=200, random_state = 2022)

⑤스케일링

#스케일링 0~1
scaler = MinMaxScaler()
x_train = scaler.fit_transform(x_train)
x_val = scaler.transform(x_val)
# 비율로 보자. 이직률이 16%
y_train.value_counts() / len(y_train) 


#일반적으로 클래스 unbalnced는 y에 대해서다.

3. 모델

① features 입력

nfeatures = x_train.shape[1]
# nfeatures : 53

② 구조 설계

 

#메모리 정리
clear_session()

#모델 선언
# relu 대신 다른 활성화 함수를 쓰면 좋아질 순 있으나, 급격히 좋아지진 않을 것.
# output 레이어는 이진분류이므로 sigmoid, 0과 1의 확률값으로 변경하기 위해서 사용

model1 = Sequential([Dense(16,input_shape=(nfeatures,), activation = 'relu'),
                     Dense(8, activation = 'relu'),
                     Dense(4, activation = 'relu'),
                     Dense(1, activation= 'sigmoid')])

#모델 요약
model1.summary()

# 이번 목표 : 히든레이어를 늘리고 줄이고, 하면서 여러 기법으로 성능을 확인해볼 것.

③ 컴파일

model1.compile( optimizer = Adam(learning_rate = 0.1), loss = 'binary_crossentropy') 
# binary_crossentrophy 유의

④ 학습

history = model1.fit(x_train, y_train, epochs = 100, validation_split = 0.2).history

⑤ 학습 곡선

- 과대 적합된 결과 확인 가능, learing_rate를 줄여서 이를 막는걸 기대해볼 수도 있음.

dl_history_plot(history)

4. 검증

 - activation fuction인 sigmoid를 output layer에 넣었고 sigmoid가 결과를 0~1 사이의 확률값으로 변환시켜줌.
-  예측 평가 시 이를 분류 문제이므로 np.where로 0과 1함수로 변환해줄 것임

# 예측 값 할당
pred1 = model1.predict(x_val)

# np.where(조건문이 , 참 , 거짓) - pred1이 0.5이상이면 1
pred1 = np.where(pred1 >= 0.5, 1 ,0)

# 성능 결과 표 확인
print(classification_report(y_val, pred1))

여기서 support는 test_size 이므로 샘플링과는 다르다. train_test_split( starify = y)

- class가 극도로 unbalance한 상황에서 Accuracy를 보면 좋지 않다.
- 이런 데이터 셋은 많을 것이다. 이유는 일반적으로 소수의 클래스를 맞추는게 대게의 목표기 떄문 - 이직, 사기 등
- 이럴 때는 f1_score를 보는게 중요

 

5. Resampling

 - 앞 데이터 셋의 Target 클래스가 불균형한지 보고, oversampling으로 개수를 맞춰주고 학습시켜보자.

y_train.value_counts()

OverSampling에는 Up과 Smote가 있다.

· up 방식 - 0의 881에 맞춰서 1의 169를 881로 맞춰줌

 

 5.1 라이브러리 불러오기

# 라이브러리 불러오기
from imblearn.over_sampling import RandomOverSampler

 5.2 데이터 셋을 OverSampling으로 ReSampling하기.

#샘플링 함수 할당
ros = RandomOverSampler()

# transform() 과 같이. fitting 하면서 resample을 적용하라는 뜻
x_train_ros, y_train_ros = ros.fit_resample(x_train, y_train)

 5.3 모델링 선언 & 컴파일 & 학습

# 메모리 정리
clear_session()

# 모델 선언
model2 = Sequential([Dense(16,input_shape=(nfeatures,), activation = 'relu'),
                     Dense(8, activation = 'relu'),
                     Dense(4, activation = 'relu'),
                     Dense(1, activation= 'sigmoid')])

# 컴파일
model2.compile( optimizer = Adam(learning_rate = 0.001), loss = 'binary_crossentropy') 

# 학습
history = model2.fit(x_train_ros, y_train_ros, epochs = 150, validation_split = 0.2).history

 5.4 학습곡선

5.5 검증

- 예측을 위한 Validation 값은 OverSampling 하지 않는다.

# 예측값 전처리 후 할당
pred2 = model2.predict(x_val)
pred2 = np.where( pred2>= 0.5, 1, 0)

# 성능 결과
print(classification_report(y_val, pred2))

기존                                                                                           변경 후

 

결론 : 큰 차이는 없지만 결과적으로 정확도와 f1_score는 증가하였다.

'데이터 마이닝 > 딥러닝' 카테고리의 다른 글

3. 모델링 간단 요약 - 다중 분류 (방법1, 방법2)  (0) 2023.03.23
3.1 softmax  (0) 2023.03.22
1.1 활성화 함수 Sigmoid, Relu  (0) 2023.03.22
Relu  (0) 2023.03.22
1. 모델링 간단 요약(선형 회귀)  (0) 2023.03.22