Derin öğrenme modellerini eğitirken mini yığın bellek etkisini nasıl hesaplayabilirim?


17

Andrej Karphaty'den bu notlara dayanarak modelimi eğitmek için bir GPU'nun ihtiyaç duyduğu bellek miktarını hesaplamaya çalışıyorum: http://cs231n.github.io/convolutional-networks/#computational-considerations

Benim ağ sahiptir 532752 aktivasyonlar ve 19072984 parametreleri (ağırlık ve bias). Bunların tümü 32 bit kayan değerlerdir, bu nedenle her biri bellekte 4 bayt alır.

Giriş görüntüm 180x50x1 (genişlik x yükseklik x derinlik) = 9.000 float 32 değer. Görüntü büyütme kullanmıyorum, bu yüzden çeşitli bellek sadece mini-parti boyutu ile ilgili olacağını düşünüyorum. 128 boyutlu mini-toplu boyut kullanıyorum.

Andrej'in önerisine dayanarak aşağıdaki bellek boyutlarını alıyorum:

Aktivasyonlar: 532.752 * 4 / (1024 ^ 2) = 2.03 MB

Parametreler: 19.072.984 * 4 / (1024 ^ 2) * 3 = 218.27 MB

Çeşitli: 128 * 9.000 * 4 / (1024 ^ 2) = 4.39 MB

Yani bu ağı eğitmek için toplam bellek 224,69 MB olacaktır .

TensorFlow kullanıyorum ve sanırım bir şey eksik. Eğitimi henüz çalıştırmadım, ancak kullanılan hafızanın hesapladığımdan çok daha yüksek olacağından eminim (geçmiş deneyimlere dayanarak).

Mini toplu işteki her görüntü için, TensorFlow degradelerini daha sonra tek bir ağırlık / önyargı güncelleme adımı için normalize edebilecek şekilde tutarsa, hafızanın başka bir 532,752 * 128 değeri (gradyanlar mini toplu). Bu durumda, bu modeli 128 resim / mini-toplu olarak eğitmek için daha fazla 260.13 MB gerekir.

Derin öğrenme modelimi eğitmeyle ilgili bellek hususlarını anlamama yardımcı olabilir misiniz? Yukarıdaki hususlar doğru mu?


Lütfen sorunuza (önerilen) cevabımı burada bulabilirsiniz .
Adam Hendry

Yanıtlar:


5

Bence doğru yoldasın.

Evet, aktivasyonların türevlerini ve backpagagation parametrelerini saklamanız gerekecektir.

Ayrıca, optimizasyon seçiminiz de önemli olabilir. SGD, Adam veya Adagrad'ı mı kullanıyorsunuz? Bunların hepsinin farklı bellek gereksinimleri olacaktır. Örneğin, adım boyutu önbelleğini momentum tabanlı bir yöntem için saklamanız gerekecek, ancak bahsettiğiniz diğer bellek hususlarına kıyasla ikincil olmalıdır.

Sonuçta, ileri geçiş için bellek gereksinimlerini hesaplamış gibi görünüyorsunuz. Andrej Karpathy , geriye doğru geçişin ileri geçişin belleğinin 3 katına kadar çıkabileceğinden bahsediyor, bu yüzden böyle bir fark görüyor olabilirsiniz (VGGNet için bir örnek görmek için web sitesinde 'Örnek Çalışmalar'a gidin).


5

@StatsSorceress TL; DR:

Kendim için gerekli belleği hesaplayıp hesaplayamayacağımı görmek için bu aktiviteden geçiyorum:

Aktivasyonlar: 532.752 * 2 * 4 / (1024 ^ 2) = 4.06 MB

Parametreler: 19.072.984 * 4 / (1024 ^ 2) * 3 = 218.27 MB

Çeşitli: 128 * 9.000 * 4 / (1024 ^ 2) = 4.39 MB

Toplam Bellek: (4.06 * 128 ) + 218.27 + 4.39 = 742.34 MB

( Eğer yanılıyorsam birisi beni bu konuda düzeltin. FYI, sen zaten 128 ile çeşitli çarptın, bu yüzden yukarıdaki 128 ile çarpmadım )


Sizi bu makaleye ve ilgili videoya yönlendireceğim . Neler olduğunu daha iyi anlamama yardımcı oldular.

NOT: Tahminler için bir ağ kullanmak için gereken bellek, iki nedenden dolayı eğitim için gerekenden çok daha azdır:

  • Tahmin ederken, bir görüntüyü yalnızca ağ üzerinden ileriye doğru göndeririz, geriye doğru değil (bu nedenle X 3 belleğini çarpmayız; aşağıya bakın)
  • Görüntü başına bir tahmin vardır (bu nedenle, bir görüntü için gereken belleği toplu bir boyutla çarpmamıza gerek yoktur çünkü tahminlerde toplu iş kullanmıyoruz).

Süreç (Eğitilecek Bellek)

  1. Tek bir görüntü üzerinde çalışmak için gereken belleği hesaplayın
  2. Bu sayıyı toplu işinizdeki resim sayısıyla çarpın

