상세 컨텐츠

본문 제목

혼공학습단 10기 머신러닝 배워보자 3주차!!

혼공학습단

by 공돌이주인 2023. 7. 15. 23:55

본문

 벌써 혼공학습을 시작한 지 3주차가 되었다. 심지어 6주 과정 중 절반인 3주차이다 ㅎㅎㅎ...

단기간에 인공지능을 완벽히 학습하기는 어렵지만 끝까지 도전해 보고자 한다.

 

이번 혼공머신의 3주차 과정은 Chapter4 로지스틱 회귀와 확률적 경사 하강법이다. 

앞 전 주차에서는 분류와 회귀 문제를 풀어보고 손코딩까지 해보았다. 

 

Chapter 4-1 

이번 챕터에서는 선형 회귀와 비슷한 로지스틱 회귀에 대해 공부해 보았다. 로지스틱 회귀는 선형 회귀와 같은 선형 방정식을 사용한 알고리즘이다. 하지만 선형 회귀와 달리 밑의 그림과 같은 시그모이드 함수, 혹은 소프트맥스 함수라는 것을 사용하여 클래스의 확률을 구할 수 있다.

시그모이드 함수

시그모이드 함수 : 출력을 0과 1 사이의 값으로 압축하여 이진 분류를 수행한다. 위의 그래프에서 보자면 0.5라는 값을 기준으로 0.5 미만의 값은 0, 초과의 값은 1로 출력하여 분류 수행한다. 참고로 0.5 일때는 라이브러리마다 다르지만 사이킷런에서는 음성 클래스인 0으로 판단한다. 

위의 시그모이드 함수는 아래와 같은 코드로 만들 수 있었다.

import numpy as np  #로지스틱 회귀
import matplotlib.pyplot as plt
z = np.arange(-5, 5, 0.1)
phi = 1 / (1 + np.exp(-z))

소프트맥스 함수 : 소프트맥스는 다중 분류를 수행하기 위한 정규화된 지수 함수이다. 앞서 말한 시그모이드 함수는 출력을 0과 1로 두 가지의 출력을 통해 클래스를 분류했다. 소프트맥스 함수는 클래스가 2개보다 많을 때 선형 방정식들의 값들을 0~1 사이로 만들면서 출력값들의 합을 1이 되도록 하는 함수이다. 이 함수로 여러 개의 클래스에 대한 확률을 예측하는 모델을 만들 수 있다.

from scipy.special import softmax #소프트맥스 함수
proba = softmax(decision, axis=1) #decision은 배열 axis=1로 각 행마다 함수 계산
 
print(np.round(proba, decimals=3))
 

[[0. 0.014 0.841 0. 0.136 0.007 0.003]

[0. 0.003 0.044 0. 0.007 0.946 0. ]

[0. 0. 0.034 0.935 0.015 0.016 0. ]

[0.011 0.034 0.306 0.007 0.567 0. 0.076]

[0. 0. 0.904 0.002 0.089 0.002 0.001]] 

이렇게 클래스 별로 확률값들을 예측하여 알려준다.

 

기본 미션 확인문제 2번. 로지스틱 회귀가 이진 분류에서 확률을 출력하기 위해 사용하는 함수는 무엇인가요?

1. 시그모이드 함수

2. 소프트맥스 함수

3. 로그함수

4. 지수함수

답은 1번 시그모이드 함수이다. 이진 분류를 수행하기 위해서는 출력값을 0과 1로 나눌 수 있는 시그모이드 함수를 사용해야 한다. 2번 소프트맥스 함수는 다중 분류에서 사용한다.

Chapter 4-2

 마지막으로 확률적 경사 하강법이다. 

내가 원하는 데이터 분류 모델을 만든 후 가장 중요한 것 중 하나가 기존 데이터에서 새로운 추가 데이터를 모델에 학습시키는 것이라 할 수 있다. 이런 훈련 방식이 점진적 학습으로 대표적인 점진적 학습 알고리즘으로 확률적 경사 하강법이 있다. 

확률적 경사 하강법 : 훈련 세트에서 데이터를 조금씩 꺼내거나(미니배치 경사 하강법), 한 번에 전체 데이터를 사용하여(배치 경사 하강법) 손실 함수의 경사에 따른 최적의 모델을 찾는 알고리즘

손실 함수 : 위의 알고리즘이 최적화할 대상이다. 이진 분류에서는 로지스틱 회귀 손실 함수, 다중 분류에서는 크로스엔트로피 손실 함수, 회귀에서 평균 제곱 오차 손실 함수를 사용한다.

 

로지스틱 손실 함수 (로그함수)

이진 분류에서 사용하는 손실 함수는 위의 그래프와 같은데 x축이 예측 확률이 된다. 양성 클래스 1일 때 손실은 -log(예측 확률)로 계산, 음성 클래스 0일 때 손실은 -log(1-예측확률)로 계산한다. 값이 0에 가까울수록 손실이 크다고 생각하면 된다.

다중 분류에서 사용하는 크로스엔트로피 손실 함수와 회귀 문제에서 사용하는 평균 제곱 오차는 다음과 같다. 

크로스엔트로피와 평균 제곱 오차

from sklearn.linear_model import SGDClassifier # 확률적 경사 하강법을 제공하는 분류용 클래스

sc = SGDClassifier(loss='log_loss', max_iter=10, random_state=42) # 손실함수는 log, max_iter는 학습할 에포크 횟수
sc.fit(train_scaled, train_target)

에포크 : 전체 데이터를 모두 사용하는 한 번 반복을 의미하는 것으로 모델에 적절한 에포크 횟수를 지정하고 반복하여 좋은 정확도를 가진 모델을 만들어야 한다.

 

같은 데이터를 사용하더라도 에포크 횟수에 따라 과소적합이나 과대적합이 될 수 있다. 에포크는 모델이 훈련데이터를 학습하는 횟수라고 할 수 있다. 만약 에포크 횟수가 적다면 훈련 데이터를 덜 학습한 과소적합 모델일 가능성이 높고, 그 반대로 많은 에포크 횟수라면 과대적합 모델일 가능성이 높게 된다.

선택 미션
300번 에포크한 훈련 세트와 테스트 세트의 점수

위의 그래프에서 100번의 에포크에서 모델이 적합한 것을 알 수 있다. 그 이전에서는 과소적합, 100번 이후로는 과대적합이 되는 것으로 추측 가능하다.

import numpy as np # 에포크와 과대/과소적합

sc = SGDClassifier(loss='log_loss', random_state=42)

train_score = []
test_score = []

classes = np.unique(train_target)

for _ in range(0, 300): # 반복문 for문을 통해 300번째 에포크 진행
    sc.partial_fit(train_scaled, train_target, classes=classes)

    train_score.append(sc.score(train_scaled, train_target))
    test_score.append(sc.score(test_scaled, test_target))

import matplotlib.pyplot as plt
plt.plot(train_score, color='red') #그래프 그리기
plt.plot(test_score)
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.show()
 
#에포트 100회로 모델 훈련 진행
sc = SGDClassifier(loss='log_loss', max_iter=100, tol=None, random_state=42
sc.fit(train_scaled, train_target)

 

관련글 더보기