[CS231n] 8. Deep Learning Software
강의 주소:
CS231n Lecture 8. Deep Learning Software
자료:
깃허브 강의 자료
1. 지난 강의 복습
지난 시간에는 SGD Momentum, Nesterov, RMSprop, Adam과 같은 발전된 최적화 알고리즘을 다뤘다. 또한 학습 시 노이즈를 추가하고 테스트 시 이를 평균화하는 방식의 Regularization인 Dropout, 그리고 대규모 데이터셋에서 미리 학습된 모델을 가져와 자신의 문제에 맞게 미세 조정하는 Transfer Learning.
2. CPU vs GPU 하드웨어 비교
딥러닝에서 하드웨어의 역할은 매우 중요하다.
CPU (Central Processing Unit)
컴퓨터의 중앙 처리 장치로 보통 4~10개 정도의 강력한 코어를 가지고 있다. 각 코어는 매우 복잡한 명령을 독립적이고 빠르게 수행할 수 있지만 병렬 처리 능력은 수십 개의 스레드 정도로 제한적이다.
GPU (Graphics Processing Unit)
원래 게임 및 그래픽 렌더링을 위해 개발되었다. CPU에 비해 각 코어의 속도는 느리고 복잡한 연산 능력은 떨어지지만 수천 개의 코어를 가지고 있어 단순한 연산을 동시에 대량으로 처리하는 병렬 연산에 최적화되어 있다.
NVIDIA와 딥러닝:
현재 딥러닝 분야에서는 NVIDIA GPU가 지배적이다. NVIDIA는 딥러닝을 위해 하드웨어와 소프트웨어(CUDA 등)를 최적화하는 데 많은 노력을 기울여 왔다.
3. GPU의 병렬 연산 원리
GPU가 딥러닝에서 빛을 발하는 이유는 행렬 곱셈 때문이다. 행렬 곱의 각 원소 계산은 서로 독립적이기 때문에 GPU의 수천 개 코어에 작업을 분산시켜 동시에 계산할 수 있다. Convolution 연산 역시 가중치와 입력 데이터 간의 내적 연산이 반복되므로 GPU를 통한 병렬 처리가 매우 효율적이다.
4. 소프트웨어 계층: CUDA와 cuDNN
CUDA:
사용자가 C 언어와 유사한 방식으로 GPU에서 직접 코드를 실행할 수 있게 해주는 추상화 계층이다. 하지만 최적의 성능을 내는 CUDA 코드를 직접 짜는 것은 매우 어렵다.
cuDNN:
NVIDIA가 제공하는 라이브러리로 Convolution, Forward/Backward pass, Batch Normalization 등 딥러닝에 필요한 핵심 연산들이 매우 고도로 최적화되어 있다. 직접 짠 코드보다 보통 3배 이상 빠르므로 반드시 사용하는 것이 권장된다.
5. 데이터 로딩 병목 현상
GPU가 아무리 빨라도 하드디스크나 SSD에서 데이터를 읽어오는 속도가 느리면 전체 학습 속도가 저하된다.
해결 방법
- 데이터셋 전체를 RAM에 올리기.
- HDD 대신 SSD 사용하기.
- CPU 멀티스레딩을 활용하여 GPU가 연산하는 동안 다음 배치를 미리 불러오는 Prefetching 기법 적용하기.
6. 딥러닝 프레임워크의 역사와 필요성
과거에는 Caffe, Torch, Theano 등 학계 중심의 프레임워크가 주를 이루었으나 현재는 TensorFlow, PyTorch, Caffe2 등 산업계에서 주도하는 프레임워크로 전환되었다.
프레임워크를 사용하는 세 가지 이유 :
- 복잡한 Computational Graph를 쉽게 구축하고 관리할 수 있다.
- Auto-gradient(자동 미분) 기능을 통해 Backprop 코드를 직접 짤 필요가 없다.
- CUDA, cuDNN 등을 활용하여 GPU 위에서 연산을 효율적으로 수행한다.
7. TensorFlow 상세 분석
TensorFlow는 Static Graph 방식을 사용한다.
두 단계의 실행 방식:
먼저 계산 그래프를 정의하고, 나중에 Session을 열어 데이터를 흘려보내며 실행한다.
Placeholders:
데이터가 들어갈 빈 자리를 의미하며 실행 시점에 실제 데이터를 주입받는다. Variables:
그래프 내부에 상주하는 가중치와 같은 상태 값을 의미한다. 가중치가 그래프 내에 머물기 때문에 매 단계마다 CPU와 GPU 사이에서 대량의 가중치 데이터를 복사할 필요가 없어 효율적이다.
Optimizer:
tf.train.Optimizer를 사용하면 미분값 계산과 가중치 업데이트를 자동으로 처리해 준다.
High-level Wrapper:
Keras, TF-Learn, Sonnet 등 텐서플로우 위에서 더 간단하게 모델을 짤 수 있게 해주는 다양한 라이브러리들이 존재한다.
8. PyTorch 상세 분석
PyTorch는 Dynamic Graph 방식을 사용하여 더 직관적인 코딩이 가능하다.
추상화 계층
- Tensor:
GPU에서 동작하는 NumPy 배열과 같다. 딥러닝 기능은 없지만 연산이 빠르다. - Variable:
계산 그래프의 노드이며 gradient을 자동으로 저장하고 계산한다. - Module:
Layer을 의미하며 가중치 상태를 저장한다.
동적 그래프의 특징:
매번 Forward pass를 할 때마다 새로운 그래프가 생성된다. 따라서 Python의 일반적인 if문이나 for문을 사용하여 네트워크 구조를 실시간으로 변경할 수 있다.
DataLoader:
미니 배치를 생성하고 멀티스레딩 데이터 로딩 및 셔플링을 매우 편리하게 처리해 준다.
9. 정적 그래프 vs 동적 그래프 비교
정적 그래프 (TensorFlow 등) 장점:
그래프 구조가 고정되어 있으므로 프레임워크가 내부적으로 연산을 하기 용이하며 완성된 그래프를 파일로 저장하여 Python 없이 C++ 환경 등에서 배포하기 유리하다.
동적 그래프 (PyTorch 등) 장점:
코드가 매우 직관적이고 디버깅이 쉽다. 조건문이나 루프가 포함된 복잡한 구조를 구현할 때 일반 Python 코드를 그대로 쓸 수 있어 훨씬 편리하다.
10. 동적 그래프가 필요한 연구 사례
- Recursive Networks:
문장의 구문 트리 구조에 따라 네트워크가 재귀적으로 동작해야 할 때 유용하다.
Neural Module Networks:
질문 내용에 따라 서로 다른 신경망 모듈을 조합하여 새로운 구조를 실시간으로 만들어야 하는 시각 질문 답변 분야에서 필수적이다.
11. Caffe 및 Caffe2
Caffe:
코드 작성 없이 .prototxt라는 설정 파일에 네트워크 구조를 정의하여 학습시키는 방식이다. 이미 학습된 모델을 공유하는 ‘Model Zoo’가 잘 발달해 있으나 복잡한 제어 흐름을 구현하기는 어렵다.
Caffe2:
Caffe의 후속으로 페이스북에서 개발했다. TensorFlow처럼 정적 그래프를 사용하며 연구보다는 모바일 기기 배포나 서비스 운영에 최적화되어 있다.
12. 프레임워크 선택 가이드
연구 목적:
유연하고 디버깅이 쉬운 PyTorch를 추천한다.
일반적인 목적 및 대규모 배포:
생태계가 넓고 검증된 TensorFlow가 안정적인 선택이다.
모바일 및 서비스 적용:
TensorFlow나 Caffe2가 유리하다.