Próbuję obliczyć ilość pamięci potrzebną GPU do trenowania mojego modelu na podstawie tych notatek Andreja Karphaty'ego: http://cs231n.github.io/convolutional-networks/#computational-considerations
Moja sieć ma 532,752 aktywacji i 19 027 984 parametrów (wag i odchyleń). Są to 32-bitowe wartości zmiennoprzecinkowe, więc każdy zajmuje 4 bajty pamięci.
Mój obraz wejściowy to 180 x 50 x 1 (szerokość x wysokość x głębokość) = 9 000 wartości zmiennoprzecinkowych 32. Nie używam augmentacji obrazu, więc myślę, że różnorodna pamięć byłaby związana tylko z rozmiarem mini-partii. Używam mini-partii wielkości 128 obrazów.
Na podstawie rekomendacji Andreja otrzymuję następujące rozmiary pamięci:
Aktywacje: 532,752 * 4 / (1024 ^ 2) = 2,03 MB
Parametry: 19,072,984 * 4 / (1024 ^ 2) * 3 = 218,27 MB
Różne: 128 * 9 000 * 4 / (1024 ^ 2) = 4,39 MB
Całkowita pamięć do wyszkolenia tej sieci wynosiłaby 224,69 MB .
Używam TensorFlow i myślę, że coś mi umknęło. Nie prowadziłem jeszcze szkolenia, ale jestem całkiem pewien (w oparciu o wcześniejsze doświadczenia), że używana pamięć będzie znacznie wyższa niż to, co obliczyłem.
Jeśli dla każdego obrazu w mini-partii TensorFlow zachowuje swoje gradienty, aby móc je później znormalizować dla pojedynczego kroku aktualizacji wag / odchyleń, myślę, że pamięć powinna wziąć pod uwagę kolejne 532,752 * 128 wartości (gradienty dla każdego obrazu w mini-partia). W takim przypadku potrzebowałbym więcej 260,13 MB, aby wyszkolić ten model ze 128 obrazami / mini-partią.
Czy możesz mi pomóc zrozumieć kwestie związane z pamięcią podczas szkolenia mojego modelu głębokiego uczenia się? Czy powyższe rozważania są prawidłowe?
źródło
Odpowiedzi:
Myślę, że jesteś na dobrej drodze.
Tak, będziesz musiał przechowywać pochodne aktywacji i parametry dla wstecznej propagacji.
Ponadto wybór optymalizacji może mieć znaczenie. Czy trenujesz używając SGD, Adama lub Adagrada? Wszystkie będą miały różne wymagania dotyczące pamięci. Na przykład będziesz musiał przechowywać pamięć podręczną wielkości kroku dla metody opartej na pędzie, chociaż powinno to być drugorzędne w porównaniu z innymi rozważanymi kwestiami pamięci.
Podsumowując, wydaje się, że obliczyłeś wymagania dotyczące pamięci dla przejścia do przodu. Andrej Karpathy wspomina, że przejście do tyłu może zająć nawet trzykrotnie więcej pamięci niż przejście do przodu, więc może to być powód, dla którego widzisz taką różnicę (przewiń w dół do „Case Studies” na stronie, aby zobaczyć przykład dla VGGNet).
źródło
@StatsSorceress TL; DR:
Przechodzę przez tę aktywność, aby sprawdzić, czy mogę samodzielnie obliczyć wymaganą pamięć:
Aktywacje: 532,752 * 2 * 4 / (1024 ^ 2) = 4,06 MB
Parametry: 19,072,984 * 4 / (1024 ^ 2) * 3 = 218,27 MB
Różne: 128 * 9 000 * 4 / (1024 ^ 2) = 4,39 MB
Całkowita pamięć: (4,06 * 128 ) + 218,27 + 4,39 = 742,34 MB
( Ktoś, proszę, popraw mnie, jeśli się mylę. FYI, już pomnożyłeś różne przez 128, więc dlatego nie pomnożyłem tego przez 128 powyżej )
Chciałbym wskazać ci ten artykuł i odpowiedni film . Pomogli mi zrozumieć, co się dzieje znacznie lepiej.
UWAGA: Pamięć wymagana do korzystania z sieci do prognoz jest znacznie mniejsza niż pamięć wymagana do szkolenia z dwóch powodów:
Proces (od pamięci do pociągu)
( PAMIĘTAJ: Mini-wsadowe mówi, że bierzemy podzbiór naszych danych, obliczamy gradienty i błędy dla każdego obrazu w tym podzbiorze, następnie uśredniamy je i idziemy w kierunku średniej. W przypadku sieci konwergentnych wagi i tendencje są wspólne, ale liczba aktywacji jest pomnożona przez liczbę obrazów w partii ).
KROK 1: Pamięć dla 1 obrazu
Aby trenować jeden obraz, musisz zarezerwować pamięć dla:
Parametry modelu:
Te ciężary i napina w każdej warstwie, ich nachylenia , a ich zmienne pędu (jeśli Adam Adagrad, RMSProp itp pozycjonujące służą)
Aby oszacować pamięć w tym celu, oblicz pamięć wymaganą do przechowywania wag i odchyleń i pomnóż ją przez 3 (tj. „Przez 3”, ponieważ mówimy, że ilość pamięci potrzebnej do przechowywania wag i odchyleń jest (z grubsza) równa potrzebne do gradientów i zmiennych pędu)
RÓWNANIA:
Zwoje:
wagi (n) = głębokość (n) * (szerokość jądra * wysokość jądra) * głębokość (n-1)
odchylenia (n) = głębokość (n)
W pełni połączone (gęste) warstwy:
wagi (n) = wyjścia (n) * wejścia (n)
odchylenia (n) = wyjścia (n)
gdzie n to bieżąca warstwa, a n-1 to poprzednia warstwa, a dane wyjściowe to liczba wyników z warstwy FC, a dane wejściowe to liczba danych wejściowych do warstwy FC (jeśli poprzednia warstwa nie jest w pełni połączoną warstwą, liczba wejść jest równa wielkości tej spłaszczonej warstwy).
UWAGA: Pamięć samych wag i odchyleń, a także pamięć dla aktywacji jednego obrazu (patrz poniżej), jest całkowitą ilością pamięci potrzebną do przewidywania (z wyłączeniem pewnego obciążenia na pamięć dla zwojów i niektórych innych rzeczy).
(Używam tu swobodnie terminów, nie przejmuj się)
Każdy splot w warstwie splotu powoduje aktywację „ liczby pikseli w obrazie ” (tzn. Przekazujesz obraz przez pojedynczy splot, otrzymujesz pojedynczą mapę funkcji składającą się z aktywacji „ m ”, gdzie „ m ” jest liczbą pikseli z twojego obraz / wejście).
W przypadku w pełni połączonych warstw liczba wygenerowanych aktywacji jest równa wielkości wydruków.
Zwoje:
aktywacje (n) = image_width * image_height * image_num_channels
W pełni połączone (gęste) warstwy:
aktywacje (n) = wyjścia (n)
Zauważ, że twój wkład jest tak naprawdę tylko obrazem na początku sieci. Po splotach zamienia się w coś innego (mapy obiektów). Więc naprawdę zastąp „image_width”, „image_height” i „image_num_channels” na „input_width”, „input_height” i „layer_depth”. (Po prostu łatwiej mi myśleć o tej koncepcji w kategoriach obrazów.)
Ponieważ musimy również przechowywać błąd aktywacji na każdej warstwie (używany w przebiegu wstecznym), mnożymy liczbę aktywacji przez 2, aby uzyskać całkowitą liczbę jednostek, dla których musimy zrobić miejsce w naszej pamięci. Liczba aktywacji wzrasta wraz z liczbą obrazów w partii, więc pomnóż tę liczbę przez rozmiar partii.
KROK 2: Memory to Train Batch
Zsumuj liczbę wag i odchyleń (razy 3) i liczbę aktywacji (razy 2 razy wielkość partii). Pomnóż to przez 4, a otrzymasz liczbę bajtów wymaganych do wyszkolenia partii. Możesz podzielić przez 1024 ^ 2, aby uzyskać odpowiedź w GB.
źródło
Alternatywnie, myślę, że możesz użyć dowolnej biblioteki profilera do analizy wykorzystania pamięci i procesora przez twój program. Istnieje wiele bibliotek Pythona, które mogą zapewniać migawkę użycia pamięci i procesora przez określony wątek lub proces w odstępie milisekundowym.
Możesz uruchomić część programu, którą chcesz monitorować w innym podprocesie, używając popen i monitorować jego pamięć i użycie procesora za pomocą PID.
psutil Uważam, że dobrze nadaje się do takiej pracy. Chociaż istnieje wiele innych.
Mam nadzieję, że to pomoże.
źródło