08_ML(Machine_Learning)

18_확률적 경사 하강법

chuu_travel 2025. 4. 9. 17:28
728x90
확률적 경사 하강법(Stochastic Gradient Descent)

 

 

● 의의

        ■ 훈련 세트에서 샘플을 하나씩 꺼내 손실함수의 경사를 따라 최적의 모델을 찾는 알고리즘

        ■ 샘플을 하나씩 사용하지 않고 여러 개를 사용하면 미니배치 경사하강법

        ■ 한 번에 전체 샘플을 사용하면 배치 경사하강법

 

 

● 손실 함수(loss function)

        ■ 확률적 경사하강법의 최적화할 대상

        ■ 어떤 문제에서 머신러닝 알고리즘이 얼마나 실제 값과 오차가 나는지 측정하는 기준

        ■ 손실 함수의 최솟값을 알 수 없기 때문에 조금씩 찾아나가는 과정이 확률적 경사하강법

 

 

● 에포크(epoch)

        ■ 손실 함수 값을 줄여나가는 과정에서 훈련 세트를 모두 사용하고도 만족할만한 결과에 도달하지 못했다면 다시 처음부터 훈련 세트를 사용함

        ■ 이렇게 훈련 세트를 한 번 모두 사용하는 과정을 에포크라고 부름

        ■ 일반적으로 수십 번에서 수백 번 이상 에포크를 수행함

 

 

● 특징

        ■ 샘플 데이터셋에 대해서만 경사를 계산하기 때문에 다루는 데이터가 줄어서 학습 속도가 빠르고 메모리 소모량이 작으며, 큰 데이터셋도 학습이 가능함 

        ■ 학습 과정에 진폭이 크고 배치 경사하강법보다 불안정하게 움직임

 

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import SGDClassifier
from sklearn.preprocessing import StandardScaler
import numpy as np
import matplotlib.pyplot as plt

 

df = pd.read_csv("./data/Fish.csv")

 

df.head()

 

x = df.drop(["Species", "Length1"], axis = 1)
y = df["Species"]
x_train, x_test, y_train, y_test = train_test_split(x, y, stratify = y, test_size = 0.25, random_state = 26)

 

# 스탠다드 스케일링 적용
ss = StandardScaler()
scaled_train = ss.fit_transform(x_train)
scaled_test = ss.transform(x_test)
sgd = SGDClassifier(loss = "log_loss", max_iter = 10, random_state = 26) # <- 테스트 데이터 분할 할 때의 random state와 맞출 필요는 없음
# log_loss: 로지스틱 회귀와 마찬가지로 맞추겠다 
# max_iter: 수행할 최대 에포크 횟수(최대에 도달하지 않고 끝날 수 도 있음) <- 보통은 기재하지 않음

 

● SGDClassifier의 매개변수

        ■ loss: 손실 함수의 종류를 지정

                ○ log_loss: 로지스틱 손실 함수

        ■ max_iter: 수행할 최대 에포크 횟수

 

sgd.fit(scaled_train, y_train)
print(sgd.score(scaled_train, y_train))
print(sgd.score(scaled_test, y_test))
0.7058823529411765
0.625
C:\ProgramData\anaconda3\Lib\site-packages\sklearn\linear_model\_stochastic_gradient.py:744: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
  warnings.warn(

 

● ConvergenceWarning: 모델이 충분히 수렴하지 않았음을 알리는 경고

 

● 확률적 경사하강법은 점진적 학습이 가능함

        ■ SGDClassifier 객체를 다시 만들지 않고 기존 모델을 추가로 훈련하는 것이 가능함

 

sgd.partial_fit(scaled_train, y_train)
print(sgd.score(scaled_train, y_train))
print(sgd.score(scaled_test, y_test))
0.7647058823529411
0.8

 

 

 

01. 에포크와 과적합

 

● 에포크 횟수가 적으면 모델이 훈련 세트를 덜 학습하고 과소적합이 일어날 수 있음

 

● 에포크 횟수가 많으면 모델이 훈련 세트를 과도하게 학습하고 과대적합이 일어날 수 있음

 

● 훈련 세트 점수는 에포크가 진행될수록 꾸준히 증가하지만 테스트 세트 점수는 어느 순간 감소하기 시작함

        ■ 테스트 세트 점수가 감소하는 지점이 과대적합이 시작되는 지점

        ■ 과대적합이 시작하기 전에 훈련을 멈추는 것을 조기종료(Early Stopping)라고 함

 

sgd = SGDClassifier(loss = "log_loss", random_state = 26)
train_score = []
test_score = []
classes = np.unique(y_train)

 

# 정답값의 고유값들
classes
array(['Bream', 'Parkki', 'Perch', 'Pike', 'Roach', 'Smelt', 'Whitefish'],
      dtype=object)

 

for _ in range(300):
    sgd.partial_fit(scaled_train, y_train, classes = classes)
    train_score.append(sgd.score(scaled_train, y_train))
    test_score.append(sgd.score(scaled_test, y_test))

 

plt.figure()
plt.plot(train_score)
plt.plot(test_score)
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.show()

 

sgd = SGDClassifier(loss = "log_loss", max_iter = 150, tol = None, random_state = 26)
# tol: 최소향상값
sgd.fit(scaled_train, y_train)
print(sgd.score(scaled_train, y_train))
print(sgd.score(scaled_test, y_test))
0.9411764705882353
0.875

 

 

● SGDClassifier는 일정 에포크 동안 성능이 향상되지 않으면 자동으로 훈련을 멈추고 종료함

        ■ tol 매개변수에서 최소 향상값을 지정

        ■ tol이 None이 되면 자동으로 멈추지 않고 max_iter 만큼 반복함

 

sgd_hinge = SGDClassifier(loss = "hinge", max_iter = 150, tol = None, random_state = 26)
sgd_hinge.fit(scaled_train, y_train)
print(sgd_hinge.score(scaled_train, y_train))
print(sgd_hinge.score(scaled_test, y_test))
0.9411764705882353
0.875

 

 

● SGDClassifier의 loss 매개변수의 기본값은 hinge(힌지 손실) 임

 

● 힌지 손실은 support vector machine(서포트 벡터 머신)을 위한 손실 함수

 

● SGDClassifier는 다양한 손실함수를 지원함

728x90