728x90
반응형
1. Optimizer 란?
- 먼저 우리가 만든 모델에 Training Data가 들어가면 Output 값이 나옵니다.
- 우리는 그 Output값이 목표로 하는 타겟값과 가까워지도록 Error Function ( = loss function)을 설정하고 Error 값이 줄어드는 방향으로 학습시키기 위해 각 Weight와 갖는 Gradient값을 계산합니다.
- 이를 활용해 weight들을 다시 설정합니다.
- 1~3 과정을 반복(Epoch)하며 최적의 Weight를 갖는 모델을 찾아냅니다.
→ 여기서 2~4 과정을 Optimization 과정, 즉 최적화 과정이라 합니다.
2. 경사 하강법 (Gradient Desent)
개념
전체 데이터셋을 사용하여 손실 함수의 기울기(gradient)를 계산한 후,
그 기울기를 따라 모델의 가중치를 업데이트 한다.
특징
- 데이터 사용 - 전체 데이터셋을 한 번에 사용하여 기울기를 계산
- 업데이트 빈도 - 가중치 업데이트는 한 에포크(epoch)에 한 번만 발생
- 수렴 -수렴이 비교적 안정적이며, 특정 방향으로 일관되게 수렴하는 경향이 있음
장점
- 최적화 과정이 덜 불안정하고, 종종 더 낮은 비용 함수 값으로 수렴
단점
- 계산 비용이 높음 - 전체 데이터셋을 사용하기 때문에 계산 비용이 크다.
- 느린 수렴 속도 - 가중치 업데이트가 전체 데이터셋에 대해 계산된 후에만 이루어지므로, 수렴 속도가 느릴 수 있다.
3. 확률적 경사 하강법 (Stochastic Gradient Desent)
개념
전체 데이터셋 중에서 임의로 선택된 하나의 샘플(데이터 포인트)을 사용하여 기울기를 계산하고,
그 기울기를 따라 가중치를 업데이트 한다.
특징
- 데이터 사용 - 매 반복마다 하나의 데이터 샘플을 사용하여 기울기를 계산
- 업데이트 빈도 - 각 샘플마다 가중치가 업데이트 된다.
- 수렴 - 더 빠르게 수렴할 수 있지만, 수렴 과정이 불안정할 수 있습니다(진동 발생 가능).
장점
- 빠른 업데이트 - 빠른 반복과 빠른 수렴이 가능하다.
- 메모리 효율성 - 전체 데이터셋을 로드할 필요 없이, 한 번에 하나의 샘플만을 사용하므로 메모리 사용량이 적다.
단점
- 수렴의 불안정성 - 진동과 불안정한 수렴이 발생할 수 있습니다. 학습률(learning rate)을 신중하게 조절해야 한다
- 최적점 근처에서의 오차 - 가중치가 계속 진동하며 최적점 근처에서 멈추지 않고 약간의 오차가 남을 수 있다.
4. 미니 배치 경사 하강법 (Mine-Batch Gradient Desent)
개념
전체 데이터셋을 여러 개의 작은 배치(mini-batch)로 나누고,
각 배치를 사용하여 기울기를 계산한 후 가중치를 업데이트합니다.
특징
- 데이터 사용 - 한 번에 여러 샘플(배치)을 사용하여 기울기를 계산한다.
- 업데이트 빈도 - 각 미니 배치마다 가중치가 업데이트 된다.
- 수렴 - SGD보다 안정적이며, GD보다 더 빠르게 수렴할 수 있다.
장점
- 계산 효율성 - 병렬 처리를 통해 계산 속도를 높일 수 있으며, 메모리 사용량도 상대적으로 적다.
- 균형 잡힌 수렴 - GD의 안정성과 SGD의 빠른 수렴 속도의 장점을 모두 가지고 있다.
단점
- 최적의 배치 크기 설정 필요 - 배치 크기가 너무 크면 GD처럼 느려지고, 너무 작으면 SGD처럼 불안정해질 수 있다.
- 복잡한 조정 - 최적의 성능을 위해 배치 크기와 학습률을 신중하게 조정해야 한다.
요약
경사하강법(GD)
전체 데이터셋을 사용하여 안정적이지만 느린 최적화를 수행 한다.
확률적 경사하강법(SGD)
각 샘플마다 빠르게 최적화를 수행하지만, 수렴 과정이 불안정할 수 있다
미니 배치 경사하강법(MBGD)
미니 배치를 사용하여 GD와 SGD의 장점을 결합한 방법으로, 계산 효율성과 수렴 안정성을 모두 제공 한다.
5. Optimizer 코드 비교
# %%
import pandas as pd
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.impute import SimpleImputer
from torch.utils.data import DataLoader, TensorDataset
# 1. 데이터 불러오기
df = pd.read_csv("C:/Users/Daehwan/Documents/naver_AI/06_binary/dataset/Titanic-Dataset.csv")
# 데이터 전처리
# 필요한 열 선택 및 결측치 처리
df = df[['Pclass', 'Age', 'Sex', 'Survived']]
df['Age'].fillna(df['Age'].median(), inplace=True) # 결측치 처리
df['Sex'] = df['Sex'].map({'male': 0, 'female': 1}) # 성별 인코딩
# 특성과 타겟 변수 분리
X = df[['Pclass', 'Age', 'Sex']].values
y = df['Survived'].values
# 데이터 표준화
scaler_x = StandardScaler()
X_scaled = scaler_x.fit_transform(X)
# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.2, random_state=42)
# %%
# 2. 모델 정의
class LogisticRegressionModel(nn.Module):
def __init__(self, input_dim):
super(LogisticRegressionModel, self).__init__()
self.linear = nn.Linear(input_dim, 1) # 이진 분류를 위한 1개의 출력 노드
def forward(self, x):
return torch.sigmoid(self.linear(x))
# %%
# 3. 경사하강법 (GD)
def train_gd(model, criterion, optimizer, X_train_tensor, y_train_tensor, epochs=100):
for epoch in range(epochs):
model.train()
optimizer.zero_grad()
outputs = model(X_train_tensor).squeeze()
loss = criterion(outputs, y_train_tensor.float())
loss.backward()
optimizer.step()
return model
# 데이터 준비
X_train_tensor = torch.tensor(X_train, dtype=torch.float32)
y_train_tensor = torch.tensor(y_train, dtype=torch.long)
# 모델, 손실 함수, 옵티마이저
model_gd = LogisticRegressionModel(X_train.shape[1])
criterion = nn.BCELoss() # 이진 분류에 적합한 손실 함수
optimizer = optim.SGD(model_gd.parameters(), lr=0.01)
# 학습
model_gd = train_gd(model_gd, criterion, optimizer, X_train_tensor, y_train_tensor, epochs=100)
# %%
# 4. 확률적 경사하강법
def train_sgd(model, criterion, optimizer, X_train_tensor, y_train_tensor, epochs=100):
for epoch in range(epochs):
for i in range(len(X_train_tensor)):
model.train()
optimizer.zero_grad()
output = model(X_train_tensor[i].unsqueeze(0)).squeeze()
loss = criterion(output, y_train_tensor[i].float())
loss.backward()
optimizer.step()
return model
# 모델, 손실 함수, 옵티마이저
model_sgd = LogisticRegressionModel(X_train.shape[1])
criterion = nn.BCELoss()
optimizer = optim.SGD(model_sgd.parameters(), lr=0.01)
# 학습
model_sgd = train_sgd(model_sgd, criterion, optimizer, X_train_tensor, y_train_tensor, epochs=100)
# %%
# 5. 미니 배치 경사 하강법
def train_mbgd(model, criterion, optimizer, dataloader, epochs=100):
for epoch in range(epochs):
for batch_X, batch_y in dataloader:
model.train()
optimizer.zero_grad()
outputs = model(batch_X).squeeze()
loss = criterion(outputs, batch_y.float())
loss.backward()
optimizer.step()
return model
# 데이터 준비
batch_size = 32
dataset = TensorDataset(X_train_tensor, y_train_tensor)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
# 모델, 손실 함수, 옵티마이저
model_mbgd = LogisticRegressionModel(X_train.shape[1])
criterion = nn.BCELoss()
optimizer = optim.SGD(model_mbgd.parameters(), lr=0.01)
# 학습
model_mbgd = train_mbgd(model_mbgd, criterion, optimizer, dataloader, epochs=100)
# %%
# 6. 성능평가
def evaluate_model(model, X_test_tensor, y_test_tensor):
model.eval()
with torch.no_grad():
outputs = model(X_test_tensor).squeeze()
predicted = (outputs > 0.5).long()
correct = (predicted == y_test_tensor).sum().item()
accuracy = correct / len(y_test_tensor)
return accuracy
# 데이터 준비
X_test_tensor = torch.tensor(X_test, dtype=torch.float32)
y_test_tensor = torch.tensor(y_test, dtype=torch.long)
# 평가
gd_accuracy = evaluate_model(model_gd, X_test_tensor, y_test_tensor)
sgd_accuracy = evaluate_model(model_sgd, X_test_tensor, y_test_tensor)
mbgd_accuracy = evaluate_model(model_mbgd, X_test_tensor, y_test_tensor)
print(f'GD 모델 정확도: {gd_accuracy * 100:.2f}%')
print(f'SGD 모델 정확도: {sgd_accuracy * 100:.2f}%')
print(f'MBGD 모델 정확도: {mbgd_accuracy * 100:.2f}%')
# %%
728x90
반응형
'AI Naver boost camp > [Week 01] Pytorch' 카테고리의 다른 글
선형 회귀 (Linear Regression) _ 2 - 경사하강법, 데이터 표준화 (0) | 2024.08.08 |
---|---|
선형 회귀 (Linear Regression) _ 1 - 상관관계, pytorch 모델 코드, loss funtion (0) | 2024.08.08 |
Day - 04 (0) | 2024.08.08 |
Tensor 노름 (0) | 2024.08.07 |
Tensor 생성과 조작 (0) | 2024.08.06 |
댓글