Logistic Regression 구현 - (train/test 분할, 교차검증(cross_val_score))

minnim·2023년 12월 5일

Logistic Regression

Wisconsin Breast Cancer Data 사용

로지스틱 회귀(Logistic Regression)는 회귀 문제가 아니라 분류 문제에 사용되는 알고리즘 중 하나이다. 주로 이진 분류(binary classification)에 적용되며, 두 개의 클래스 중 하나에 속하는지 여부를 예측하는데 사용된다. 다중 클래스 분류(multiclass classification)로 확장하여 여러 개의 클래스로 분류할 수도 있다.

로지스틱 회귀는 선형 회귀와 유사하게 입력 특성과 가중치의 선형 결합을 계산하지만, 출력을 특정 범위로 제한하는 로지스틱 함수 또는 시그모이드 함수를 사용하여 결과를 반환한다.

# 필요한 module import
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn import linear_model
from sklearn.model_selection import cross_val_score
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense
from tensorflow.keras.optimizers import Adam
  • load_breast_cancer
    • scikit-learn에서 제공하는 내장 데이터셋 중 하나인 유방암 데이터셋을 불러오는 함수
    • 유방암 진단에 관련된 특성을 포함
  • MinMaxScaler
    • 데이터의 스케일을 조정하기 위한 스케일러
    • 데이터의 특성을 0과 1 범위로 스케일 조정
  • train_test_split
    • 데이터를 훈련용과 테스트용으로 나누는 함수
  • cross_val_score
    • 교차 검증을 수행하여 모델의 성능을 평가하는 함수
    • 교차 검증은 데이터를 여러 번 반복해서 나누어 모델을 평가하여 모델의 일반화 성능을 더 정확하게 측정하는 데 사용
  • Sequential, Flatten, Dense
    • Keras에서 제공하는 딥러닝 모델을 구축하는데 사용되는 클래스 - Sequential: 모델의 뼈대를 만들어주는 클래스
    • Flatten은 입력 데이터를 평탄화하는 역할을 하는 층
    • Dense는 완전 연결 층
  • Adam
    • Keras에서 제공하는 옵티마이저
    • Adam은 경사 하강법의 한 종류로, 모델의 가중치를 업데이트하는데 사용

💻모델 구현

기본 데이터 세팅

  • x_data ➡ cancer.data : 세포 특징
  • t_data ➡ cancer.target : 악성종양은 0, 양성종양은 1
 # Raw Data Loading
cancer = load_breast_cancer()

# x_data(feature): 세포 특징 | t_data: 악성종양이냐, 양성종양이냐(0,1) | 데이터의 설명

# x_data => cancer.data
# t_data => cancer.target

print(cancer.data.shape, cancer.target.shape)  # 데이터 shape 확인
# (569, 30) : x_data는 총 569개의 행으로 구성, 컬럼(feature)은 30개
# (569,) : t_data 역시 총 569개, 0과 1로 구성!

# return_counts = True : 각각의 unique한 값의 빈도수를 세어줌
print(np.unique(cancer.target, return_counts = True))

# (array([0, 1]), array([212, 357]))
#                        0.37, 0.63  (0과 1의 비율)
# 0(악성종양)과 1(양성종양)로 구성
# 약간의 데이터 불균형 존재(imbalanced data) ==> 0: 212개 , 1: 357개


# 데이터셋 저장
x_data = cancer.data
t_data = cancer.target

# boxplot으로 이상치와 데이터 분포를 간단하게 확인!
plt.boxplot(x_data)
plt.show()

업로드중..

  • boxplot으로 확인해보니 데이터 정규화가 필요!(스케일이 너무 다름)
  • 원래 정규화는 당연히 이상치를 제거하고 진행해야 함!
  • 수치적 이상치로는 보이나 실제로 있을 수 있는 데이터이기 때문에 일단 이상치가 존재하지 않는다고 가정하고 진행

