Pytorch 파헤치기

기남·2023년 5월 12일
0
post-thumbnail

🎉 왜 Tensorflow보다 Pytorch를 택할까

사용하기 쉬운 API와 직관적인 문법
PyTorch는 사용하기 쉬운 API와 직관적인 문법을 가지고 있다. 반면 TensorFlow는 상대적으로 복잡한 API와 문법을 가지고 있어서, 처음 사용하는 사람들에게는 학습 곡선이 더욱 가파르다.

동적 계산 그래프(dynamic computation graph)를 사용
PyTorch는 실행되는 동안 계산 그래프를 동적으로 생성하고 수정할 수 있는데, 이는 딥러닝 모델 개발을 보다 유연하게 할 수 있게 만들어 줍니다. TensorFlow는 정적 계산 그래프(static computation graph)를 사용하므로, 계산 그래프를 먼저 정의한 후에 그래프를 실행해야 한다.

활발한 커뮤니티, 다양한 라이브러리
PyTorch는 커뮤니티가 활발하고, 딥러닝 모델 구현에 필요한 다양한 라이브러리와 도구들이 많이 개발되어 있다.

🎈Numpy 대신 Tensor를 이용하는 이유

GPU 연산 지원
PyTorch Tensor는 Numpy 배열과 유사하지만, GPU 연산을 지원한다. GPU를 사용하면 데이터를 병렬로 처리할 수 있기 때문에 모델 학습 및 추론 속도를 크게 높일 수 있다.

자동 미분 기능
PyTorch는 자동 미분(automatic differentiation)을 지원한다. 이를 통해 미분 계산을 자동으로 수행할 수 있어, 신경망 모델의 학습을 더욱 효율적으로 할 수 있다.

🧨Autograd 원리

순전파 단계에서 각각의 연산을 수행할 때마다 연산 그래프(computational graph)를 정의한다. 이렇게 만들어진 그래프를 이용해 역전파 시에 Gradient를 자동으로 계산한다.

✨Dataset , DataLoader

Dataset
사용자가 학습에 사용할 데이터셋을 만들 수 있도록 해주는 클래스이다. 예를 들어, 이미지 분류 모델을 학습시키기 위해서는 이미지 파일들이 포함된 폴더 구조가 있을텐데, 이 폴더 구조를 읽어와서 이미지와 레이블을 읽어오는 역할을 한다. Dataset 클래스는 추상클래스로, 개발자가 데이터셋 클래스를 만들 때 상속받아 구현해야 한다.

DataLoader
Dataset에서 로드된 데이터를 실제 모델 학습에 사용할 수 있는 형태로 변환해주는 역할을 한다. 이 클래스는 데이터셋에서 미니배치(mini-batch) 크기만큼 데이터를 추출하고, 데이터를 미니배치 단위로 나누어 모델 학습에 로딩한다. Data 배치를 출력하는 함수로 볼 수도 있다.

  • collate_fn : 텍스트 데이터와 같이 data가 고정된 길이가 아닐 경우, 이 함수를 이용해 데이터를 묶어줘야 2개 이상의 batchsize를 사용할 수 있다.
  • num_workers : 데이터를 불러오는
    CPU 프로세스의 개수
  • drop_last : 마지막 배치의 크기가 미니배치 크기보다 작을 경우 해당 배치를 버릴지 여부

🎉model.train() , model.eval()

model.train()
모델을 학습 모드로 전환한다. 이 모드에서는 모델의 순전파 시에 연산 그래프를 만들고 역전파 시에 파라미터가 업데이트된다. 또한, Dropout과 같은 학습 중에만 적용되는 기술들도 활성화된다.

model.eval()
모델을 평가 모드로 전환한다. 이 모드에서는 모델의 내부 상태가 변하지 않는다. 또한, Dropout과 같은 학습 중에만 적용되는 기술들이 비활성화된다.

🎃torch.no_grad()

torch.no_grad()를 사용하면 해당 구문 내에서 모든 연산의 기록을 추적하지 않는다. 이는 Gradient 계산과 같은 불필요한 계산을 방지할 수 있으며, 이를 통해 메모리 사용량을 줄이고 모델 평가를 더 빠르게 수행할 수 있다.

🎄model.to()

모델을 CPU 또는 GPU 로 이동시킨다. model.to(cuda)로 모델의 모든 매개 변수와 버퍼GPU에 할당하면 이후 모든 대규모 연산이 GPU에서 수행되어 빠르게 처리된다.

🎐transforms.normalize() 효과

RGB 채널 평균(mean)과 표준편차(std) 값을 이용해 이미지들을 정규화하여, 모델이 학습할 때 인풋 이미지들의 분포가 유사해져 학습에 도움이 된다.

🎑Cross-entropy Loss (교차 엔트로피)

ii번째 예측값이 정답과 일치할 확률 : yt(1y)1ty^t(1-y)^{1-t}
모든 예측값이 정답과 일치할 확률 : i=1nyt(1y)1t\prod_{i=1}^ny^t(1-y)^{1-t}

이때 위의 수식은 모두 곱셈으로 이루어져 있기 때문에 미분이 어렵다. 따라서 LogLog함수를 취해줌으로써 덧셈으로 표현해 미분이 쉽게 되도록 한다.

