My Blog

강화학습 환경에 대한 상식(심층강화학습을 위한 하드웨어)


강화학습을 위한 컴퓨터

강화학습(Reinforcement Learning, RL)을 수행하기 위해서는 적절한 하드웨어가 필요합니다. 컴퓨터 하드웨어의 다양한 구성 요소들이 강화학습의 성능에 큰 영향을 미치기 때문에, 각 구성 요소에 대해 이해하는 것이 중요합니다. 이러한 이해가 없어도 강화학습을 코드적인 부분으로 구현하는데는 아무런 문제가 없지만, 디버깅 과정에서 발생하는 오류, 혹은 메모리 문제 등 강화학습이나 딥러닝 학습이나 실행도중 발생하는 갖가지 오류를 해결하기 위해 상식적으로 알아두면 매우 도움이 되는 내용들로 구성했습니다. 요즘 현대인들은 휴대용 스마트폰이 대중화가 되어 컴퓨터를 사무용으로만 사용하고 주로 스마트폰을 사용하고 있습니다. 그러나 강화학습이나 딥러닝을 다루고자 하면 컴퓨터를 사용해야 하고, 주로 GPU 연산장치를 사용하기에 일반 사무용 컴퓨터보다 조금 더 알아야 하는 부분도 분명 있기에, 여기에 필요한 지식을 습득해야지만 좀더 수월하게 할수 있을 것입니다. 아래에서는 강화학습을 위한 컴퓨터 하드웨어에 대해 자세히 설명하겠습니다. 먼저 컴퓨터 구성요소는, 1. 중앙 처리 장치(CPU: Central Processing Unit) 2. 그래픽 처리 장치(GPU: Graphics Processing Unit) 3. 메모리(RAM: Random Access Memory) 4. 저장 장치(Storage) 5. 마더보드(Motherboard) 6. 전원 공급 장치(PSU: Power Supply Unit) 7. 냉각 시스템(Cooling System) 등등으로 구성되어 있는데, 특히 딥러닝에는 GPU가 중요합니다. GPU는 대규모 병렬 연산을 수행하는 데 특화된 장치로, 강화학습에서 매우 중요한 역할을 합니다. 특히 딥러닝 기반 강화학습에서는 GPU가 필수적입니다. CUDA 코어 수: CUDA 코어는 병렬 연산을 수행하는 작은 프로세서들로 구성되어 있습니다. 많은 수의 CUDA 코어를 가진 GPU는 더 많은 연산 작업을 병렬로 처리할 수 있습니다. 메모리 용량: GPU 메모리는 딥러닝 모델과 데이터셋을 저장하는 데 사용됩니다. 큰 모델과 대규모 데이터셋을 처리하려면 충분한 메모리 용량이 필요합니다. 대역폭: GPU와 시스템 메모리 간의 데이터 전송 속도는 성능에 큰 영향을 미칩니다. 높은 대역폭을 제공하는 GPU를 선택하는 것이 중요합니다. GPU공급회사는 대표적으로 엔비디아의 그래픽 카드를 주로 사용하고, 구글의 TPU도 있으나 TPU에 대해서는 다음에 한번 자세히 다루도록 하겠습니다. 딥러닝에 GPU를 주로 사용하게 된다는것만 알고 계셔도 됩니다.

중앙 처리 장치(CPU: Central Processing Unit)

