혼공단/혼공단 5기

혼자 공부하는 머신러닝 + 딥러닝 4장 - 확률적 경사 하강법

하양훈 2021. 2. 12. 14:37
반응형

1. 확률적 경사 하강법

 

<점진적인 학습>

 

- 앞서 훈련한 모델을 버리지 않고, 새로운 데이터에 대해서만 조금씩 더 훈련하는 방식.

- 이렇게 진행할 경우 훈련에 사용한 데이터를 모두 유지할 필요도 없고 앞서 학습한 데이터를 까먹을 일도 없을 것이다.

- 대표적인 점진적 학습 알고리즘으로 확률적 경사 하강법이 있다.

 

<확률적 경사 하강법>

 

- 전체 데이터 세트에서 확률적으로 선택된 하나의 예로 각 단계의 예측 경사를 계산하는 방법

- 확률적이란 말은 '무작위하게' 혹은 '랜덤하게'의 기술적인 표현이다. 

- 확률적 경사 하강법에서 훈련 세트를 한번 모두 사용하는 과정을 에포크(epoch)라고 부른다.

 

- 미니배치 경사 하강법 : 여러개의 샘플을 사용해 경사하강법을 수행하는 방식

- 배치 경사 하강법 : 한번 경사로를 따라 이동하기 위해 전체 샘플을 사용하는 방식, 가장 안정적인 방법이지만 그만큼 컴퓨터 자원을 많이 사용하게 된다. 

 

2. 손실 함수

 

- 머신 러닝 알고리즘이 얼마나 엉터리인지 측정하는 기준, 손실 함수의 값이 작을수록 좋다.

- 비용함수와는 다른 말이다. 하지만 보통 이 둘을 엄격하게 구분하지 않고 섞어서 사용한다.

(손실 함수 : 샘플 하나에 대한 손실을 정의 / 비용 함수 : 훈련 세트에 있는 모든 샘플에 대한 손실 함수의 합) 

 

※ 손실 함수의 경우 미분이 가능해야 하므로, 정확도는 손실함수로 사용이 불가능하다(연속적이지 않고, 듬성듬성 떨어져 있으므로)

 

<로지스틱 손실 함수>

 

- 샘플 4개의 확률을 0.9, 0.3, 0.2, 0.8이라고 가정해 계산해 보면 아래와 같은 표가 나올 수 있다.

예측 확률 실제 정답 손실 함수 계산 결과 손실 체크
0.9 1 -0.9 낮은 손실
0.3 1 -0.3 높은 손실
0.2 0.8 0 -0.8 낮은 손실
0.8 0.2 0 -0.2 높은 손실

- 예측 확률을 사용해 이런 식으로 계산 하면 연속적인 손실함수를 얻을 수 있을 것이다.

- 여기에 로그 함수를 적용하면 최종적으로 아래와 같은 식이 될 것이다.

1) 양성 클래스(타깃 = 1) 일때 : - log(예측확률)

1) 음성 클래스(타깃 = 0) 일때 : - log(1-예측확률)

 

- 이 예측 확률이 0에서 멀어질수록 손실이 아주 큰 양수가 된다.

- 이 손실 함수를 로지스틱 손실함수 또는 이진 크로스엔트로피 손실함수라고도 부른다,

 

- 다중 분류에서 사용하는 손실함수를 크로스엔트로피 손실함수라고 부른다

- 회귀에서는 평균 절댓값 오차, 평균 제곱오차를 많이 사용한다.

1) 평균 절댓값 오차 : 타깃에서 예측값을 빼 절댓값을 평균 낸 값

2) 평균 제곱오차 : mean squared error,타깃에서 예측값을 빼 제곱한 값을 평균 낸 값

 

3. SGDClassifier

 

- 사이킷런에서 확률적 경사하강법을 제공하는 대표적인 분류용 클래스는 SGDClassifier이다.

from sklearn.linear_model import SGDClassifier
sc = SGDClassifier(loss='log', max_iter=10, random_state=42)
sc.fit(train_scaled, train_target)

print(sc.score(train_scaled, train_target))
>> 0.773109243697479
print(sc.score(test_scaled, test_target))
>> 0.775

 

- SGDClassifier에서는 객체를 만들때 2개의 매개변수를 지정한다.

1) loss : 손실 함수의 종류를 지정하는 변수, log로 지정할지 손실함수로 로지스틱 손실함수를 지정한다는 의미이다.

2) max_iter : 수행할 에포크 횟수를 지정

 

sc.partial_fit(train_scaled, train_target)

print(sc.score(train_scaled, train_target))
>> 0.8151260504201681
print(sc.score(test_scaled, test_target))
>> 0.825

 

- partial_fit 메소드를 사용하면 SGDClassifier 객체를 따로 만들지 않고, 기존 모델에서 1 에포크씩 이어서 훈련할 수 있다.

 

4. 에포크와 과대/과소 적합

 

- 에포크 횟수가 적으면 모델이 훈련세트를 덜 학습해 과소적합이 올 수 있다. 하지만 에포트 횟수가 너무 많으면 훈련 세트에 너무 잘 맞아 과대 적합이 생길 수 있다. 

- 그렇기에 과대적합이 시작하기 전에 훈련을 멈추는게 가장 좋을 것이다. 이 과정을 조기 종료라고 한다.

 

import numpy as np

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

train_score = []
test_score = []

#타깃에 존재하는 값들 종류 파악
classes = np.unique(train_target)

#에포크 횟수별로 점수 기록하기
for _ in range(0, 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)
plt.plot(test_score)
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.show()

 

에포크의 실행 별로 훈련 세트와 테스트 세트의 점수를 비교해보는 그래프를 그린 실습코드를 이용해 어디에서 과소적합과 과대적합이 일어날지를 한번 비교해보도록 하겠다.

 

 

- 그래프를 그려본 결과 데이터가 작아서 잘 드러나지 않지만, 백번째 에포크 이후에는 훈련 세트와 테스트 세트 사이의 점수차이가 더 벌어지는 것을 확인할 수가 있다. 이런 식으로 그래프, 혹은 둘의 차이를 이용해 최적화된 에포크 횟수를 구할 수 있을 것이다.

 

<SGDClassifier의 loss 매개변수>

- loss 매개변수의 기본값은 hinge이다.

- 여기서 hinge는 힌지 손실을 말하며, 서포트 벡터 머신이라고도 불리는 또 다른 머신러닝 알고리즘을 위한 손실함수 이다.

 

<전체 소스 코드>

링크 : https://bit.ly/hg-04-2

반응형