[5week] ML - 로지스틱 회귀, K-분할 교차 검증

atdawn·2024년 10월 2일
0

AIVLE

목록 보기
14/25

Chapter 4. Logistic Regression

선형회귀와 로지스틱 회귀

로지스틱 함수

  • 분류 문제에 사용
  • 시그모이드(sigmoid) 함수라고도 부름
  • 확률 값 p는 f(x) 값이 커지면 1, 작아지면 0 에 가까워 짐
  • (,)(-\infty,\infty) 범위를 갖는 선형 판별식 결과로 (0,1)(0,1) 범위의 확률 값을 얻게 됨
  • 기본적으로 확률 값 0.5를 임계값(Threshold)로 하여 이보다 크면 1, 아니면 0으로 분류함.

x 데이터가 주어졌을 때 확률을 예측하는 로지스틱 회귀 분석은 학습 데이터를 잘 설명하는 선형 판별식 f(x)의 기울기(a)와 절편(b)를 찾는 문제


로지스틱 회귀 실습 : Diabete(이진 분류)

  • 환경 준비
# 라이브러리 불러오기
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings

warnings.filterwarnings(action='ignore')
%config InlineBackend.figure_format='retina'

# 데이터 읽어오기
path = 'https://raw.githubusercontent.com/jangrae/csv/master/diabetes.csv'
data = pd.read_csv(path)
  • 데이터 확인
  • 데이터 준비 : target='Outcome'

모델링

  • 1단계 : 불러오기
# 1단계: 불러오기
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, classification_report
  • 2단계: 선언하기
# 2단계: 선언하기
model = LogisticRegression(max_iter=500, random_state=1)

max_iter : 최대반복 횟수
-> 지정된 최대 반복 횟수 동안에만 모델이 학습 (무한루프, 과적합 방지)

  • 3단계: 학습하기
# 3단계: 학습하기
model.fit(x_train,y_train)
  • 4단계: 예측하기
# 4단계: 예측하기
y_pred = model.predict(x_test)
  • 5단계 평가하기
# 5단계 평가하기
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))

모델 살펴보기

  • 회귀 계수 확인
# 회귀 계수 확인
print(list(x))
print(model.coef_)
print(model.intercept_)

로지스틱 회귀(Logistic Regression)는 이름에 "회귀"가 들어가지만, 실제로는 분류 문제에 사용되는 이유?

  • 이 모델이 회귀 분석의 기법을 사용하여 확률을 예측
  • 회귀 분석의 기법을 사용하여 확률을 예측하고, 그 확률을 통해 분류를 수행
  • 선형 판별식 z값 확인
# 선형 판별식(z or f(x))
z = model.decision_function(x_test)
print(z[:10]) #10개 확인

  • 시그모이드 함수 사용 : 이진 분류
# 시그모이드 함수 사용
from scipy.special import expit
print(expit(z)[10:21].round(2))

0.5보다 크면 1, 작으면 0이라고 분류

  • 확률값 p 확인
# 확률값 확인
p = model.predict_proba(x_test)
print(p[10:21].round(2))

좌측값은 확인 하지 않아도 됨, 우측값이 확률

임계값 조정

  • 확률값 얻기
# 확률값 얻기
p = model.predict_proba(x_test)

#1의 확률 얻기
p1 =p[:,1] #1번 열만 확인

# 확인 
print(p1[:10])

  • 임계값 = 0.5 : 위의 실습과 같음
  • 임계값 = 0.45
# 임계값 = 0.45
y_pred2 = [1 if x > 0.45 else 0 for x in p1]
print(classification_report(y_test, y_pred2))

정확도가 0.01 증가


로지스틱 회귀 실습 : Iris (다중분류)

...

모델링

# 1단계: 불러오기
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, classification_report

# 2단계: 선언하기
model = LogisticRegression( random_state=1)

# 3단계: 학습하기
model.fit(x_train,y_train)

# 4단계: 예측하기
y_pred = model.predict(x_test)

# 4단계: 예측하기
y_pred = model.predict(x_test)

모델 살펴보기

P(y=kx)=ezkj=1Kezj\large P(y=k|x)=\frac{e^{z_k}}{\sum^K_{j=1}e^{z_j}}

  • 회귀 계수 확인
print(list(x))
print(model.coef_)
print(model.intercept_)

  • 선형 판별식(z or f(x)) z1, z2, z3
# 선형 판별식(z or f(x)) z1, z2, z3
z = model.decision_function(x_test)
print(z[:5])