CPU는 컴퓨터의 주요 처리 장치로, 모든 연산 작업을 수행합니다. 강화학습에서는 다음과 같은 CPU 특성이 중요합니다: 코어 수와 스레드 수: 다중 코어와 다중 스레드 CPU는 병렬 처리를 통해 더 많은 연산 작업을 동시에 수행할 수 있습니다. 이는 대규모 데이터 처리가 필요한 강화학습에서 매우 유용합니다. 클럭 속도: CPU의 클럭 속도가 높을수록 더 빠른 연산 속도를 제공합니다. 높은 클럭 속도는 강화학습 알고리즘의 실행 시간을 단축시킬 수 있습니다. 비트 bit는 정보의 크기를 측정하는 가장 작은 단위입니다. 8비트가 1바이트 byte 혹은 8b = 1B 입니다. 여기서는 미터법에 따라 접두사가 붙는데, 1,000바이트 = 1킬로바이트 kb 100만 바이트 = 1메가바이트 mb 입니다. 데이터가 수치 데이터가 아니라면 먼저 하드웨어에 비트로 표현되기 전에 수치로 변환됩니다. 이미지는 픽셀값으로 변환되고, 소리는 주파수와 진폭으로 변환되고, 범주형 데이터는 원핫 부호화로, 단어는 벡터로 변환되는 식입니다. 데이터를 컴퓨터가 이해할 수 있도록 만들기 위한 전제조건은 데이터를 수치화해야 하고, 이러한 데이터가 하드웨어 수준에서 비트로 변환됩니다. 흔히 사용되는 가장 작은 메모리 묶음은 1바이트 또는 8비트인데, 지수법칙을 이용하면 8비트의 비트열은 2에 8제곱 = 256 개의 각기 다른 메세지를 표현할 수 있기 때문에 1바이트는 256개의 숫자를 나타낼 수 있습니다. 컴퓨터 수치연산에 자주 사용하는 numpy라이브러리에서는 각기 다른 범위의 정수를 구현하기 위해 1바이트를 사용하는데, 부호없는 8비트 정수 uint8의 범위는 [0,255]이고 부호있는 8비트 정수 int8은 [-128,127]이 됩니다. 바이트는 메모리에서 차지하는 공간이 가장 작기 때문에 그레이스케일 이미지(0~255)의 픽셀값과 같은 작은 수치 범위를 갖는 데이터를 저장하는데 적합합니다. 이때 바이트가 저장하는 공간을 메모리(RAM)라고 합니다.

메모리(RAM: Random Access Memory) 와 저장장치(Storage)

RAM은 컴퓨터의 임시 저장 장치로, 현재 실행 중인 프로그램과 데이터를 저장합니다. 강화학습에서는 충분한 RAM 용량이 필요합니다. 용량: 강화학습에서는 대규모 데이터셋과 복잡한 모델을 처리하기 때문에 충분한 RAM 용량이 필요합니다. 일반적으로 16GB 이상의 RAM을 권장합니다. 속도: RAM의 속도는 데이터 접근 시간에 영향을 미칩니다. 빠른 RAM은 전체 시스템 성능을 향상시킬 수 있습니다. 강화학습을 위해 컴퓨터를 활용할때 작은 용량의 RAM은 충분하지 않으므로 활용에 충분히 큰 용량을 확보하는게 중요합니다. 저장 장치(Storage) 저장 장치는 데이터를 영구적으로 저장하는 장치로, 주로 HDD(하드 디스크 드라이브)와 SSD(솔리드 스테이트 드라이브)로 구분됩니다. SSD: SSD는 HDD보다 빠른 데이터 접근 속도를 제공하며, 강화학습에서 대규모 데이터셋을 신속하게 로드하고 저장하는 데 유리합니다. 용량: 강화학습 프로젝트에서는 대규모 데이터셋과 모델 파일을 저장해야 하므로, 충분한 저장 용량이 필요합니다. 1TB 이상의 저장 용량을 권장합니다.

데이터의 유형(int, uint, float)

