딥 러닝 모델을 훈련 할 때 미니 배치 메모리 영향을 계산하는 방법은 무엇입니까?


17

나는 안드레이 Karphaty에서이 노트를 기반으로 내 모델을 학습하기 위해 GPU에 의해 메모리에 필요한 양을 계산하기 위해 노력하고있어 : http://cs231n.github.io/convolutional-networks/#computational-considerations

내 네트워크에는 532,752 개의 활성화19,072,984 개의 매개 변수 (가중치 및 바이어스)가 있습니다. 이들은 모두 32 비트 부동 소수점 값이므로 각각 4 바이트의 메모리를 사용합니다.

입력 이미지는 180x50x1 (너비 x 높이 x 깊이) = 9,000 부동 32 값입니다. 이미지 확대를 사용하지 않으므로 기타 메모리는 미니 배치 크기에만 관련이 있다고 생각합니다. 128 이미지의 미니 배치 크기를 사용하고 있습니다.

Andrej의 권장 사항에 따라 다음 메모리 크기를 얻습니다.

활성화 : 532,752 * 4 / (1024 ^ 2) = 2.03MB

매개 변수 : 19,072,984 * 4 / (1024 ^ 2) * 3 = 218.27MB

기타 : 128 * 9,000 * 4 / (1024 ^ 2) = 4.39MB

따라서이 네트워크를 훈련시키는 데 필요한 총 메모리는 224,69MB 입니다.

TensorFlow를 사용하고 있는데 뭔가 빠진 것 같습니다. 아직 교육을 실시하지는 않았지만 사용 경험이 계산 한 것보다 훨씬 높을 것입니다.

미니 배치의 각 이미지에 대해 TensorFlow가 그라디언트를 유지하여 단일 가중치 / 바이어스 업데이트 단계에서 나중에 정규화 할 수 있다면 메모리가 다른 532,752 * 128 값 (각 이미지의 그라디언트)을 고려해야한다고 생각합니다 미니 배치). 이 경우 128 이미지 / 미니 배치로이 모델을 교육하려면 260.13MB가 더 필요합니다.

딥 러닝 모델을 훈련하기위한 메모리 고려 사항을 이해하도록 도와 줄 수 있습니까? 위의 고려 사항이 맞습니까?


귀하의 질문에 대한 (제안 된) 답변을 여기에서 참조하십시오 .
Adam Hendry

답변:


5

당신이 올바른 길을 가고 있다고 생각합니다.

그렇습니다. 활성화의 파생물과 역 전파 매개 변수를 저장해야합니다.

또한 선택한 최적화가 중요 할 수 있습니다. SGD, Adam 또는 Adagrad를 사용하여 훈련하고 있습니까? 이들은 모두 다른 메모리 요구 사항을 갖습니다. 예를 들어, 모멘텀 기반 방법을 위해 단계 크기 캐시를 저장해야하지만 언급 한 다른 메모리 고려 사항과 비교하여 보조 크기 여야합니다.

전체적으로, 당신은 순방향 패스를위한 메모리 요구 사항을 계산 한 것 같습니다. Andrej Karpathy 는 역방향 패스가 순방향 패스의 메모리를 최대 3 배까지 차지할 수 있다고 언급하므로 이러한 차이가 발생할 수 있습니다 (VGGNet의 예를 보려면 웹 사이트에서 'Case Studies'로 스크롤).


5

@StatsSorceress TL; DR :

이 활동을 수행하여 필요한 메모리를 직접 계산할 수 있는지 확인합니다.

활성화 : 532,752 * 2 * 4 / (1024 ^ 2) = 4.06 MB

매개 변수 : 19,072,984 * 4 / (1024 ^ 2) * 3 = 218.27MB

기타 : 128 * 9,000 * 4 / (1024 ^ 2) = 4.39MB

총 메모리 : (4.06 * 128 ) + 218.27 + 4.39 = 742.34 MB

( 내가 틀렸다면 누군가 나를 수정하십시오. 참고로, 당신은 이미 기타에 128을 곱했기 때문에 위의 128을 곱하지 않은 이유입니다 )


이 기사해당 비디오 를 알려 드리겠습니다 . 그들은 내가 더 잘 진행되고있는 것을 이해하도록 도와주었습니다.

참고 : 예측에 네트워크를 사용하는 데 필요한 메모리는 다음 두 가지 이유로 훈련에 필요한 메모리보다 훨씬 작습니다.

  • 예측할 때 네트워크를 통해 이미지를 앞으로 만 전송하고 뒤로는 전송하지 않습니다 (따라서 메모리 X 3을 곱하지는 않습니다. 아래 참조).
  • 이미지 당 하나의 예측이 있습니다 (따라서 예측에 배치를 사용하지 않기 때문에 하나의 이미지에 필요한 메모리에 배치 크기를 곱할 필요가 없습니다).

프로세스 (트레이닝 할 메모리)

  1. 하나의 이미지를 학습하는 데 필요한 메모리 계산
  2. 이 숫자에 배치의 이미지 수를 곱 하십시오.