-softmax 함수 사용
다중 클래스 분류 문제에서 사용되며, 각 클래스에 속할 확률

# softmax 함수 사용
from scipy.special import softmax

print(softmax(z, axis=1)[:5].round(2))

  • 확률값
# 확률값 얻기
p = model.predict_proba(x_test)

# 확인 
print(p[:5].round(2))

가장 큰 확률을 가진 클래스로 예측한다.



K-Fold Cross Validation : K분할 교차 검증

K-분할 교차 검증 개념

  • 모든 데이터가 평가에 한 번, 학습에 k-1번 사용
  • K개의 분할(Fold)에 대한 성능을 예측 -> 평균과 표준편차 계산 -> 일반화 성능
  • 단, k는 2이상 되어야 함. (최소한 한 개씩의 학습용, 검증용 데이터가 필요)

장점

• 모든 데이터를 학습과 평가에 사용할 수 있음
• 반복 학습과 평가를 통해 정확도를 향상시킬 수 있음
• 데이터가 부족해서 발생하는 과소적합 문제를 방지할 수 있음
• 평가에 사용되는 데이터의 편향을 막을 수 있음
• 좀 더 일반화된 모델을 만들 수 있음

단점

  • 반복 횟수가 많아서 많은 시간이 소요

우리 수업에서는

• 평가용 데이터가 따로 있어 가진 데이터가 모두 학습용이면 전체를 K-분할 해도 됨
• 수업에서 사용하는 데이터는 그렇지 않으니 학습용, 평가용으로 분리해 사용해야 함
• 평가용 데이터는 이후 최종 평가에 사용할 데이터이니 성능 검증에 사용하면 안됨
• 그러므로 수업에서의 K-분할은 x_train, y_train 데이터만을 대상으로 함
• 물론 실제 평가에서 얻은 성능이 이 성능보다 더 높거나 낮을 수 있음


K분할 교차 검증 실습 : Diabetes

...

데이터 준비

...

  • 정규화 (KNN)
# 모듈 불러오기
from sklearn.preprocessing import MinMaxScaler

# 정규화
scaler = MinMaxScaler()
scaler.fit(x_train)
x_train_s = scaler.transform(x_train)
x_test_s = scaler.transform(x_test)

성능 예측

  • K분할 교차 검증 방법으로 모델 성능을 예측합니다.
  • cross_val_score(model, x_train, y_train, cv=n) 형태로 사용합니다.
  • cv 옵션에 k값(분할 개수, 기본값=5)을 지정합니다.
  • cross_val_score 함수는 넘파이 배열 형태의 값을 반환합니다.
  • cross_val_score 함수 반환 값의 평균을 해당 모델의 예측 성능으로 볼 수 있습니다.
  • 클수록 좋은 값

  • DecisionTree
# 불러오기
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score

# 선언하기
model = DecisionTreeClassifier(max_depth=5,  random_state=1)

# 검증하기
cv_score = cross_val_score(model, x_train, y_train, cv=10)

# 확인
print(cv_score)
print('평균:', cv_score.mean())
print('표준편차:', cv_score.std())

result={}
result['Decision Tree'] = cv_score.mean()

  • KNN
# 불러오기
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score


# 선언하기
model = KNeighborsClassifier()

# 검증하기 (스케일한 x 사용)
cv_score = cross_val_score(model, x_train_s, y_train, cv=10 )

# 확인
print(cv_score.mean())

# 저장
result['KNN'] = cv_score.mean()
  • Logistic Regression
# 불러오기
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score


# 선언하기
model = LogisticRegression()

# 검증하기
cv_score = cross_val_score(model, x_train, y_train, cv=10)

# 확인
print(cv_score.mean())

# 저장
result['Logistic Regression'] = cv_score.mean()

현재까지의 과정은 아직 fitting을 하지 않음.
학습데이터에 가장 좋은 성능을 가진 것을 확인 한 것 뿐.

# 예측 및 평가 수행
from sklearn.metrics import classification_report

model = LogisticRegression()
model.fit(x_train, y_train)
y_pred = model.predict(x_test)
print(classification_report(y_test,y_pred))



5. Hyperparameter 튜닝

Chapter 1. Hyperparameter

  • 알고리즘을 사용해 모델링할 때 모델 성능을 최적화하기 위해 조절할 수 있는 매개변수
  • 튜닝 하는 방법에 정답은 없음