비트열의 크기를 두배로 증가시키면 8비트에서 16비트 정수로 구현할 수 있습니다. int16은 [-32768, 32768] 범위를 다룰수 있고, 더욱이 16비트열이 충분히 길기 때문에 float로 알려진 십진법 숫자 부동소수점을 표현하는데도 사용할 수 있습니다. 이렇게 하면 16비트 실수형 float16이 만들어지게 됩니다. 비트를 두배로 하는 과정을 반복하면 32비트와 64비트의 정수와 실수를 구현할 수 있는데, 이들은 각각 4바이트와 8바이트에 해당하고 int32, float32, float64로 만들어지지만 비트수가 두배가 될때마다 계산속도, 연산속도는 반으로 줄어들게 되는데, 이진 연산을 수행할 비트열의 원소 개수가 두배가 되기 때문입니다. 정수는 0을 중심으로 값의 범위를 정할때 int8, int16, int32, int64의 데이터 유형으로 구현할 수 있고, 부호없는 정수는 값의 범위가 0부터 시작하도록 범위를 조정한 것으로 표현할때는 uint8, uint16, uint32, uint64로 표현합니다. 부호가 있는 정수 int가 범위를 벗어나는 값을 할당받으면 오버플로가 발생해 연산이 꼬여 오류가 발생하나, 부호가 없는 정수 uint의 경우에는 오버플로우가 발생하지 않는 대신 모듈러스를 이용해 계산하게 됩니다. 특히 극단에 있는 값을 제한할 필요가 있을때는 다운캐스팅을 수행하기 전 먼저 그 값을 클리핑하는게 좋습니다. 부동소수점 숫자는 float16, float32, float64와 같이 16비트로 구현할 수 있습니다. 정수형 int와의 차이점은 데이터 크기, 계산 속도, 숫자가 나타낼 수 있는 십진수의 정밀도에서 발생하고, 비트수가 많을수록 아무래도 정밀도가 올라가게 됩니다. 이런 이유로 float16은 반정밀도라고 하고, float32는 단일 정밀도, float64는 이중 정밀도라고 합니다. 8비트 실수는 정밀도가 낮은 편에 속해 신뢰도가 떨어지기 때문에 잘 구현하지 않고, 반정밀도를 사용하면 단일 정밀도를 사용할때와 같은 속도로 두번 계산할수 있고 소수점 아래 많은 자릿수까지 정밀할 필요없는 계산에 적용하기 충분하므로 많이 사용됩니다. 대부분의 계산에서는 단일 정밀도로 충분하며 심층강화학습에서도 단일정밀도 데이터 유형이 가장 많이 사용되는데, 물리방정식이나 심도있는 과학계산에서는 이중정밀도를 사용하기도 합니다.

심층강화학습에서 데이터 유형의 최적화

