Search

Pytorch Workflow with Classification

대분류
인공지능/데이터
소분류
ML/DL 정리 노트
유형
딥 러닝
부유형
Introduction Pytorch
최종 편집 일시
2024/10/27 15:16
생성 일시
2024/10/23 09:17
14 more properties

Pytorch Workflow

import torch from torch import nn # nn contains all of PyTorch's building blocks for neural networks import matplotlib.pyplot as plt plt.ion() # Check PyTorch version > torch.__version__ 2.4.0+cu121
Python
복사

Part 1: 데이터를 숫자로 변환 (Turn data into numbers)

첫 번째 단계는 다양한 형태의 입력 데이터를 모델이 처리할 수 있는 숫자 형태로 변환하는 과정이다.
입력 데이터는 다음과 같은 형태로 들어올 수 있다:
이미지 데이터: 음식 사진, 또는 다른 시각적 정보
텍스트 데이터: 트윗, 뉴스 기사 등의 문장
음성 데이터: 음성 명령, 대화 등
이러한 데이터는 각각 고유한 방식으로 **숫자 데이터(numerical encoding)**로 변환된다.
예를 들어:
이미지의 경우, 픽셀값을 숫자로 표현할 수 있으며, 각 픽셀은 특정한 색상 값을 가진다.
텍스트의 경우, 단어 또는 문장을 벡터화(벡터 임베딩)하여 숫자로 변환한다. 각 단어는 고유한 숫자 벡터로 변환되며, 이는 단어 간 유사성을 반영한다.
음성 데이터는 진폭(amplitude) 값이나 주파수(frequency) 값으로 변환되어 수치 데이터로 표현된다.
그림에서는 이러한 입력 데이터가 숫자 배열(예: [[116, 78, 15], [117, 43, 96], [125, 87, 23]])로 변환되고 있음을 보여준다.
이 단계에서 중요한 것은, 모델이 학습할 수 있도록 모든 입력이 숫자로 인코딩된다는 점이다.

Part 2: 패턴을 학습하는 모델 구축 (Build model to learn patterns in numbers)

두 번째 단계는 딥러닝 모델이 숫자 데이터를 입력받아 패턴을 학습하는 과정이다. 그림의 중앙에는 신경망(neural network) 구조가 보이며, 이 네트워크는 데이터를 처리하고 학습한다.
이 과정에서 모델은 다음과 같은 작업을 수행한다:
표현 학습(representation learning): 입력된 숫자 데이터를 바탕으로 패턴을 찾고, 중요한 특징(feature)을 추출한다. 이는 가중치(weights) 및 매개변수(parameters)를 학습하는 과정을 포함한다.
숫자 간의 관계 학습: 다양한 레이어(layer)를 거치며, 각 데이터가 가지는 의미 있는 패턴을 파악하게 된다. 예를 들어, 음식 사진을 통해 음식의 종류를 학습하거나, 텍스트를 통해 스팸 여부를 판별하는 과정을 학습한다.
그림에서 출력되는 Representation outputs는 모델이 입력 데이터를 바탕으로 학습한 패턴을 바탕으로 숫자 벡터로 출력한 결과이다.
예시로 [(0.983, 0.004, 0.013), (0.110, 0.889, 0.001), (0.023, 0.027, 0.985)] 같은 벡터가 표현된다.

Outputs (최종 출력)

최종적으로 모델은 학습된 패턴을 바탕으로 결과값을 출력한다. 예를 들어:
이미지 데이터의 경우, "라면", "스파게티"와 같은 음식 종류를 분류할 수 있다.
텍스트 데이터의 경우, 스팸 메시지를 분류하여 "스팸 아님(Not Spam)"이라고 판단할 수 있다.
음성 데이터의 경우, "Hey Siri, what’s the weather today?"와 같은 명령을 이해하여 날씨 정보를 제공하는 것처럼, 모델이 적절한 응답을 반환한다.

Neural Network Classification

Binary Classification
Target can be one of two options, e.g. yes or no
Multi class Classification
Target can be one of more than two options
Multi label Classification
Target can be assigned more than one option

Binary Classification

2.모델링 정의

모델 정의

1. 선형 모델