( UNUTMAYIN: Mini-gruplama, verilerimizin bir alt kümesini aldığımızı, alt kümedeki her resim için degradeleri ve hataları hesapladığımızı, daha sonra bunları ortalayıp ortalamanın yönünde adım attığımızı söylüyor. etkinleştirme sayısı, toplu işteki görüntü sayısı ile çarpılır. ).

ADIM 1: 1 Görüntü için Bellek

Bir görüntüyü eğitmek için aşağıdakiler için bellek ayırmalısınız:

  • Model Parametreleri:

    Ağırlıklar ve önyargılar her bir katman, bunların en gradyanlar ve bunların ivme değişkenleri (Adam, Adagrad, RMSProp vb optimize kullanılırsa)

    Bunun için belleği yaklaşık olarak tahmin etmek için, ağırlıkları ve önyargıları saklamak için gereken belleği hesaplayın ve bunu 3 ile çarpın (yani "3 ile") çünkü ağırlıkları ve önyargıları saklamak için gereken bellek miktarının (kabaca) eşit olduğunu söylüyoruz. degradeler ve momentum değişkenleri için gerekli olanlar)

    DENKLEMLER:

    konvolusyonları:

    ağırlıklar (n) = derinlik (n) * (kernel_width * kernel_height) * derinlik (n-1)

    önyargı (n) = derinlik (n)

    Tam Bağlı (Yoğun) Katmanlar:

    ağırlıklar (n) = çıkışlar (n) * girişler (n)

    önyargı (n) = çıktılar (n)

burada n , geçerli katman ve n-1 , bir önceki katmandır ve çıkışlar , FC katmanındaki çıkışların sayısıdır ve girişler , FC katmanına giriş sayısıdır (eğer önceki katman tam bağlı bir katman değilse, giriş sayısı düzleştirilmiş katmanın boyutuna eşittir).

NOT: Yalnızca ağırlık ve önyargıların hafızası, ayrıca bir görüntü için aktivasyon hafızası (aşağıya bakınız), tahminler için ihtiyacınız olan toplam hafıza miktarıdır (kıvrımlar ve diğer bazı şeyler için hafıza için bazı ek yükler hariç).

  • Aktivasyonlar (bunlar Caffe'deki "Lekeler" dir):

(Terimleri burada gevşekçe kullanıyorum, yanımda ol)

Bir evrişim katmanındaki her evrişim " görüntüdeki piksel sayısı " aktivasyonlarını (yani bir resmi tek bir evrişimden geçirirseniz, " m " aktivasyonlarından oluşan tek bir özellik haritası alırsınız , burada " m " ", görüntü / giriş).

Tamamen bağlı katmanlar için, ürettiğiniz aktivasyon sayısı çıktınızın boyutuna eşittir.

konvolusyonları:

aktivasyonlar (n) = image_width * image_height * image_num_channels

Tam Bağlı (Yoğun) Katmanlar:

aktivasyonlar (n) = çıkışlar (n)

Girişinizin gerçekten yalnızca ağın başlangıcındaki bir resim olduğunu unutmayın. Kıvrımlardan sonra, başka bir şeye dönüşür (özellik haritaları). Bu nedenle, daha kesin olması için "image_width", "image_height" ve "image_num_channels" ifadelerini "input_width", "input_height" ve "layer_depth" ile değiştirin. (Bu konsepti görüntüler açısından düşünmek benim için daha kolay.)

Ayrıca her katmandaki (geri geçişte kullanılan) etkinleştirme hatasını da depolamamız gerektiğinden, depolama alanımızda yer açmamız gereken toplam varlık sayısını elde etmek için etkinleştirme sayısını 2 ile çarpıyoruz. Etkinleştirme sayısı, toplu işteki görüntü sayısı ile artar, bu nedenle bu sayıyı toplu iş boyutu ile çarparsınız.

2.ADIM: Toplu Eğitim için Bellek

Ağırlık ve önyargı sayısını (3 kez) ve aktivasyon sayısını (seri boyutunun 2 katı) toplayın. Bunu 4 ile çarpın ve toplu işi eğitmek için gerekli bayt sayısını elde edin. GB olarak cevap almak için 1024 ^ 2'ye bölebilirsiniz.


Neden "tahminde toplu kullanmıyoruz" dersiniz? Bir kullanıcının çok sayıda görüntü üzerinde tahminlerde bulunması gerekiyorsa, toplu işlerde tahminlerde kullanmak mantıklı olabilir.
user3731622

1

Alternatif olarak, programınız tarafından bellek ve CPU kullanımını analiz etmek için herhangi bir profil kitaplığı kullanabileceğinizi düşünüyorum. Milisaniye aralıklarında belirli bir iş parçacığı veya işlemle bellek ve CPU kullanımının anlık görüntüsünü veren birçok python kütüphanesi vardır.

Programınızın izlemek istediğiniz bölümünü popen kullanarak farklı bir alt işlemde çalıştırabilir ve PID kullanarak belleğini ve CPU kullanımını izleyebilirsiniz.

psutil böyle işler için iyi buluyorum. Gerçi başkaları da var.

Umarım bu yardımcı olacak.


3
Cevabınız için teşekkürler, @Anwar. Deneysel bir gözlemden ziyade analitik bir hesaplama arıyorum.
barbolo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.