강화학습(Reinforcement Learning, RL)은 에이전트가 환경과 상호작용하며 최대의 보상을 얻는 방법을 학습하는 과정입니다. 이 과정에서 데이터는 매우 중요한 역할을 합니다. 데이터 유형의 최적화는 강화학습 성능을 향상시키는 데 필수적입니다. 이 글에서는 왜 데이터 유형의 최적화가 필요한지, 그리고 어떻게 이를 실현할 수 있는지에 대해 자세하고 쉽게 설명하겠습니다. 1. 데이터의 효율적인 사용 강화학습에서는 에이전트가 환경과 상호작용하면서 얻는 데이터를 통해 학습합니다. 그러나 모든 데이터가 유용하지는 않습니다. 데이터를 효율적으로 사용하기 위해 최적화가 필요합니다. 중복 데이터 제거: 동일한 상황에서 반복적으로 수집된 데이터는 중복됩니다. 중복된 데이터를 제거함으로써 학습 속도를 높이고 저장 공간을 절약할 수 있습니다. 유의미한 데이터 선택: 에이전트의 학습에 실제로 기여하는 유의미한 데이터를 선택하는 것이 중요합니다. 이를 통해 에이전트가 더 빠르게 학습할 수 있습니다. 2. 데이터 품질 향상 데이터의 품질은 강화학습의 성능에 직접적인 영향을 미칩니다. 고품질 데이터를 사용하면 에이전트의 학습이 더 정확하고 효율적이게 됩니다. 노이즈 제거: 데이터에 포함된 노이즈(불필요한 정보)를 제거하면 에이전트가 중요한 정보를 더 잘 학습할 수 있습니다. 예를 들어, 이미지 데이터에서는 불필요한 배경 정보를 제거할 수 있습니다. 정확한 라벨링: 강화학습에서는 보상 신호가 매우 중요합니다. 데이터에 대한 정확한 라벨링이 이루어져야 에이전트가 올바른 학습을 할 수 있습니다. 3. 데이터 다양성 확보 다양한 데이터는 에이전트가 다양한 상황에 대해 학습할 수 있도록 도와줍니다. 데이터의 다양성은 에이전트의 일반화 능력을 향상시키는 데 필수적입니다. 다양한 상황 포함: 에이전트가 다양한 상황을 경험하도록 데이터를 수집하는 것이 중요합니다. 이를 통해 에이전트는 새로운 상황에서도 적절하게 대응할 수 있습니다. 다양한 행동 탐색: 에이전트가 다양한 행동을 시도하고 그 결과를 학습할 수 있도록 유도합니다. 이는 에이전트가 최적의 정책을 찾는 데 도움이 됩니다. 4. 데이터 효율성 극대화 강화학습에서는 많은 양의 데이터가 필요합니다. 그러나 데이터 수집에는 시간과 비용이 많이 들기 때문에, 효율적인 데이터 사용이 중요합니다. 경험 재생(Experience Replay): 에이전트가 이전에 경험한 데이터를 재사용함으로써 학습 효율성을 높일 수 있습니다. 이는 데이터 사용을 최적화하고 에이전트의 학습을 안정화합니다. 중요도 샘플링(Prioritized Sampling): 중요한 경험을 더 자주 학습에 사용하는 방법입니다. 이를 통해 에이전트가 중요한 경험을 더 빠르게 학습할 수 있습니다. 5. 데이터의 적절한 전처리 데이터 전처리는 강화학습에서 중요한 단계입니다. 적절한 전처리는 데이터의 품질을 높이고, 학습 과정에서의 성능을 향상시킬 수 있습니다. 정규화(Normalization): 데이터의 범위를 일정하게 조정하여 학습을 더 안정적이고 빠르게 만듭니다. 예를 들어, 입력 데이터를 0과 1 사이로 정규화할 수 있습니다. 데이터 증강(Data Augmentation): 기존 데이터를 변형하여 새로운 데이터를 생성하는 방법입니다. 이는 데이터의 다양성을 높이고, 에이전트의 일반화 능력을 향상시킵니다. 6. 현실 세계 적용 강화학습의 목표는 현실 세계의 문제를 해결하는 것입니다. 따라서 현실 세계의 데이터와 유사한 데이터를 사용하는 것이 중요합니다. 시뮬레이션 데이터 활용: 실제 데이터를 수집하기 어려운 경우, 시뮬레이션을 통해 유사한 데이터를 생성할 수 있습니다. 이는 강화학습의 초기 단계에서 매우 유용합니다. 현실 데이터 반영: 실제 환경에서 수집된 데이터를 사용하여 에이전트의 학습을 더욱 현실적으로 만듭니다. 이는 에이전트가 실제 상황에서도 효과적으로 작동할 수 있도록 합니다. 결론 강화학습에서 데이터 유형의 최적화는 에이전트의 학습 성능을 극대화하는 데 필수적입니다. 효율적인 데이터 사용, 데이터 품질 향상, 데이터 다양성 확보, 데이터 효율성 극대화, 적절한 데이터 전처리, 현실 세계 적용 등 다양한 측면에서 데이터 유형을 최적화함으로써, 에이전트는 더 빠르고 정확하게 학습할 수 있습니다. 이를 통해 강화학습의 목표를 성공적으로 달성할 수 있을 것입니다. 위에서 경험 재생에 저장할 데이터의 양으로 백만 개의 프레임을 보면 상태를 제외하면 이런 변수의 대다수는 스칼라 값으로, 모든 스칼라 변수에 대해 백만개의 값을 저장하려면 백만개의 원소가 필요하고 uint8을 이용하면 1MB를 차지하지만 float16을 이용하면 2MB를 차지할 것입니다. 현재 컴퓨터 기준으로 보면 1MB 차이는 매우 사소하므로 의도치않게 소수점 이하 숫자가 누락되거나 값의 범위가 제한되는 리스크 없애기위해 모든 데이터에 대해 float16을 사용하는 것이 일반적입니다. 강화학습에서 상태에 대한 메모리 최적화를 위해 신경써야 하는 부분은 일반적으로 심층 강화학습에서 생성되는 데이터중 대부분이 상태이기 때문에, 상태가 상대적으로 작은 텐서라면 float16으로 충분할 테지만 이미지와 같이 상태가 클 경우에는 보통의 휴대폰 카메라로 촬영하는 1920x1080 고해상도 이미지를 다루기에도 데이터 용량이 수MB가 될수 있으므로 그레이스케일로 변환하여 3개의 컬러 채널을 하나로 줄이기도 하고, 256x256에서 84x84로 다운슴플링 하여 데이터 크기를 줄여서 학습에 사용합니다. 원래의 RGB값은 0~255의 범위를 갖는 정수이지만, 그레이스케일로 만들면 RGB값은 0.0~255.0의 범위를 갖는 float32 픽셀값으로 변환되고, 대부분의 작업에서는 높은 정밀도의 픽셀값이 필요하지 않기 때문에, 픽셀값은 다시 uint8로 변환시켜 사용할 수도 있습니다. 실제 강화학습 알고리즘 실행시에 상태, 행동, 보상 및 처리된 데이터가 소비하는 메모리보다 더 큰 메모리를 소비하게 되므로, 알고리즘이 필요로 하는 원시 상태의 양이 변하지 않아도 메모리에서 데이터가 차지하는 공간이 몇 배로 늘수 있습니다. 이러한 데이터 유형에 따른 메모리 관리가 필요한 이유는 심층 강화학습에서 데이터 말고도 신경망 그 자체 만으로도 많은 메모리를 소비하기 때문에 적절한 관리가 필요합니다. 이처럼 저장된 데이터가 신경망에서 계산될때 하드웨어 한계로 인해 데이터 전달이 지연될수 있는데, 저장소 최적화를 위해 데이터 용량을 작게 만들어놓지 않으면 CPU/GPU가 데이터를 전달되기를 기다리는 동안이나 프로세스가 데이터 전달 및 복사를 위해 돌아가고 있을때와 같은 훈련 과정에서 병목 현상이 발생할 수도 있습니다. 컴퓨터 메모리 중 프로세서에 가장 가까이 위치하고 있으면서 일반적으로 프로그래밍으로 제어 가능한 메모리는 RAM으로 데이터를 효율적으로 RAM에 전달하는 것만으로도 데이터 병목 현상의 주요 원인은 이미 제거된 것입니다. 파이토치의 자동미분 같은 미분연산이 가능하도록 하기 위해 데이터를 Tensor 객체로 변환하여 신경망에 전달해야 하고, 데이터가 이미 numpy 데이터로 CPU RAM에 전달됐다면, 파이토치는 추가적인 데이터 복사없이 단순히 이 numpy데이터를 참조하여 tensor를 구축하게 됩니다. tensor를 이용하면 작업이 매우 효율적이고 용이하게 할수 있고 이러한 numpy-to-tensor 변환 예제로 인해 가능하고, 변환이 끝나면 tensor는 CPU RAM에서 곧바로 CPU로 전달되어 계산됩니다. GPU를 이용해 계산하려면, 텐서를 CPU RAM으로부터 GPU RAM으로 전달해야 하고 이 과정에서 데이터를 복사해 새로운 위치에 구축하는데 추가로 시간이 소요되므로, 데이터가 클 경우(딥러닝)에는 GPU의 계산속도 향상에 따른 효율이 올라가는데, 데이터가 작을 경우 주로 강화학습에서 신경망이 상대적으로 작은 데이터를 사용하기 때문에 이럴 경우에는 GPU를 사용해도 CPU대비 계산속도 향상 효과가 크지 않은 경우도 많습니다. 데이터 전달에 걸리는 시간 때문에 전체적으로 처리 속도가 더 느려질 경우도 있으니 데이터의 유형과 용량 등 계산하여 강화학습에 GPU연산을 하는게 좋습니다. 데이터 병목을 유발하는 또다른 잠재적 요인은 다수 프로세스를 이용해 알고리즘 훈련과정을 병렬화할때 발생하기도 하는데, 큰 컴퓨터 하나에서 훈련 실행하는 것이 가능하다면 데이터 통신에 따른 병목을 없앨수 있기 때문에 그렇게 하는편이 좋습니다. GPU 계산 효율을 높이는 환경은 주로 이미지 기반의 환경이나 게임 시뮬레이션 환경이 될수 있으나 데이터 유형 등을 잘 살펴서 적용해 보심이 좋을 듯 합니다.

Blog Home Back to Post List