( 기억하세요 : 미니 배치는 데이터의 서브 세트를 가져 와서 서브 세트의 각 이미지에 대한 그라디언트 및 오류를 계산 한 다음 이들을 평균화하고 평균 방향으로 진행한다고 말합니다. convnets의 경우 가중치와 바이어스는 공유되지만 활성화 횟수는 배치의 이미지 수에 따라 제한됩니다. ).

1 단계 : 1 개의 이미지를위한 메모리

하나의 이미지를 훈련 시키려면 다음을 위해 메모리를 예약해야합니다.

  • 모델 매개 변수 :

    각 레이어 의 가중치바이어스 , 그레디언트모멘텀 변수 (Adam, Adagrad, RMSProp 등의 경우 옵티마이 저가 사용 된 경우)

    이를 위해 메모리를 근사화하려면 가중치와 바이어스를 저장하는 데 필요한 메모리를 계산하고 가중치와 바이어스를 저장하는 데 필요한 메모리의 양이 (대략) 같다고 말하므로 3을 곱합니다 (예 : "3"). 그라디언트 및 운동량 변수에 필요한 것)

    방정식 :

    컨볼 루션 :

    가중치 (n) = 깊이 (n) * (kernel_width * kernel_height) * 깊이 (n-1)

    치우침 (n) = 깊이 (n)

    완전히 연결된 (고밀도) 레이어 :

    가중치 (n) = 출력 (n) * 입력 (n)

    바이어스 (n) = 출력 (n)

여기서 n 은 현재 레이어이고 n-1 은 이전 레이어이고 출력 은 FC 레이어의 출력 수이고 입력 은 FC 레이어 의 입력 수입니다 (이전 레이어가 완전히 연결된 레이어가 아닌 경우, 입력 수는 평평한 레이어의 크기와 같습니다).

참고 : 가중치 및 바이어스 전용 메모리와 하나의 이미지에 대한 활성화 메모리 (아래 참조)는 예측에 필요한 총 메모리 양입니다 (볼록 및 기타 사항에 대한 메모리 오버 헤드 제외).

  • 활성화 (Caffe에서 "Blob") :

(여기서 용어를 느슨하게 사용하고 있습니다.

컨볼 루션 레이어의 각 컨볼 루션은 " 이미지의 픽셀 수 "활성화를 생성합니다 (예 : 단일 컨볼 루션을 통해 이미지를 전달하면 " m "활성화 로 구성된 단일 기능 맵이 표시됩니다 . 여기서 " m "은 사용자의 픽셀 수임) 이미지 / 입력).

완전히 연결된 레이어의 경우 생성하는 활성화 수는 출력 크기와 같습니다.

컨볼 루션 :

활성화 (n) = image_width * image_height * image_num_channels

완전히 연결된 (고밀도) 레이어 :

활성화 (n) = 출력 (n)

입력 내용은 실제로 네트워크 시작 부분의 이미지 일뿐입니다. 컨볼 루션 후에는 다른 것으로 바뀝니다 (피처 맵). 따라서 "image_width", "image_height"및 "image_num_channels"를 "input_width", "input_height"및 "layer_depth"로보다 정확하게 대체하십시오. (이미지 측면에서이 개념을 생각하기가 더 쉽습니다.)

또한 각 계층에서 활성화에 대한 오류를 저장해야하기 때문에 (후진 패스에서 사용), 스토리지 공간에서 공간을 확보해야하는 총 엔티티 수를 얻기 위해 활성화 수에 2를 곱합니다. 일괄 처리의 이미지 수에 따라 활성화 수가 증가하므로이 수에 일괄 처리 크기를 곱하십시오.

2 단계 : 배치를 훈련시키는 메모리

가중치 및 바이어스 수 (3 회)와 활성화 횟수 (배치 크기의 2 배)를 합산합니다. 이 값에 4를 곱하면 배치를 훈련시키는 데 필요한 바이트 수를 얻습니다. 1024 ^ 2로 나누면 GB 단위로 답을 얻을 수 있습니다.


"예측에 배치를 사용하지 않습니다"라고 말하는 이유는 무엇입니까? 사용자가 많은 수의 이미지를 예측해야하는 경우 예측에 배치를 사용하는 것이 좋습니다.
user3731622

1

또는 프로파일 러 라이브러리를 사용하여 프로그램의 메모리 및 CPU 사용량을 분석 할 수 있다고 생각합니다. 특정 스레드 또는 프로세스별로 밀리 초 간격으로 메모리 및 CPU 사용량의 스냅 샷을 제공 할 수있는 많은 Python 라이브러리가 있습니다.

popen을 사용하여 다른 하위 프로세스에서 모니터링하려는 프로그램 부분을 실행하고 PID를 사용하여 메모리 및 CPU 사용량을 모니터링 할 수 있습니다.

psutil 나는 그런 일에 좋다고 생각한다. 많은 사람들이 있지만.

이것이 도움이되기를 바랍니다.


3
답변 @Anwar에 감사드립니다. 나는 경험적 관찰보다는 분석적 계산을 찾고 있습니다.
barbolo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.