본문 바로가기
AI Naver boost camp/[Week 01] Pytorch

경사하강법(GD) vs 확률적경사하강법(SGD) vs 미니 배치 경사하강법(MBGD)

by AI-BT 2024. 8. 10.
728x90
반응형

1. Optimizer 란?

  1. 먼저 우리가 만든 모델에 Training Data가 들어가면 Output 값이 나옵니다.
  2. 우리는 그 Output값이 목표로 하는 타겟값과 가까워지도록 Error Function ( = loss function)을 설정하고 Error 값이 줄어드는 방향으로 학습시키기 위해 각 Weight와 갖는 Gradient값을 계산합니다.
  3. 이를 활용해 weight들을 다시 설정합니다.
  4. 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
반응형

댓글