🔍스케일링

  • MinMaxScalre 적용 후 데이터 분포 다시 확인
scaler = MinMaxScaler()
scaler.fit(x_data)
x_data_norm = scaler.transform(x_data)

# plt.boxplot(x_data_norm)
# plt.show()
# 박스플롯으로 확인해보니 0과 1로 데이터들이 정규화된 것을 알 수 있음

🔍 train, test 데이터 분리

  • 학습용 데이터와 평가용 데이터로 분리
# 데이터 분리
# train data와 test data로 분리(데이터를 섞어서 분리)
x_data_train_norm, x_data_test_norm, t_data_train, t_data_test = \
train_test_split(x_data_norm,
                 t_data,
                 stratify=t_data,
                 test_size=0.2,   # default값은 0.25
                 random_state=3)

# 섞어서 분리했기 때문에 데이터의 편향이 없을거라 생각되나
# 확인해보기
np.unique(t_data_test, return_counts=True )
# (array([0, 1]), array([42, 75]))  # 35% , 65%
# 원 데이터 0과 1의 비율(37%, 63%)과 유사 

💡cross_val_score

  • scikit-learn 라이브러리에서 제공되는 교차 검증(cross-validation)을 수행하는 함수
  • 모델의 성능을 평가하기 위해 데이터를 여러 부분으로 나누어 모델을 여러 번 훈련하고 평가하는데 사용
  • 교차 검증은 모델의 일반화 성능을 더 정확하게 평가할 수 있게 해주며, 데이터가 작을 때 과적합(overfitting)을 방지하는 데 도움이 된다.


  • sklearn_model: 평가하려는 scikit-learn 모델 객체입니다. 이 모델은 이미 훈련되어 있어야 하며, 교차 검증을 통해 평가됩니다.

  • x_data_train_norm:모델의 입력 데이터로 사용되는 훈련용 특성 데이터입니다. 일반적으로는 모델을 훈련시키기 위한 특성들이 정규화(normalization)되어 있습니다.

  • t_data_train: 모델의 훈련용 타겟 데이터입니다. 모델이 예측하려는 목표값 또는 레이블이 들어갑니다.

  • cv: 교차 검증을 몇 번(fold) 수행할지를 결정하는 매개변수입니다. 여기에서 cv=5는 5-폴드 교차 검증을 의미하며, 데이터를 5개 부분으로 나누어 5번의 훈련 및 평가를 수행합니다.

  • 반환값 (score): 교차 검증의 각 폴드에서 모델의 성능을 나타내는 점수(스코어)들의 배열이 반환됩니다. 이 점수들은 각 폴드에서의 테스트 데이터에 대한 모델의 성능을 나타냅니다.

💻 sklearn 구현

# sklearn model 구현

sklearn_model = linear_model.LogisticRegression()

# 학습하기 전에 cross validation(교차검증)을 한번 수행해 볼꺼예요!
# train data를 가지고 수행해요!
score = cross_val_score(sklearn_model,
                x_data_train_norm,
                t_data_train,
                cv = 5)    # 다섯번의 accuracy 구하기
                           # 5-폴드 교차 검증을 의미하며, 데이터를 5개 부분으로 나누어 5번의 훈련 및 평가를 수행
print(score)
# [0.97802198 0.94505495 0.95604396 0.98901099 0.94505495]

print(f'sklearn의 평균 validation accuracy : {np.mean(score)}')
# 0.9626373626373625

# 학습 진행
# 학습 시 train 데이터 사용!!
sklearn_model.fit(x_data_train_norm,
                  t_data_train)

# 모델 최종 평가
# 평가 시 test 데이터 사용!!
test_score = sklearn_model.score(x_data_test_norm,
                                 t_data_test)

print(f'모델의 최종 score : {test_score}')   # 0.9649

💻 Tensorflow 구현

activation = 'sigmoid'
optimizer=Adam

