KJH
pytorch MNIST 예제 설명 본문
pytorch에서 제공해주는 예제를 통해 어떻게 학습이 되는지 파악해보고자 한다.
https://github.com/pytorch/examples/blob/main/mnist/main.py
examples/mnist/main.py at main · pytorch/examples
A set of examples around pytorch in Vision, Text, Reinforcement Learning, etc. - pytorch/examples
github.com
딥러닝 모델을 학습할때는 기본적으로 세 가지 객체가 필요합니다.
Data, Model, Optimizer
모델 학습 과정
1. data에서 입출력을 분리해서 실험 세팅에 맞게 준비 (data_x[실험데이터], data_y[검증데이터] 분리)
2. data_x가 model을 통과, model_y를 얻음
3. model_y와 data_y의 출력을 비교
4. 비교 결과를 토대로 optimizer가 model을 학습 시킴
main함수의 133라인의 scheduler까지가 Data, Model, Optimizer랑 실험 세팅을 준비하는 코드이고,
train함수에 위 1,2,3,4 과정이 들어가 있으며 model을 학습시키게 됩니다.
1,2,3,4의 과정이 몇줄 안되는 간단한 코드로 구현이 완료되어 있습니다.
train함수 내에서 모델을 직접적으로 사용하는 부분은 얼마없고 data만 넣을 뿐이지 모델을 학습시킨다 라고 와닿진 않습니다..
train함수 실행 전 준비과정 코드가 딥러닝 학습에서 중요한 포인트로 작용을 하는 거 같습니다.
arg parse를 통해 준비 과정을 셋팅 합니다.
특정 cli에 옵션을 넣는 방식으로 보이고 --batch-size를 예로 들면
args = parser.parse_args() 가 실행 될때 args.batch_size = 64 (기본값) 으로 변환해서 들어가게 됩니다.
def main():
# Training settings
parser = argparse.ArgumentParser(description='PyTorch MNIST Example')
parser.add_argument('--batch-size', type=int, default=64, metavar='N',
help='input batch size for training (default: 64)')
parser.add_argument('--test-batch-size', type=int, default=1000, metavar='N',
help='input batch size for testing (default: 1000)')
parser.add_argument('--epochs', type=int, default=14, metavar='N',
help='number of epochs to train (default: 14)')
parser.add_argument('--lr', type=float, default=1.0, metavar='LR',
help='learning rate (default: 1.0)')
parser.add_argument('--gamma', type=float, default=0.7, metavar='M',
help='Learning rate step gamma (default: 0.7)')
parser.add_argument('--no-cuda', action='store_true', default=False,
help='disables CUDA training')
parser.add_argument('--no-mps', action='store_true', default=False,
help='disables macOS GPU training')
parser.add_argument('--dry-run', action='store_true', default=False,
help='quickly check a single pass')
parser.add_argument('--seed', type=int, default=1, metavar='S',
help='random seed (default: 1)')
parser.add_argument('--log-interval', type=int, default=10, metavar='N',
help='how many batches to wait before logging training status')
parser.add_argument('--save-model', action='store_true', default=False,
help='For Saving the current Model')
args = parser.parse_args()
모델을 학습시킬때 어떤 장비를 쓸지 선택하는 부분
실행 장비에 CPU, GPU, MPS장비가 있는지 확인하는 부분입니다.
※ mps는 처음 보는데 센서를 활용해 자동화 공정을 구성하는 장비라고 하네요 공장에서 사용되는거 같습니다.
use_cuda = not args.no_cuda and torch.cuda.is_available()
use_mps = not args.no_mps and torch.backends.mps.is_available()
if use_cuda:
device = torch.device("cuda")
elif use_mps:
device = torch.device("mps")
else:
device = torch.device("cpu")
학습과정에서 데이터셋을 랜덤의 기준을 지정하는 부분
데이터 순서를 랜덤으로 섞거나 모델 초기화 때 랜덤으로 배정되는 숫자 같이 사용하지만 없다고 해서 큰 영향을 주지는 않습니다.
torch.manual_seed(args.seed)
_kwargs 변수에는 main함수 상단에서 설정했던 값이 들어갑니다.
train_kwargs = {'batch_size': args.batch_size}
test_kwargs = {'batch_size': args.test_batch_size}
GPU 를 사용할 수 있는 환경이면 세 가지 값이 추가됩니다.
num_workers : data loader 과정에서 사용할 CPU 대수
※ GPU는 모델/tensor 계산에 사용하고, CPU는 그 외(data 준비 등등)에 사용하게 됩니다.
pin_memory : 로드한 데이터를 RAM에서 GPU에 빠르게 옮겨주는 옵션입니다.
shuffle : 학습 epoch마다 batch의 조합을 매번 데이터를 섞게 됩니다.
if use_cuda:
cuda_kwargs = {'num_workers': 1,
'pin_memory': True,
'shuffle': True}
train_kwargs.update(cuda_kwargs)
test_kwargs.update(cuda_kwargs)
Data 객체 준비
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
dataset1 = datasets.MNIST('../data', train=True, download=True,
transform=transform)
dataset2 = datasets.MNIST('../data', train=False,
transform=transform)
train_loader = torch.utils.data.DataLoader(dataset1,**train_kwargs)
test_loader = torch.utils.data.DataLoader(dataset2, **test_kwargs)
train=True : 학습용 데이터셋 가져오기
train=False : 테스트용 데이터셋 가져오기
download=True : 데이터가 없으면 인터넷에서 받아오기
transform=transform -> transforms.ToTensor() : data를 꺼내어 tensor 형태로 변경합니다.
-> transforms.Normalize((0.1307,), (0.3081,)) : 데이터셋의 평균/표준편차 값을 미리 구해둔 것
위 두 값으로 데이터셋 전체를 정규화(Normalization) 시켜줍니다.
※ 인공지능 모델을 훈련시키고 사용할 때, 일반적으로 입력은 0 ~ 1 사이의 값으로 정규화함
from torchvision import datasets, transforms
...
dataset1 = datasets.MNIST('../data', train=True, download=True,
transform=transform)
dataset2 = datasets.MNIST('../data', train=False,
transform=transform)
정규화 된 데이터셋과, 데이터를 어떻게 가공할지에 대한 정보인 _kwargs로 DataLoader를 선언
이 과정을 거치면 날것의 데이터셋을 학습할 때 쓰기 용이한 형태로 변경됨
※ 객체를 준비하는 과정 중 Data에 해당되는 과정인데 입출력을 분리 하는 과정은 datasets.MNIST 에 정리 되어 있어서 간단하게 가능
※ kwargs 앞의 **은 딕셔너리의 각 키-값 쌍을 DataLoader 함수의 인자로 전달하게 해줌
※ *도 있는데 리스트나 튜플의 요소를 인자로 전달하게 해줌
train_loader = torch.utils.data.DataLoader(dataset1,**train_kwargs)
test_loader = torch.utils.data.DataLoader(dataset2, **test_kwargs)
Model 객체 준비
Net() : 딥러닝 모델 부분으로 convolution 2개, dropout, linear layer 2개로 구성되어 있음
to(device) : 모델 계산을 위해 CPU,GPU,MPS 중 하나를 사용하게 하는 부분
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.dropout1 = nn.Dropout(0.25)
self.dropout2 = nn.Dropout(0.5)
self.fc1 = nn.Linear(9216, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = F.max_pool2d(x, 2)
x = self.dropout1(x)
x = torch.flatten(x, 1)
x = self.fc1(x)
x = F.relu(x)
x = self.dropout2(x)
x = self.fc2(x)
output = F.log_softmax(x, dim=1)
return output
def main():
...
model = Net().to(device)
Optimizer 객체 준비
모델의 직접적인 수정은 없이 optimizer를 사용하기만 해서 어디서 모델이 변경되는건지 의아 했었는데요
모델의 파라미터를 optimizer가 가지고 있었고, 44번 줄 step 단계에서 모델로 접근하여 변화시키고 있습니다.
lr(learning rate) 값으로 데이터를 쪼개어 학습하게 됩니다.
optimizer = optim.Adadelta(model.parameters(), lr=args.lr)
scheduler는 LR을 관리하고 optimizer를 보고 있습니다. 큰 역할은 아니지만 원활한 학습에 도움을 줍니다.
scheduler = StepLR(optimizer, step_size=1, gamma=args.gamma)
'MLOps' 카테고리의 다른 글
k3s gpu containerd기반 kubeflow 구축 (0) | 2024.07.21 |
---|---|
ML용어 비전공자 입장에서 이해해보기 (2022 ~ ing) (0) | 2024.07.19 |
pytorch 폐암환자 예측하기 (0) | 2024.07.17 |
MLOps (0) | 2024.07.14 |