3 분 소요

❗ 문제 ❗

한빛 럭키백이 대박이 나서 새로운 수산물을 넣고 싶은데, 이에 대한 확률도 도출을 해야된다. 근데 어느 생선이 먼저 영업팀에 도착할지 모르고, 모든 생선이 올 때까지 기다릴 수도 없다.

💡 해결 방안 💡

  1. 새로운 데이터를 추가하여 모델을 매일매일 훈련시킨다. -> 지속하기 어려운 방안.
  2. 새로운 데이터를 추가할 때 이전 데이터를 버림으로써 훈련 데이터 크기를 일정하게 유지 -> 데이터 유실. 앞으로 모델이 버려진 생선을 예측할 수 없다.
  3. 점진적 학습 : 훈련한 모델을 버리지 않고 새로운 데이터에 대해서만 조금씩 더 훈련하면서 동시에 사용한 데이터 모두 유지하는 학습, 대표적인 예시 -> 확률적 경사 하강법

🔮 확률적 경사 하강법

확률적이란 말은 ‘무작위하게’ 혹은 ‘랜덤하게’의 기술적인 표현이다. 경사는 우리가 아는 경사,,,기울기를 의미. 하강법은 내려가는 방법을 의미. 즉 경사 하강법은 경사를 따라 내려가는 방법을 말한다.

  • 경사 하강법
    가장 가파른 길을 찾아 내려오지만 조금씩 내려오는 것이 중요하다. 내려오는 과정이 경사 하강법 모델을 훈련하는 것이다.
    • 에포크 : 훈련 세트를 한번 모두 사용하는 과정
    • 확률적 경사 하강법
      훈련 세트에서 랜덤하게 하나의 샘플을 선택 하여 가파른 경사를 조금 내려간다. 그 다음 훈련 세트에서 랜덤하게 또 다른 샘플을 하나 선택하여 경사를 조금 내려간다. … 이런식으로 전체 샘플을 모두 사용할 때까지 계속한다.
      if 모든 샘플을 다 썻는데도 도착하지 못하면? 다시 처음부터!!
    • 미니배치 경사 하강법 : 여러 개의 샘플 을 사용해서 경사 하강법을 수행하는 방식
    • 배치 경사 하강법 : 극단적으로 한 번 경사로를 따라 이동하기 위해 전체 샘플을 사용 하는 방식

🔮 손실 함수

어떤 문제에서 머신러닝 알고리즘이 얼마나 엉터리인지를 측정하는 기준이다. 손실 함수의 값이 작을수록 좋은 것이다. 분류에서 손실은 정답을 못 맞히는 것이다. 한 사람이 걷고 있는데, 그 사람이 걸어가는 방향으로 x축을 세팅하고, 높이를 y축으로 세팅하면 손실 정도는 y축과 같다. 즉, 사람이 걸어가다가 낮아진 부분이 손실이 된다. 그래서 손실 함수를 잘 적용시키기 위해서는 이에 맞는 손실을 구해야되고, 보폭이 너무 크게된다면 진짜 최소값의 손실을 알 수 없기 때문에 확률적 경사 하강을 통해서 조금씩 조금씩 이동하며 손실을 구하여 함수를 구하는 것이다.

  • 이진 분류 정답이 1, 오답이 0이라고 했을 때, 예측값과 같은지 다른지(=정확도) 비교를 통해서 손실 정도를 파악할 수 있다. 정확도는 맞힌 개수 / 전체 샘플 개수 로 파악한다. 정확도에 음수값을 붙혀서 손실 함수로 표현할 수 있다. 정확도가 높아서 음수를 붙힌다면 손실이 낮은 값이 될 것이고, 정확도가 낮아서 음수를 붙힌다면 손실이 큰 값이 될 것이다. 이를 이용하여 손실 함수를 만들 수 있다.
    • 로지스틱 손실 함수(or 이진 크로스엔트로피 손실 함수) 로지스틱 회귀를 이용하여서 구한 확률을 이용하여 손실 함수를 그릴 수 있다. 정답 타깃이 1인 경우 -(예측 X 1), 정답 타깃이 0인 경우는 _-{(1-예측) _ 1}* 로 손실값을 확인한다.
      • 양성 클래스(타깃 = 1) -log(예측 확률)
      • 음성 클래스(타깃 = 0) -log(1-예측 확률)
  • 다중 분류
    • 크로스엔트로피 손실 함수 -> 우리가 직접 구현해서 사용할 일은 없으니 이진 분류와 원리가 비슷하다고 이해하자
  • 회귀 평균 제곱의 오차를 정확도이자 손실값으로 쓴다. 분류 모델과는 다르게 회귀의 손실 함수는 작은 값일수록 좋은 모델이다.

🔮 SGDClassifier 분류 모델

  • 사이킷런
    • 모델 클래스
      • 분류 모델
        • KNeighborsClassifier
        • KNeighborsRegressor
        • LogisticRegression
        • SGDClassifier
      • 회귀 모델
        • LinearRegression
        • SGDRegression
    • 변환기 클래스
      • PolynomialFeatures
      • StandardScaler

1️⃣ 데이터 준비하기

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

fish = pd.read_csv('http://bit.ly/fish_csv_data')
fish_input = fish[['Weight', 'Length', 'Diagonal', 'Height', 'Width']].to_numpy()
fish_target = fish['Species'].to_numpy()
train_input, test_input, train_target, test_target = train_test_split(fish_input, fish_target, random_state = 42)
ss = StandardScaler()
ss.fit(train_input)
train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)

2️⃣ 최적의 max_iter 찾기

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))
print(sc.score(test_scaled, test_target))

>>>
0.773109243697479
0.775
  • loss : 기본값은 hinge이다. 힌지 손실은 서포트 벡터 머신이라고 불리는 또 다른 머신러닝 알고리즘을 위한 손실 함수이다. 위에서 log 함수를 사용하여 손실 함수를 만들었기 때문에 손실 함수를 로그로 만든다는 뜻이다.
  • max_iter : 전반적으로 점수가 낮기 때문에 과소적합되었다고 볼 수 있다. 그렇기 때문에 _max_iter* 의 값을 변경시킴으로써 해결할 수 있다. max_iter은 몇 번 반복시키는 것인지를 나타내는 매개변수이다.

  • 🍖 partial_fit 메소드 : 이미 훈련한 모델에 추가적으로 훈련시키고 싶을 때 사용. 즉 점진적인 학습을 위해서 사용이 된다.
import numpy as np
import matplotlib.pyplot as plt

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))

plt.plot(train_score)
plt.plot(test_score)
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.show()

download1

반복문에서 *는 임시값으로 i와 같은 값을 사용할 필요가 없기 때문에 *를 통해서 ㄹㅇ 300번 반복만하는 반복문을 만들 수 있다.
출력값을 보니 max_iter이 약 100일 때가 가장 적절한 값이 나올 것 같다.

🌗 확률적 경사 하강법을 이용한 모델

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))

>>>
0.957983193277311
0.925

손실 함수를 사용하여서 머신러닝 알고리즘의 점수를 메김. 여기서 SGDClassifier은 전달한 훈련 세트에서 샘플들을 하나씩 뽑으면서 경사 하강법 단계를 수행하기 때문에 이 알고리즘은 확률적 경사 하강법 을 사용한 것이고, 여기서 손실 함수를 통해서 알고리즘의 점수를 확인한 것이다.

댓글남기기