# Tensorflow 구현

# 1. 모델 생성
keras_model = Sequential()  # 박스 그리기

# 2. 레이어 생성
# 박스 안에 레이어 두 개 (Flatten, Dense)
# # input_shape는 피쳐개수와 동일하게 설정
keras_model.add(Flatten(input_shape=(30, ))) # 독립변수(feature)가 30개니까 동글뱅이(node)도 30개로 설정
keras_model.add(Dense(units = 1,    # units은 target변수, 즉 t_data와 동일한 개수로 설정
                      activation = 'sigmoid'))

# 3. 모델 설정
keras_model.compile(optimizer=Adam(learning_rate=1e-2),   # 학습 결과가 영 별로면 하이퍼파라미터인 learning_rate를 바꿔보기
                    loss='binary_crossentropy',
                    metrics=['acc']) # metircs = ['acc']: 학습 시 매 epoch마다 validation(모델 학습 시 임시평가하는 것)을 수행하고,
                                        #                 해당 validation의 평가기준은 accuracy를 사용하겠다는 의미

# 4. 학습 진행
keras_model.fit(x_data_train_norm,
                t_data_train,
                epochs=300,
                verbose = 1,   # 매 epoch 마다 학습 결과 출력
                validation_split = 0.2)  # 학습데이터 중 20%를 validation 하는 데 사용하겠다.

# Epoch 300/300
# 12/12 [==============================] - 0s 5ms/step
# - loss: 0.0785 - acc: 0.9808 - val_loss: 0.0917 - val_acc: 0.9560
# training data로 학습한 후
# training data로 평가 vs. validation data로 평가

# loss : training data로 학습한 후 training data를 이용해서 계산한 loss
# val_loss : validation data로 계산한 loss

"-loss: 0.0785 - acc: 0.9808"는 train 데이터에 대한 손실이 0.0785이며 정확도가 0.9808이라는 의미

"val_loss: 0.0917 - val_acc: 0.9560"는 test 데이터에 대한 손실이 0.0917이며 정확도가 0.9560이라는 의미

  • validation data로 계산한 val_loss와 val_accuracy로 평가
  • loss와 acc는 train 데이터로 학습하고 train데이터로 답을 맞추는 것과 다름없기 때문에 이를 평가 지표로 사용하는건 무쓸모.

💡 Metric에 대한 정보

  • loss (손실)

    • train 데이터에 대한 손실 값
    • 모델이 예측한 값과 실제 값 사이의 차이를 나타냄이
    • loss 값이 감소할수록 모델이 더 정확한 예측을 하고 있다는 것을 의미
  • acc (정확도)

    • train 데이터에 대한 정확도를 나타냄
    • 즉, 모델이 훈련 데이터에서 올바르게 분류한 샘플의 비율
    • acc 값이 증가할수록 모델의 성능이 향상되고 있다는 것을 의미
  • val_loss (검증 손실)

    • test 데이터에 대한 손실 값
    • 모델이 train 데이터에 과적합되지 않고, 일반적으로 적용되는 데이터에서 얼마나 좋은 성능을 내는지를 나타냄
    • val_loss 값이 감소하는 것이 이상적
  • val_acc (검증 정확도)

    • test 데이터에 대한 정확도를 나타냄
    • 즉, 모델이 test 데이터에서 얼마나 올바르게 분류하는지를 나타냄
    • vla_acc 값이 증가하는 것이 이상적

🔍 Evaluation(평가)

  • 평가 시 test 데이터 사용해야 함
  • keras_model.evaluate(x_data_test_norm, t_data_test)
# 학습이 다 끝났으니
# Evaluation(평가)!
# !! test 데이터 사용해야 함!!
result = keras_model.evaluate(x_data_test_norm,
                     t_data_test)

print(result)

# [0.08987449109554291, 0.9736841917037964]
#       loss값              accuracy값
profile
일단 해보는 사람

0개의 댓글