Por que o treinamento leva tanto tempo na minha GPU?

10

Detalhes:

GPU : GTX 1080

Treinamento : ~ 1,1 milhão de imagens pertencentes a 10 classes

Validação : ~ 150 mil imagens pertencentes a 10 classes

Tempo por época : ~ 10 horas

Eu configurei CUDA, cuDNN e Tensorflow (GPU Tensorflow também).

Eu não acho que meu modelo é tão complicado que leva 10 horas por época. Até chequei se minha GPU era o problema, mas não era.

O tempo de treinamento é devido às camadas totalmente conectadas?

Meu modelo:

model = Sequential()
model.add()
model.add(Conv2D(64, (3, 3), padding="same", strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding="same", strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(3, 3), strides=2))
model.add(Flatten())
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dense(4096))
model.add(Activation('relu'))
model.add(Dense(10))
model.add(Activation('softmax'))

model.summary()

opt = keras.optimizers.rmsprop(lr=0.0001, decay=1e-6)

model.compile(loss='categorical_crossentropy',
          optimizer=opt,
          metrics=['accuracy']
          )

Como existem muitos dados, usei o ImageDataGenerator.

gen = ImageDataGenerator(
 horizontal_flip=True
)

train_gen = gen.flow_from_directory(
        'train/',
        target_size=(512, 512),
        batch_size=5,
        class_mode="categorical"
)

valid_gen = gen.flow_from_directory(
        'validation/',
        target_size=(512, 512),
        batch_size=5,
        class_mode="categorical"
)
Pradyumna Rahul
fonte
2
Eu votei para mover este para estouro de pilha, mas realmente pertence na troca pilha de ciência de dados, IMO
generic_user
generic_user: "ciência de dados" pode usar "aprendizado de máquina", mas nem todo "aprendizado de máquina" é para "ciência de dados". (ML é apenas mais uma ferramenta, tensorflow apenas outra biblioteca; ML pode em breve (se já não estiver) ser usado até mesmo para as tarefas rotineiras como o gerenciamento de arquivos de propriedade de preferência do usuário.)
michael
ver também relacionada (tl; dr: verificar realmente em execução no gpu, olhada estatísticas GPU que tf pode fornecer) stackoverflow.com/questions/42527492/... stackoverflow.com/questions/38559755/...
michael
Eu tentei essa abordagem e afirma que minha GPU atual está sendo usada. Para confirmar, também usei a nvidia-smi para verificar a utilização da GPU e ela varia entre 85% e 99%.
Pradyumna Rahul

Respostas:

7

Isso é o esperado. Se você dividir o número de segundos pelo número de imagens processadas, obterá 33 milissegundos por imagem, o que parece adequado para uma rede tão pequena. Redes maiores costumam ter uma estimativa de 50 a 200 milissegundos por imagem.

Sim, é provável que uma grande camada densa prejudique seu desempenho, pois é uma matriz enorme (256 por 4096) e uma grande multiplicação de matrizes para acompanhar toda vez que você executa a rede.

shimao
fonte
O que você sugeriria para melhorar o desempenho?
4
1: aumente o tamanho do lote para 32 ou 64. 2: reduza o tamanho da camada FC para talvez 1024 ou 2048 unidades e veja se isso ajuda. 3: Parada antecipada. É possível que sua rede tenha convergido ou começado a se ajustar demais antes de você terminar sua primeira época; nesse caso, você deve treinar menos.
Devo reduzir as etapas por época?
Pradyumna Rahul
@shimao o que você quis dizer com "treinar menos"? Você quer dizer usar menos dados?
StatsSorceress
3

Como o shimao disse, é sobre o que você esperaria. Apesar de não ter muitas camadas, um tamanho de entrada de 512x512 é uma imagem grande para convolução. O grande tempo de computação provavelmente é mais devido à convolução de 64 filtros sobre a imagem grande, em vez das camadas totalmente conectadas.

A rede que você montou possui um gargalo de informações engraçadas. Você começa com 64 filtros na imagem em tamanho original, diminuindo apenas à medida que o tamanho da imagem diminui. À medida que a imagem passa pela sua rede, os recursos que você está aprendendo se tornam mais e mais abstratos e complexos. Sua camada Conv2D (32, (3, 3)) limita essencialmente a rede a aprender um mapa de 128 recursos de 128x128.

A maioria das arquiteturas de rede duplica o número de recursos toda vez que agrupa, e as arquiteturas mais recentes da imagenet descartam as camadas totalmente conectadas em favor de um pool médio sobre o mapa final de recursos e basicamente executam a regressão logística na saída desse pool.

Tente começar com menos filtros, digamos 16 na sua primeira camada de convolução, dobrando cada vez que você caminha ou faz pool. Faça isso mais algumas vezes do que você é, para aumentar o campo receptivo e diminuir o tamanho do mapa de recursos. Faça isso até 64x64 ou 32x32, que seriam 128 ou 256 filtros. Você pode usar o pool Global Avg ou Max da Keras para eliminar também as camadas totalmente conectadas. Isso deve dobrar a velocidade da rede, e eu esperaria um aumento na precisão ao mesmo tempo.

mpotma
fonte
Bem, a arquitetura de rede é baseada em um trabalho de pesquisa que eu estava tentando reproduzir. lirmm.fr/%7Echaumont/publications/…
Pradyumna Rahul