# 1. nn.Module을 상속받는 모델 클래스를 생성한다 class CircleModelV0(nn.Module): def __init__(self): super().__init__() # 2. X와 y의 입력 및 출력 형태를 처리할 수 있는 nn.Linear 레이어 2개를 생성한다 self.layer_1 = nn.Linear(in_features=2, out_features=5) # 입력 특성 2개(X)를 받아 출력 특성 5개를 생성한다 self.layer_2 = nn.Linear(in_features=5, out_features=1) # 입력 특성 5개를 받아 출력 특성 1개(y)를 생성한다 # 3. 순전파 계산을 포함하는 forward 메서드를 정의한다 def forward(self, x): # y와 동일한 형태의 단일 특성을 출력하는 layer_2의 출력을 반환한다 layer_1_out = self.layer_1(x) layer_2_out = self.layer_2(layer_1_out) # layer_1을 거친 출력이 layer_2로 전달되어 계산된다 return layer_2_out
Python
복사

2. 추가 레이어 모델

class CircleModelV1(nn.Module): def __init__(self): super().__init__() self.layer_1 = nn.Linear(in_features=2, out_features=10) self.layer_2 = nn.Linear(in_features=10, out_features=10) # extra layer self.layer_3 = nn.Linear(in_features=10, out_features=1) def forward(self, x): # note: always make sure forward is spelt correctly! # Creating a model like this is the same as below, though below # generally benefits from speedups where possible. # layer1_out = self.layer_1(x) # layer2_out = self.layer_2(layer1_out) # prediction = self.layer_3(layer2_out) # return prediction return self.layer_3(self.layer_2(self.layer_1(x)))
Python
복사

3. 추가 레이어 + 활성함수 모델 (비선형)

# 비선형 활성화 함수를 사용하여 모델을 구축한다 from torch import nn class CircleModelV2(nn.Module): def __init__(self): super().__init__() self.layer_1 = nn.Linear(in_features=2, out_features=10) self.layer_2 = nn.Linear(in_features=10, out_features=10) self.layer_3 = nn.Linear(in_features=10, out_features=1) self.relu = nn.ReLU() # ReLU 활성화 함수를 추가한다 # 모델에 시그모이드를 추가할 수도 있다 # 이는 예측 시 시그모이드를 사용할 필요가 없음을 의미한다 # self.sigmoid = nn.Sigmoid() def forward(self, x): # 레이어 사이에 ReLU 활성화 함수를 삽입한다 out = self.layer_1(x) out = self.relu(out) out = self.layer_2(out) out = self.relu(out) out = self.layer_3(out) return out # return self.layer_3(self.relu(self.layer_2(self.relu(self.layer_1(x)))))
Python
복사

사전 정의

손실 함수(Loss Function) 및 옵티마이저(Optimizer)

# Create a loss function # loss_fn = nn.BCELoss() # BCELoss = no sigmoid built-in loss_fn = nn.BCEWithLogitsLoss() # BCEWithLogitsLoss = sigmoid built-in # Create an optimizer optimizer = torch.optim.SGD(params=model_0.parameters(), lr=0.1)
Python
복사

정확도 검증 함수

# Calculate accuracy (a classification metric) def accuracy_fn(y_true, y_pred): # eq() -> equal를 뜻함 -> eq(y_true, y_pred) -> [true, false, flase, true ..] # eq(y_true, y_pred).sum() -> 정답 수 # eq(y_true, y_pred).sum().item() -> python 형변환 함수 correct = torch.eq(y_true, y_pred).sum().item() # torch.eq() calculates where two tensors are equal # 정확도 = ( 정답 수 / 전체 수 ) * 100 acc = (correct / len(y_pred)) * 100 return acc
Python
복사

3.모델 학습

원시 모델 출력에서 예측된 레이블로 전환하기

logits -> prediction probabilities -> prediction labels
logits : 표준 로지스틱 분포의 분위수함수, 오즈비(odds ratio)의 자연로그
# 테스트 데이터에 대한 순전파의 첫 5개 출력을 확인한다 y_logits = model_0(X_test.to(device))[:5] # y_logits는 (배치, 예측) 형태이다 > print(y_logits.shape) torch.Size([5, 1]) > y_logits tensor([[-0.2079], [-0.1507], [-0.3872], [-0.1570], [-0.4334]], grad_fn=<SliceBackward0>)
Python
복사
# Use sigmoid as activate function y_pred_probs = torch.sigmoid(y_logits) # y_pred_probs -> (batch, prediction) > print(y_logits.shape) torch.Size([5, 1]) tensor([[-0.2079], [-0.1507], [-0.3872], [-0.1570], [-0.4334]], grad_fn=<SliceBackward0>) > y_pred_probs # (5, 1) tensor([[0.4482], [0.4624], [0.4044], [0.4608], [0.3933]], grad_fn=<SigmoidBackward0>)
Python
복사
y_pred_probs >= 0.5인 경우, y=1 (클래스 1)
y_pred_probs < 0.5이면, y=0 (클래스 0)
예측 레이블에서 예측 확률을 바꾸려면 시그모이드 활성화 함수의 출력을 반올림하면 된다.
# 예측 확률을 반올림하여 예측된 라벨을 찾는다 y_preds = torch.round(y_pred_probs) # 불필요한 차원을 제거한다 > y_preds.squeeze() # shape : (5,) tensor([0., 0., 0., 0., 0.], grad_fn=<SqueezeBackward0>)
Python
복사

