Estou tentando calcular a quantidade de memória necessária para uma GPU treinar meu modelo com base nas notas de Andrej Karphaty: http://cs231n.github.io/convolutional-networks/#computational-considerations
Minha rede possui 532.752 ativações e 19.072.984 parâmetros (pesos e vieses). Esses são todos os valores flutuantes de 32 bits; portanto, cada um deles ocupa 4 bytes de memória.
Minha imagem de entrada é 180x50x1 (largura x altura x profundidade) = 9.000 valores flutuantes 32. Como não uso aumento de imagem, acho que a memória diversa estaria relacionada apenas ao tamanho do minilote. Estou usando um tamanho de mini lote de 128 imagens.
Com base na recomendação de Andrej, recebo os seguintes tamanhos de memória:
Ativações: 532.752 * 4 / (1024 ^ 2) = 2,03 MB
Parâmetros: 19,072,984 * 4 / (1024 ^ 2) * 3 = 218,27 MB
Diversos: 128 * 9.000 * 4 / (1024 ^ 2) = 4,39 MB
Portanto, a memória total para treinar essa rede seria 224,69 MB .
Estou usando o TensorFlow e acho que estou perdendo alguma coisa. Ainda não realizei o treinamento, mas tenho certeza (com base em experiências anteriores) que a memória em uso será muito maior do que eu calculei.
Se para cada imagem no minilote, o TensorFlow mantém seus gradientes para normalizá-los posteriormente para uma única etapa de atualização de pesos / desvios, acho que a memória deve levar em consideração outros 532.752 * 128 valores (gradientes para cada imagem no mini-lote). Se for esse o caso, eu precisaria de mais 260,13 MB para treinar este modelo com 128 imagens / mini-lote.
Você pode me ajudar a entender as considerações de memória para treinar meu modelo de aprendizado profundo? As considerações acima estão corretas?
fonte
Respostas:
Eu acho que você está no caminho certo.
Sim, você precisará armazenar os derivados das ativações e dos parâmetros para retropropagação.
Além disso, sua escolha de otimização pode ser importante. Você está treinando usando SGD, Adam ou Adagrad? Todos eles terão diferentes requisitos de memória. Por exemplo, você precisará armazenar o cache do tamanho da etapa para um método baseado em momento, embora isso deva ser secundário comparado às outras considerações de memória mencionadas.
Portanto, você parece ter calculado os requisitos de memória para um passe para frente. Andrej Karpathy menciona que o passe para trás pode levar até 3x a memória do passe para frente, por isso pode ser por isso que você vê essa diferença (role para baixo até 'Estudos de caso' no site para ver um exemplo para a VGGNet).
fonte
@StatsSorceress TL; DR:
Estou passando por essa atividade para ver se consigo calcular a memória necessária:
Ativações: 532.752 * 2 * 4 / (1024 ^ 2) = 4,06 MB
Parâmetros: 19,072,984 * 4 / (1024 ^ 2) * 3 = 218,27 MB
Diversos: 128 * 9.000 * 4 / (1024 ^ 2) = 4,39 MB
Memória total: (4,06 * 128 ) + 218,27 + 4,39 = 742,34 MB
( Alguém, por favor, me corrija se estiver errado. Para sua informação, você já multiplicou por 128, por isso não o multipliquei por 128 acima )
Eu indicaria este artigo e o vídeo correspondente . Eles me ajudaram a entender o que está acontecendo muito melhor.
NOTA: A memória necessária para usar uma rede para previsões é muito menor que a necessária para o treinamento por dois motivos:
Processo (Memória a Treinar)
( LEMBRE-SE: o mini-lote diz que pegamos um subconjunto de nossos dados, calculamos os gradientes e os erros de cada imagem no subconjunto, calculamos a média e avançamos na direção da média. Para convnets, pesos e preconceitos são compartilhados, mas o número de ativações é multiplicado pelo número de imagens no lote. ).
PASSO 1: Memória para 1 imagem
Para treinar uma imagem, você deve reservar memória para:
Parâmetros do modelo:
Os pesos e desvios em cada camada, seus gradientes e suas variáveis de momento (se forem utilizados otimizadores Adam, Adagrad, RMSProp etc., otimizadores)
Para aproximar a memória, calcule a memória necessária para armazenar os pesos e desvios e multiplique por 3 (ou seja, "por 3" porque estamos dizendo que a quantidade de memória necessária para armazenar os pesos e desvios é (aproximadamente) igual a necessário para os gradientes e para as variáveis de momento)
EQUAÇÕES:
Convoluções:
pesos (n) = profundidade (n) * (largura do kernel * altura do kernel) * profundidade (n-1)
vieses (n) = profundidade (n)
Camadas (densas) totalmente conectadas:
pesos (n) = saídas (n) * entradas (n)
vieses (n) = saídas (n)
onde n é a camada atual e n-1 é a camada anterior, e saídas são o número de saídas da camada FC e entradas são o número de entradas para a camada FC (se a camada anterior não for uma camada totalmente conectada, o número de entradas é igual ao tamanho dessa camada achatada).
OBSERVAÇÃO: A memória apenas para pesos e preconceitos, além da memória para as ativações de uma imagem (veja abaixo), é a quantidade total de memória necessária para previsões (excluindo algumas despesas gerais de memória para convoluções e outras coisas).
(Estou usando termos vagos aqui, tenha paciência comigo)
Cada convolução em uma camada de convolução produz ativações de " número de pixels na imagem " (ou seja, você passa uma imagem através de uma única convolução, obtém um único mapa de recursos que consiste em ativações " m ", em que " m " é o número de pixels da sua imagem / entrada).
Para camadas totalmente conectadas, o número de ativações produzidas é igual ao tamanho da sua saída.
Convoluções:
ativações (n) = largura_imagem * altura_imagem * número_imagem_canais
Camadas (densas) totalmente conectadas:
ativações (n) = saídas (n)
Observe que sua entrada é realmente apenas uma imagem no início da rede. Após as convoluções, ele se transforma em outra coisa (mapas de recursos). Então, substitua "largura_de_imagem", "altura_de_imagem" e "número_de_imagem" por "largura_de_ entrada", "altura_de entrada" e "profundidade_cama" para ser mais preciso. (É mais fácil para mim pensar nesse conceito em termos de imagens.)
Como também precisamos armazenar o erro para as ativações em cada camada (usada na passagem para trás), multiplicamos o número de ativações por 2 para obter o número total de entidades que precisamos abrir espaço em nosso espaço de armazenamento. O número de ativações aumenta com o número de imagens no lote, portanto você multiplica esse número pelo tamanho do lote.
PASSO 2: Memória para Treinar Lote
Soma o número de pesos e desvios (vezes 3) e o número de ativações (vezes 2 vezes o tamanho do lote). Multiplique isso por 4 e você obterá o número de bytes necessários para treinar o lote. Você pode dividir por 1024 ^ 2 para obter a resposta em GB.
fonte
Como alternativa, acho que você pode usar qualquer biblioteca de criação de perfil para analisar o uso de memória e CPU pelo seu programa. Existem muitas bibliotecas python que podem fornecer instantâneos do uso da memória e da CPU por segmento ou processo específico em um intervalo de milissegundos.
Você pode executar a parte do seu programa que deseja monitorar em um subprocesso diferente usando o popen e monitorar sua memória e uso da CPU usando seu PID.
psutil acho bom para esse trabalho. Embora existam muitos outros.
Espero que isso ajude.
fonte