-
[혼공머] 4-2. 확률적 경사 하강법Data Science/딥러닝 & 머신러닝 2025. 1. 11. 00:00
1. 점진적인 학습
1. 새로운 문제
- 새로운 생선이 도착하는 대로 즉시 훈련 데이터를 제공할 수 있을까?
- sol 1. 기존의 훈련 데이터에 새로운 데이터를 추가해 매일 다시 훈련
- 단점 : 시간이 지날수록 데이터가 늘어나서 지속 가능 X
- sol 2. 새로운 데이터를 추가할 때 이전 데이터를 버려서 훈련 데이터 크기 유지
- 단점 : 데이터셋의 크기 유지, 중요한 생선 데이털르 버리면 문제 발생
- sol3. ‘점진적 학습’
- 훈련한 모델을 버리지 않고 새로운 데이터에 대해 조금씩 더 훈련
- 데이터 모두 유지할 필요도 없고 생선을 까먹지도 않을 것
- 대표적으로, 확률적 경사 하강법 알고리즘을 사용한다.
2. 경사 하강법
1. 경사 하강법
- 말의 뜻 : 경사를 따라 내려가는 방법 → 가장 빠른 방법은 경사가 가파른 길
- 경사 = 기울기
- 하강법 = 내려가는 방법
- 경사 하강법의 목표 : 가장 가파른 경사를 따라 원하는 지점에 도달
- 한 번에 많이 움직이면, 오히려 올라갈 수도 있다.
- 가장 가파른 길을 찾아 내려오지만, 조금씩 내려와야 한다.
2. 경사 하강법의 종류
- 확률적 경사 하강법 : one sample
- 미니배치 경사 하강법 : many sample
- 배치 경사 하강법 : all sample
3. 확률적 경사 하강법
- 확률적 = 무작위하게
- 목표 : 훈련 세트에서 랜덤하게 하나의 샘플을 골라, 가장 가파른 길을 찾는 것
- 과정
- 전체 샘플을 모두 사용할 때까지 1개 골라서 내려간다.
- 그 다음 훈련 세트에서 또 다른 샘플 1개 선택해서 내려가는 방식
- 샘플을 다 사용했는데도 아직 산에 있다면 다시 처음부터 시작
- = 훈련 세트에 모든 샘플을 다시 채워넣고, 확률적 경사 하강법 진행
- 여러 번의 ‘에포크’ 수행
- 에포크 = 확률적 경사 하강법에서 훈련 세트를 한 번 모두 사용하는 과정
- 신경망 알고리즘에서 주로 사용 : 한 번에 모든 데이터를 사용하기 어렵기 때문
4. 미니배치 경사 하강법
- 무작위로 샘플을 내려가는 확률적 경사 하강법이 걱정되는 경우 사용
- 무작위로 여러 개의 샘플을 사용해 경사 하강법을 수행하는 방식
5. 배치 경사 하강법
- 전체 샘플을 사용해 경사 하강법을 수행하는 방식
- 1번의 경사로를 따라 이동
- 가장 안정적인 방식이지만 컴퓨터 자원을 너무 많이 사용
3. 손실 함수
1. 손실 함수
- 정의 : 머신러닝 알고리즘이 별로인 정도(?)를 측정하는 기준
- 작을수록 좋다.
- 비용 함수와 손실 함수의 차이
- 비용 함수 : 훈련 세트에 있는 모든 샘플에 대한 손실 함수의 합
- 손실 함수 : 샘플 하나에 대한 손실을 정의
2. 손실 함수가 연속적이어야 하는 이유
- 분류에서의 손실 = 정답을 못 맞히는 것정확도를 손실 함수로 사용한다면 정확도가 이산적이라는 문제 발생따라서 연속적 = 미분 가능 해야 한다.
- 정확도가 이산적 → 경사 하강법을 이용해 움직일 수 없다.
3. 손실 함수의 종류
- 로지스틱 손실 함수 (이진 크로스엔트로피 손실 함수)
- 크리스엔트로피 손실 함수
- MSE : 회귀에서 사용하는 손실 함수 ; 평균 제곱 오차
앞으로 사용할 예시에서는
샘플 4개의 예측 확률을 각각 0.9, 0.3, 0.2, 0.8 이라고 하자.
샘플 4개의 타겟 값은 각각 1, 1, 0, 0 이다.
4. 로지스틱 손실 함수
- 이진 분류에서의 손실 함수
- 구하는 방법
- ‘양성 클래스[1]’ 일 확률과 1을 곱한 후 음수를 취한다.예측이 1에 가까울수록 좋은 모델이다.따라서 양성 클래스에 대한 예측으로 바꾸어 손실을 구한다.
- 0.2의 예측은 타겟이 0이 되므로, 곱하면 0이 되는 문제가 있다.
- 예측 확률에 로그 함수를 적용한다.로그 함수는 0에 가까울수록 아주 큰 음수가 된다.
- 음수의 로그함수는 양수가 되고 손실이 양수면 이해하기 쉽다.
5. 크로스엔트로피 손실 함수
- 다중 분류에서 사용하는 손실 함수
4. SGDClassifier
1. SGDClassifier 모델
- 확률적 경사 하강법을 제공하는 분류용 클래스
- 객체 생성 시 지정해야 하는 매개변수 2가지
- loss : 손실 함수의 종류
- ‘hinge’ = 서포트 벡터 머신을 위한 손실 함수 (기본값)
- ‘log_loss’ = 로지스틱 손실 함수
- max_iter : 수행할 에포크 횟수 ( 전체 훈련 세트 반복 횟수)
- loss : 손실 함수의 종류
- 점진적 학습 가능 → partial_fit() 으로 모델 이어서 훈련
- 호출할 때마다 1 애포크씩 이어서 훈련
- 일정 에포크 동안 성능이 향상되지 않으면 자동으로 멈춘다.
- tol 매개변수로 향상될 최솟값 지정 가능
2. 데이터 준비
fish = pd.read_csv('<https://bit.ly/fish_csv_data>')
3. 훈련 데이터와 타겟 데이터 분리
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)
4. 데이터 전처리
- 훈련 세트와 테스트 세트의 특성을 표준화 전처리
- 훈련 세트에서 학습한 통계 값으로 테스트 세트도 변환
from sklearn.preprocessing import StandardScaler ss = StandardScaler() ss.fit(train_input) train_scaled = ss.transform(train_input) test_scaled = ss.transform(test_input)
5. SGDClassifier 모델
# 훈련 sc = SGDClassifier(loss='log_loss', max_iter=10, random_state=42) sc.fit(train_scaled, train_target) # 정확도 sc.score(train_scaled, train_target), sc.score(test_scaled, test_target) # (0.773109243697479, 0.775) # 이어서 훈련 sc.partial_fit(train_scaled, train_target) sc.score(train_scaled, train_target), sc.score(test_scaled, test_target) # (0.9663865546218487, 0.925)
6. 힌지 손실을 이용한 SGDClassifier 모델
sc = SGDClassifier(loss='hinge', max_iter=100, tol = None, random_state=42) sc.fit(train_scaled, train_target) sc.score(train_scaled, train_target), sc.score(test_scaled, test_target) # (0.9495798319327731, 0.925)
5. 에포크와 과대/과소적합
1. 확률적 경사 하강법에서의 과대/과소적합
- 에포크 횟수가 적으면 모델이 훈련 세트 덜 학습
- = 훈련 세트와 테스트 세트에 잘 맞지 않는 과소적합된 모델
- 에포크 횟수가 많으면 훈련 세트에 아주 잘 맞는 모델
- = 훈련 세트에 너무 잘 맞아 테스트 세트에서는 점수가 낮은 과대적합된 모델
- 에포크 횟수에 따른 변화
- 어느 순간부터 테스트 세트 점수 감소
- 이 시점이 과대적합의 시작점
- 어느 순간부터 테스트 세트 점수 감소
2. 조기 종료
- 과대적합이 시작되기 전 훈련을 멈추는 것
- partial_fit을 이용해 에포크에 따른 정확도 나타내기
- 에포크마다 훈련 세트와 테스트 세트에 대한 점수 기록
import numpy as np sc = SGDClassifier(loss='log_loss', max_iter=100, tol=None, random_state=42) train_score = [] test_score = [] classes = np.unique(train_target)
- 300번의 에포크 동안 partial_fit
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))
- 300번의 에포크 동안 기록한 점수 그래프로 표시
import matplotlib.pyplot as plt plt.plot(train_score) # blue plt.plot(test_score) # orange plt.xlabel('epoch') plt.ylabel('accuracy') plt.show()
- 100 번째 에포크 이후 점수가 벌어진다 → 100번이 적당한 반복 횟수
sc = SGDClassifier(loss = 'log_loss', max_iter = 100, tol = None, random_state = 42) sc.fit(train_scaled, train_target) print(sc.score(train_scaled, train_target)) # 0.95 print(sc.score(test_scaled, test_target)) # 0.92
- 100번의 에포크 동안 모델 훈련
6. 점진적 학습을 위한 확률적 경사 하강법 전체 소스 코드
# 데이터 준비 import pandas as pd import numpy as np fish = pd.read_csv('<https://bit.ly/fish_csv_data>') 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_scaled = ss.transform(train_input) test_scaled = ss.transform(test_input) # SGDClassifier - 힌지 손실함수 sc = SGDClassifier(loss='hinge', max_iter=100, tol = None, random_state=42) sc.fit(train_scaled, train_target) sc.score(train_scaled, train_target), sc.score(test_scaled, test_target) # SGDClassifier - 로지스틱 손실함수 from sklearn.linear_model import SGDClassifier sc = SGDClassifier(loss='log', max_iter=10, random_state=42) sc.fit(train_scaled, train_target) sc.score(train_scaled, train_target), sc.score(test_scaled, test_target) # 점진적 학습 sc.partial_fit(train_scaled, train_target) # 에포크와 과대/과소적합 # 1. 정확도 기록 import numpy as np 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) # partial _fit 위해 classes train_score.append(sc.score(train_scaled, train_target)) test_score.append(sc.score(test_scaled, test_target)) # 2. 정확도 그래프 import matplotlib.pyplot as plt plt.plot(train_score) plt.plot(test_score) plt.xlabel('epoch') plt.ylabel('accuracy') # 3. 더 좋은 에포크로 재훈련 sc = SGDClassifier(loss='log', max_iter=100, tol=None, random_state=42) sc.fit(train_scaled, train_target) sc.score(train_scaled, train_target), sc.score(test_scaled, test_target)
'Data Science > 딥러닝 & 머신러닝' 카테고리의 다른 글
[혼공머] 5-1. 결정 트리 (0) 2025.01.12 [혼공머] 4-1. 로지스틱 회귀 (0) 2025.01.10 [혼공머] 3-3. 특성 공학과 규제 (0) 2025.01.10 [혼공머] 3-2. 선형 회귀 (0) 2025.01.10 [혼공머] 3-1. K-최근접 이웃 회귀 (0) 2025.01.10