Building a training and testing loop

# 재현성을 위해 랜덤 시드를 설정한다 torch.manual_seed(42) # 에폭 수를 설정한다 epochs = 1000 # 학습 및 평가 루프를 구축한다 for epoch in range(epochs): ################################################# ### 학습 루프 -> 1 에폭이 실행되었다 # 1. 순전파(forward) -> 모델을 학습시킨다 # 2. 손실 함수 -> 오차를 계산한다 # 3. 역전파(Backward) -> 오차만큼 모델의 파라미터를 수정한다 ################################################# model_0.train() # 1. 순전파를 수행한다 (모델은 원시 로짓을 출력한다) # X_train -> (800, 2) -> (배치, 특성) # y_logits -> (배치, 예측) -> (800, 1) y_logits = model_0(X_train) # y_logits -> (배치(예측),) -> (800,) y_logits = y_logits.squeeze() # 불필요한 `1` 차원을 제거한다 # 모델과 데이터가 동일한 디바이스에 있어야 작동한다 # y_pred -> (배치(확률),) -> (800,) y_pred = torch.round(torch.sigmoid(y_logits)) # 로짓을 확률로 변환한 후 예측 라벨로 반올림한다 # 2. 손실 및 정확도를 계산한다 # loss = loss_fn(torch.sigmoid(y_logits), # nn.BCELoss를 사용할 경우 torch.sigmoid()가 필요하다 # y_train) # loss_fn(예측값, 실제값) -> 차이를 계산한다 loss = loss_fn(y_logits, # nn.BCEWithLogitsLoss를 사용하면 원시 로짓과 함께 작동한다 y_train) # 정확도(accuracy_fn) = (정답 수 / 전체 수) * 100 # accuracy_fn(실제값, 예측값) -> 정확도를 계산한다 acc = accuracy_fn(y_true=y_train, y_pred=y_pred) # 3. 옵티마이저의 기울기를 초기화한다 optimizer.zero_grad() # 4. 손실에 대해 역전파를 수행한다 loss.backward() # 5. 옵티마이저를 업데이트한다 optimizer.step() ################################################# ### 테스트 루프 -> 학습 루프가 완료된 후에 실행된다 # 1. torch.inference_mode() -> 모델 파라미터를 고정시킨다 (required_grad=False) # 2. 순전파(Forward) -> 예측은 수행하지만 학습은 하지 않는다 # -> model_0(X_test) -> (배치, 예측) # -> model_0(X_test).squeeze() -> (배치(예측),) # 3. 손실 함수 -> 오차를 계산한다 # -> y_test(배치(실제값),)과 test_logits(배치(예측값),)의 오차를 계산한다 # 4. 평가 -> 정확도(accuracy_fn)를 계산한다 # -> 예측값을 확률값으로 변경한다 -> torch.sigmoid(test_logits) # -> 확률값을 이용해 이진 분류를 수행한다 -> torch.round(torch.sigmoid(test_logits)) # -> 정확도를 계산한다 -> accuracy_fn(실제값, 예측된 이진 분류) ################################################# model_0.eval() with torch.inference_mode(): # 1. 순전파를 수행한다 test_logits = model_0(X_test).squeeze() # 2. 손실 및 정확도를 계산한다 test_loss = loss_fn(test_logits, y_test) test_pred = torch.round(torch.sigmoid(test_logits)) test_acc = accuracy_fn(y_true=y_test, y_pred=test_pred) # 100 에폭마다 진행 상황을 출력한다 if epoch % 100 == 0: print(f"Epoch: {epoch} | Loss: {loss:.5f}, Accuracy: {acc:.2f}% | Test loss: {test_loss:.5f}, Test acc: {test_acc:.2f}%")
Python
복사

5.모델 저장