Decision Tree

  • max_depth
    • 트리의 최대 깊이 제한
    • 기본값: 완벽하게 클래스 결정 값이 될 때까지 깊이를 계속 키우며 분할하거나, 노드가 가지는 데이터 개수가 min_samples_split보다 작아질 때까지 계속 깊이를 증가시킴
    • 이 값이 작을 수록 트리 깊이가 제한되어 모델이 단순해 짐
  • min_samples_leaf
    • leaf가 되기 위한 최소한의 샘플 데이터 수
    • 이 값이 클 수록 모델이 단순해 짐
  • min_samples_split
    • 노드를 분할하기 위한 최소한의 샘플 데이터 수
    • 이 값이 클 수록 모델이 단순해 짐

KNN

  • n_neighbors : (k) 이웃 개수

  • 생각해 볼 수 있는 방법 1 (Grid Search)
    ① 1~n 구간의 정수를 n_neighbors 값으로 해서 모델 성능 정보 수집
    ② 수집된 정보에서 가장 성능이 좋았던 때의 n_neighbors 값을 찾음
    ③ 이 n_neighbors 값을 갖는 KNN 모델을 선언해 학습, 예측 및 평가 과정 진행
    → n 값이 크면 상당히 많은 시간이 소요될 것임
    → 충분한 범위를 옵션 값으로 설정해 확인했으니 다행

  • 생각해 볼 수 있는 방법 2 (Random Search)
    ① 1~n 구간의 정수 중 무작위로 m개 골라 n_neighbors 값으로 해서 모델 성능 수집
    ② 수집된 정보에서 가장 성능이 좋았던 때의 n_neighbors 값을 찾음
    ③ 이 n_neighbors 값을 갖는 KNN 모델을 선언해 학습, 예측 및 평가 과정 진행
    → 임의의 m개만 골라 수행하니 시간 소모는 적을 것임
    → 선택되지 못한 값 중에서 더 좋은 성능을 보이는 값이 있을까 봐 걱정됨

  • 딕셔너리 형태로 파라미터 하나의 범위를 지정한 경우
    • n_neighbors 값이 1부터 100까지 설정되면서 성능을 확인
    • Grid Search의 경우 100번 수행되면서 모든 경우 의 성능 확인
    • Random Search의 경우 지정한 개수의 임의의 값에 대해서만 성능 확인
# 파라미터 하나의 경우
param = {'n_neighbors': range(1, 101)}
  • 딕셔너리 형태로 파라미터 두 개의 범위를 지정한 경우

    • n_neighbors 값이 100개, metric 값이 2개 → 200개 조합이 만들어짐
    • Grid Search 경우 200번 수행되면서 200개 조합에 대해 모든 경우의 성능 확인
    • Random Search의 경우 지정한 개수의 임의의 조합에 대해서만 성능 확인
# 파라미터 두 개 경우
param = {'n_neighbors': range(1, 101),
'metric': ['euclidean', 'manhattan']}


Random Search 사용 법

  1. 함수 불러오기
# 함수 불러오기
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import RandomizedSearchCV
  1. 파라미터 값 범위 지정
  • 딕셔너리 형태로 범위 지정
  • 미지정 값은 기본 값으로 지정
  • 리스트 형태 또는 range함수를 사용해 적절한 step 설정
# 파라미터 선언
param = {'n_neighbors': range(1, 500, 10),
'metric': ['euclidean', 'manhattan']}
  1. 모델 선언
  • Random Search 모델 선언
  • n_iter(임의로 선택할 파라미터 조합 수) 지정
  • 적절한 dv값 지정
# 기본모델 선언
knn_model = KNeighborsClassifier()
# Random Search 선언
model = RandomizedSearchCV(knn_model,
							param,
							cv=3,
							n_iter=20)
  1. 모델 학습
  • Random Search 모델 학습
  • 모델 학습 과정이 최선의 파라미터 값을 찾는 과정
# 학습하기
model.fit(x_train, y_train)
  1. 결과 확인
  • 결과는 딕셔너리 형태
# 수행 정보
model.cv_results_
# 최적 파라미터
model.best_params_
# 최고 성능
model.best_score_
  1. 예측 및 평가
  • 최선의 파라미터 값으로 모델이 자동으로 학습된 상태
  • 곧 바로 예측 및 평가를 진행 할 수 있음.

Random Search + Grid Search 적용 고려

  • Hyperparameter 값을 어떻게 정해야 할 지 경험이 없을 때
  • Random Search와 Grid Search를 함께 사용할 수 있음

profile
복습 복습 복습

0개의 댓글