[혼공머신러닝] Ch 4. 다양한 분류 알고리즘(2)
확률적 경사 하강법
확률적 경사 하강법이란 Stochastic Gradient Descent로써, 무작위로 배치 크기가 1인 데이터를 추출하여 기울기를 계산하고 경사 하강 알고리즘을 적용하는 방법을 말합니다. 랜덤하게 하나의 샘플을 택하여 하강 알고리즘을 적용하기 때문에 전체 샘플을 사용하지 않습니다. 이러한 형태로 전체 샘플을 모두 사용할 때 까지 알고리즘을 여러번 적용한다고 생각하면 됩니다.
우선 pandas를 사용하여 데이터를 불러오겠습니다.
#dataframe 생성
import pandas as pd
fish = pd.read_csv('https://bit.ly/fish_csv')
print(fish)
우선 데이터를 불러온 후에 Species 열을 제외한 열들을 입력 데이터로, Species 열을 타깃 데이터롤 설정합니다.
fish_input = fish[['Weight', 'Length', 'Diagonal', 'Height', 'Width']].to_numpy()
fish_target = fish['Species'].to_numpy()
#train set와 test set으로 나누기
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)
fish 데이터를 sklearn을 이용하여 train set와 test set로 나눠줍니다. 그리고 StandardScaler을 사용하여 train set와 test set를 표준화 전처리를 해주도록 하겠습니다.
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_input)
train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)
이제 확률적 경사 하강법을 사용하기 위해 sklearn의 SGDClassifier 클래스를 이용합니다. SGDClassifier 클래스에는 loss 변수에 손실 함수의 종류를 지정해주고, 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
점수가 낮게 나왔기 때문에 점수를 높이기 위해 이어서 훈련하여 점진적인 학습을 해보도록 합니다. 이어서 훈련할 때에는 partial_fit() 메서드를 사용하는데, 사용할 때 마다 1 epoch 씩 이어 훈련할 수 있습니다.
sc.partial_fit(train_scaled, train_target)
print(sc.score(train_scaled, train_target))
print(sc.score(test_scaled, test_target))
0.8151260504201681
0.85
확률적 경사 하강법을 사용한 모델은 에포크의 횟수에 따라 과대적합이나 과소적합 될 수 있기 때문에 에포크 횟수에 따른 훈련세트 점수와 테스트세트 점수를 그래프로 나타내 적절한 에포크의 값을 찾아줘야 합니다.
import numpy as np
sc = SGDClassifier(loss='log', random_state = 42)
train_score = []
test_score = []
classes = np.unique(train_target)
#300번의 epoch동안 훈련 반복 진행
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()
결과인 그래프를 보면 초반에는 과소적합되어 훈련세트와 테스트세트 점수가 낮고, 약 100번째 에포크 이후에는 훈련세트와 테스트 세트의 점수가 벌어지고 있는 것을 볼 수 있습니다. 100번째 에포크가 적절한 값인 것을 확인할 수 있습니다. 반복횟수를 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
최종 점수가 잘 나오는 것을 확인할 수 있습니다.
Comments