L=1Ni=1Nj=1Cyijlog(pij)\mathcal{L} = -\frac{1}{N} \sum_{i=1}^{N} \sum_{j=1}^{C} y_{ij} \log(p_{ij})

🎁Tensor, Numpy

Tensor와 Numpy는 같은 메모리 공간을 공유하기 때문에 하나를 변경하면 다른 하나도 변경된다.

🎟 zero_grad()

backward()함수가 호출되면 Gradient가 기존의 값에 누적되어 더해지도록 설계되어 있다. 따라서 zero_grad()를 통해 Gradient들을 0으로 초기화해주어야 한다.

RNN과 같은 형태에 Gradient 누적이 필요할 수 있다.

🎫데이터 전처리

데이터를 모델이 이해하기 쉽고 효과적으로 학습할 수 있는 형태로 바꾸는 것을 말한다.
노이즈, 중복값 제거
Real World의 데이터에는 노이즈와 중복값이 다수 존재할 수 있기 때문에 이를 제거해주어야 한다.

모델에 적합한 형태로 변형
이미지의 Scale을 모델의 인풋 사이즈로 바꾸거나 정규화하는 과정이 필요하다.

Data Augmentation
회전, Crop, 밝기 조정 등의 기법을 이용해 데이터 양을 늘려 모델의 일반화 성능을 높일 수 있다.

🎠torch.nn

신경망 모델을 만들 수 있는 기본 코드들이 구현되어 있는 라이브러리이다.

nn.Module
모든 신경망 모델의 기본 클래스로, 이 클래스를 상속받아 새로운 모델을 정의한다.

nn.Linear
모든 입력 노드와 출력 노드 간의 매핑을 갖는 선형 layer이다.

nn.Conv2d
2D 이미지에서 컨볼루션 연산을 해 특징맵을 뽑아내는 Convolutional layer이다.

이외에도 nn.ReLU와 같은 활성화함수와 nn.CrossEntropyLoss와 같은 비용함수들을 포함한다.

🎢num_workers

학습 도중 CPU의 작업을 몇 개의 코어가 할 것인지를 정하는 파라미터이다. 데이터를 전처리한 후 GPU로 로드하는 것에 더 많은 코어를 할당해 빠르게 처리하면 GPU의 효율이 높아진다. 하지만 데이터 그만큼 데이터 전처리 이외의 CPU 작업이 느려지기 때문에 적절한 튜닝이 필요하다.

nn.DataParallel

단일 Process 멀티 thread 방식을 이용한 데이터 병렬 처리 기법이다.

동작 순서

  • 각 Forward Pass마다 모델이 각 GPU들에 복제된다.
  • Batch가 각 GPU에 분산되어 인풋으로 들어간다.
  • 각 디바이스가 Forward Pass를 수행하고 연산 결과를 메인 GPU로 모두 모은다.
  • Loss를 계산하고 각 디바이스에 전파한다.
  • 전달받은 Loss로 Backward Pass를 수행하고 Gradient를 계산한다.
  • 각 디바이스가 계산한 Gradient를 한데 모으고 평균을 낸다.
  • 메인 GPU의 모델을 업데이트한다.
  • 이 과정을 반복한다.

단점

  • 메인 GPU의 작업량과 메모리 사용량이 다른 GPU들에 비해 높다.
  • 파이썬은 한번에 한 쓰레드만 파이썬 바이트 코드를 실행할 수 있도록 막는 GIL(Global Interpreter Lock)이 있는데 이로 인해 병렬 연산의 장점이 크게 없다.
  • 매번 모든 GPU로 모델을 복제하는 과정에 오버헤드가 크다.

nn.DistributedDataParallel

멀티 Process 방식을 이용하고, Gradient 공유 및 파라미터 업데이트 오버헤드가 크게 줄어든 기법이다.

GPU들이 고리를 이룬다고 생각했을 때, 각 GPU가 다음 GPU에게 Gradient들을 전달하면서 간편하게 모두 Gradient를 공유할 수 있다.

따라서 모든 GPU가 같은 Gradient를 공유하고, 동시에 병렬적으로 모델을 업데이트할 수 있기 때문에 모델을 다시 복제할 필요가 없다.

또한 역전파가 뒤쪽 레이어부터 진행되기 때문에 역전파 도중에 파이프라인 기법으로 Gradient를 전달 및 공유할 수 있다.

코드 구현

  • Model을 DDP 함수로 묶는다.
  • Dataloader가 Sample을 분배할 때 Distributed Sampler을 이용하도록 한다.
  • GPU 동기화를 관리해주는 백엔드(nccl)를 선택한다.
  • (단일 노드) 사용 가능한 port를 할당해 master 프로세스가 다른 GPU들과 통신할 수 있도록 한다.
    (멀티 노드) 한 노드를 master 노드로 삼고 이 노드의 ip-address와 사용 가능한 port를 할당한다.
  • 각 GPU에서 프로세스 작업을 실행한다.

nccl
NVIDIA GPU를 사용하는 분산 학습에서 사용되는 라이브러리로, CPU와 GPU 간의 데이터 전송을 최적화해주며 GPU 동기화를 관리한다.

profile
AI 공부하는 대학생

0개의 댓글

관련 채용 정보