ML기존 훈련데이터에 이어 계속해서 생겨나는 새로운 데이터에 대해 지속적으로 훈련하여 업데이트하는 것에 대한 고민
(점진적 학습, 온라인 학습)
경사하강법 시리즈는 최적화를 위한 도구이다. DL(신경망 알고리즘)에서 필수이다.
Stochastic Gradient Descent (SGD; 확률적 경사하강법): train set에서 sample 하나씩 손실함수 경사를 따라 최적 model 찾기
Minibatch Gradient Descent (MGD; 미니배치 경사하강법): 무작위 몇 개 샘플을 선택해서 최적점 찾기. (빈번하게 사용됨)
Batch Gradient Descent(BGD; 배치 경사하강법): 전체 데이터로 바로 최적점 찾기(컴퓨터 자원 무리 우려 有)
Epoch(에포크): train set 한 번 모두 사용하는 과정 (SGD는 일반적으로 수십, 수백 번 이상 수행)
Loss Function(손실함수): SGD가 최적화할 대상. 보통 이미 정의되어있음. (ML 엉터리정도 측정 기준, 소소익선)
엄밀한 정의는 샘플 1개에 대한 손실을 정의한다.
Ex) 이진분류는 로지스틱 회귀(또는 이진 크로스엔트로피), 다중분류는 크로스엔트로피. 회귀는 평균 제곱 오차(MSE)
(!) Cost Function(비용함수) = sum(손실함수) 그런데 보통 같은 의미로 사용하는 경우 多
specises를 taget으로 설정한 data 준비 및 데이터 분할
import pandas as pd
fish = pd.read_csv('https://bit.ly/fish_csv')
fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy()
fish_target = fish['Species'].to_numpy()
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)
(반드시 해야함!) 표준화 전처리 (훈련세트 기준으로 테스트도 변환!; 평균 및 표준편차로..)
from sklearn.preprocessing import StandardScaler
ss = StandardScaler() # 객체화
ss.fit(train_input) # 학습(train 기준)
train_scaled = ss.transform(train_input) #변환
test_scaled = ss.transform(test_input)
SGD classifier 적용하기 (미니배치나 배치하강법 적용 불가. 확률적 경사하강법만 적용됨)
from sklearn.linear_model import SGDClassifier
sc = SGDClassifier(loss='log', max_iter=10, random_state=42) # 객체화
# loss: 손실함수 설정. 'log': 로지스틱 손실함수(이진분류), max_tier: 반복횟수
sc.fit(train_scaled, train_target) # 훈련
print(sc.score(train_scaled, train_target)) # 정확도 검증
print(sc.score(test_scaled, test_target))
0.773109243697479
0.775
-> 정확도가 낮은 이유는 반복횟수 부족때문으로 추정; Convergence warning 경고 뜸 (반복횟수 부족하다는 알림)
실전에서는 보통 이에 따라 값을 늘려줘서 다시 적용한다.
점진적 학습(추가학습)이 가능한 SGD: partial_fit()
그냥 fit()쓰면 이전에 쓴 것은 다 버리고 다시 하는 것을 의미한다.
sc.partial_fit(train_scaled, train_target) #SGD는 이 set sample 하나하나씩 꺼내서 수행한다.
# 여기서 이 partial_fit은 epoch 한 번 더 실행한 꼴이다.
print(sc.score(train_scaled, train_target))
print(sc.score(test_scaled, test_target))
0.8151260504201681
0.85 -> 1 epoch 수행 결과로 정확도가 향상되었다. 그러면 어느 정도까지 반복해야 할까?
Overfitting직전에 훈련을 멈추는 Early stopping(조기 종료) 지점을 epoch 횟수 그래프로 찾아보자
import numpy as np
sc = SGDClassifier(loss='log', random_state=42)
train_score = []
test_score = []
classes = np.unique(train_target) # 7개 생선 목록
for _ in range(0, 300): # 300번 반복. '_' 변수는 단순 반복하고 버리는 용도로 사용됨
sc.partial_fit(train_scaled, train_target, classes=classes)
# partial_fit 사용시 기준점이 되는 정보 classes를 입력해주는 것이 좋다. 그냥 fit은 생락 可
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.legend(['Train score', 'Test score'], loc='best')
plt.show()
100 epoch(max_iter=100)으로 맞추고 다시 훈련을 시도해보자,
tol: SGDClassifier가 epoch 반복에 따른 성능이 향상되지 않으면 자동으로 멈출지 여부. None 입력시 자동멈춤 비활성화
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
SGDClassfier의 default loss function은 'hinge'이다. hinge는 support vector machine ML알고리즘을 위한 함수이다.
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))
0.9495798319327731
0.925
default함수를 사용한 결과이다. (참고용)
회귀모형의 경우 SGDRegressor를 사용하며 사용방법은 동일하다.
'Programming > Python' 카테고리의 다른 글
ETL (Extract, Transform, Load) with command-line tools (1) | 2024.01.03 |
---|---|
[DL] over(under)fitting 최적, Dropout, Callback (0) | 2023.09.20 |
[ML] Logistic regression (0) | 2023.09.15 |
[DL] tensorflow, Deep Neural Network(DNN) (0) | 2023.09.15 |
[Numpy] Linear algebra package (0) | 2023.09.13 |