분류 모델

import torch
import torch.nn as nn
import torch.optim as optim
import seaborn as sns
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder

# 디바이스 설정
device = torch .device('cuda' if torch.cuda.is_available() else 'cpu')

# 데이터 가져오기
tips = sns.load_dataset('tips').dropna()

# 특성, 타겟 설정
x = tips[['total_bill', 'tip', 'size']].values
le = LabelEncoder()
y = le.fit_transform(tips['day'])                # 입력값을 입력하면 요일을 맞추겠다..
                                                 # Thur = 3, Fri = 0, sat = 2, sun = 1
                                                 
# 데이터 분할
x_train, x_test, y_train, y_test = train_test_split(
    x, y, test_size=0.2,
    random_state=42
)

# 스케일링
scaler = StandardScaler()
x_trian = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)

# Tensor 변환 
# y값에 대해서만 long값으로 변경 + 언스퀴지도 삭제
x_train_tensor = torch.tensor(x_train, dtype=torch.float32).to(device)
y_train_tensor = torch.tensor(y_train, dtype=torch.long).to(device)
x_test_tensor = torch.tensor(x_test, dtype=torch.float32).to(device)
y_test_tensor = torch.tensor(y_test, dtype=torch.long).to(device)

# 모델 정의
class ClassificationModel(nn.Module):
    def __init__(self):
        super(ClassificationModel, self).__init__()
        self.linear = nn.Linear(3,4)                # 위에 수치예측에선 (2,1)로 정의함 (입력2, 출력1)
                                                    # 여기는 입력변수 3개, 출력값 4개로 설정함
                                                    # 왜?
    def forward(self, x): 
        return self.linear(x)                   # CrossEntropyLoss 활용, softmax 자동 계산됨
        
# 모델 초기화
model = ClassificationModel().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr = 0.01)

# 학습
epochs = 300  # 총 300번 학습을 돌림
for epoch in range(epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(x_train_tensor)
    loss = criterion(outputs, y_train_tensor)
    loss.backward()
    optimizer.step()

    if (epoch+1) % 50 == 0:
        print(f"Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}")
        
# 평가
model.eval()
with torch.no_grad():
    outputs = model(x_test_tensor)
    _, predicted = torch.max(outputs,1)
    correct = (predicted == y_test_tensor).sum().item()
    accuracy = correct / y_test_tensor.size(0)
    print(accuracy)      

image.png

image.png

이론

미니배치

: 전체 데이터 셋을 몇 개의 데이터 셋으로 나누었을 때, 그 작은 데이터 셋 뭉치

ex) 훈련 데이터 1000개를 10개의 미니 배치로 나누어 학습하는 경우, 배치 사이즈는 100

→ 데이터의 양이 굉장히 많은 경우 해당 데이터를 전부 사용하는 것이 아닌 데이터의 일부를 무작위로 추려 근사치로 사용할 수 있음. 이 일부가 되는 데이터가 미니배치

옵티마이저

: 손실함수의 최소값을 찾는 알고리즘

손실함수 loss func

: 얼마나 틀리는지 (loss)를 알게 하는 함수

image.png

  1. 입력 값 x 입력

  2. 예측 y`과 타깃 y값 세팅

  3. 손실 함수 적용

  4. 옵티마이저를 통해 최소값 알아냄 → 이를 통해 가중치 업데이트

  5. 1~5 반복

  6. 현재 가중치: b

  7. 입력 넣고 예측값 계산: y^

  8. 타깃 y와 비교 → 손실함수 적용 → 손실값 a

  9. 손실값에 대해 미분 → 기울기 계산

  10. 옵티마이저가 기울기와 학습률을 사용해

    → 새로운 가중치 bnew

  11. b=bnew ← 덮어씌움

  12. 반복

가중치 = b 예측값 = y

타겟 = y 손실함수 결과값 = a 옵티마이저 결과 값 = b (가중치 b 덮어 씌운 값)