Stochastic Gradient Descent¶
앞서 훈련한 모델을 버리지 않고 새로운 데이터에 대해서만 조금씩 더 훈련하는 방식을 점진적 학습이라고 한다.
- 점진적 학습의 대표적인 알고리즘이 확률적 경사 하강법(Stochastic Gradient Descent, SGD)이다.
- SGD는 전체 샘플을 사용하지 않고 딱 하나의 샘플을 훈련 세트에서 랜덤하게 골라 Loss function을 가장 빠르게 줄이는 방법을 찾는다.
- 이런 방식으로 훈련 세트를 한 번 모두 사용하는 과정을 epoch라고 한다. 일반적으로 경사 하강법은 수십, 수백 번의 epoch를 사용한다.
- mini-batch gradient descent는 딱 하나가 아니라 여러 개의 샘플을 사용해 경사 하강법을 수행하는 것을 뜻한다.
- batch gradient descent는 모든 샘플을 사용하여 경사 하강법을 수행하는 것을 뜻한다. 가장 정확하지만 컴퓨터 자원이 많이 필요하다.
- 참고로 후에 나올 신경망 모델의 대부분이 SGD나 mini-batch GD를 사용한다.
손실 함수는 어떤 문제에 대해 머신러닝 알고리즘이 얼마나 엉터리인지 나타내는 지표이다.
- 분류에서 손실은 정답을 맞추지 못하는 것이다.
- 정확도는 손실 함수가 될 수 없다. 연속적이지 않기 때문이다.
- 연속적인 손실 함수를 만들기 위해 로지스틱 손실 함수를 채택할 수 있다. 앞서 배운 로지스틱 회귀 모델을 이용한 분류에서 예측은 0 또는 1이지만 확률은 0~1 사이 어떤 값도 될 수 있었다. 즉, 연속적이다.
- 로지스틱 손실 함수는 이진 크로스엔트로피 손실 함수라고도 하며, 정답(t)과 예측값(y)에 대해 Loss=-(t*log y + (1-t)log(1-y)) 의 관계를 갖는다.
- 다중 분류에 대해서는 크로스엔프로피 손실 함수를 사용한다.
SGDClassifer¶
In [1]:
import pandas as pd
fish = pd.read_csv('https://bit.ly/fish_csv_data')
In [2]:
# Species 데이터를 제외한 나머지 데이터를 input 값으로 사용
fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy()
fish_target = fish['Species'].to_numpy()
In [3]:
from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(
fish_input, fish_target, random_state=42)
In [4]:
# 훈련 세트와 테스트 세트의 특성을 표준화 전처리
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_input)
train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)
In [5]:
from sklearn.linear_model import SGDClassifier
In [6]:
sc = SGDClassifier(loss='log', max_iter=10, random_state=42)
sc.fit(train_scaled, train_target)
print(sc.score(train_scaled, train_target))
print(sc.score(test_scaled, test_target))
iteration이 낮아서 정확도가 낮게 나왔다.
In [7]:
sc.partial_fit(train_scaled, train_target)
print(sc.score(train_scaled, train_target))
print(sc.score(test_scaled, test_target))
- 모델을 이어서 학습할 때는 partial_fit() 메서드를 사용한다.
- 아직 점수가 낮지만 epoch를 한 번 더 실행하니 정확도가 조금 높아졌다.
- 그럼 얼마나 많은 epoch를 수행해야 할까?
- epoch가 너무 적으면 과소적합할 수 있고, 너무 많으면 과대적합할 수 있다.
- 과대적합이 시작하기 전에 훈련을 멈추는 것을 조기 종료(early stopping)이라고 한다.
In [8]:
import numpy as np
sc = SGDClassifier(loss='log', random_state=42)
train_score = []
test_score = []
classes = np.unique(train_target)
In [9]:
for _ in range(0, 300): #300 epoch동안 훈련 진행, _는 나중에 사용하지 않고 버리는 값을 넣어두는 용도로 사용함
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))
In [10]:
import matplotlib.pyplot as plt
plt.plot(train_score)
plt.plot(test_score)
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.show()
- 파란색이 훈련 세트, 주황색이 테스트 세트에 대한 결과이다.
- 초반에는 과소적합의 위험이 있고, 후반에는 두 데이터 셋의 스코어 사이 간격이 커진다
- 따라서 100 epoch 정도가 적당해보인다.
In [11]:
sc = SGDClassifier(loss='log', max_iter=100, tol=None, random_state=42)
sc.fit(train_scaled, train_target)
print(sc.score(train_scaled, train_target))
print(sc.score(test_scaled, test_target))
- tol 매개변수는 반복을 멈출 조건을 뜻한다. n_iter_no_change 매개변수에서 지정한 에포크 동안 손실이 tol만큼 줄어들지 않으면 알고리즘이 중단된다.
- 참고적으로, SGD의 loss function의 default값은 hinge이다.
- 힌지 손실은 서포트 벡터 머신(SVM)이라는 알고리즘을 위한 손실 함수이다.
- 여러 종류의 손실 함수를 loss에 지정하여 사용할 수 있다.
- 아래는 default값을 적용한 경우이다.
In [12]:
sc = SGDClassifier(loss='hinge', max_iter=100, tol=None, random_state=42)
sc.fit(train_scaled, train_target)
print(sc.score(train_scaled, train_target))
print(sc.score(test_scaled, test_target))
In [1]:
from IPython.core.display import display, HTML
display(HTML("<style>.container { width:90% !important; }</style>"))
'혼자 공부하는 머신러닝 + 딥러닝' 카테고리의 다른 글
[혼공머신] 10. Cross Validation & Grid Search (0) | 2021.12.18 |
---|---|
[혼공머신] 9. Decision Tree (0) | 2021.12.18 |
[혼공머신] 7. Logistic Regression (0) | 2021.12.17 |
[혼공머신] 6. Feature Engineering & Regularization (0) | 2021.12.17 |
[혼공머신] 5. Linear Regression (0) | 2021.12.17 |