Pourquoi la formation prend-elle autant de temps sur mon GPU?


10

Détails:

GPU : GTX 1080

Formation : ~ 1,1 million d'images appartenant à 10 classes

Validation : ~ 150 mille images appartenant à 10 classes

Temps par époque : ~ 10 heures

J'ai configuré CUDA, cuDNN et Tensorflow (GPU Tensorflow également).

Je ne pense pas que mon modèle soit si compliqué que cela prenne 10 heures par époque. J'ai même vérifié si mon GPU était le problème, mais ce n'était pas le cas.

Le temps de formation est-il dû aux couches entièrement connectées?

Mon modele:

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']
          )

Parce qu'il y a beaucoup de données, j'ai utilisé 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"
)

2
J'ai voté pour le déplacer vers le débordement de pile, mais cela appartient vraiment à l'échange de pile de science des données, IMO
generic_user

generic_user: "data science" peut utiliser "machine learning", mais tous les "machine learning" ne sont pas destinés à "data science". (ML est juste un autre outil, tensorflow juste une autre bibliothèque; ML pourrait bientôt (sinon déjà) être utilisé même pour les tâches banales telles que la gestion des fichiers de propriétés des préférences utilisateur.)
michael

voir aussi connexes (tl; dr: vérifier réellement en cours d'exécution sur gpu, regardez les statistiques gpu que tf peut fournir) stackoverflow.com/questions/42527492/… stackoverflow.com/questions/38559755/…
michael

J'ai essayé cette approche et il indique que mon GPU actuel est utilisé. Afin de confirmer, j'ai également utilisé nvidia-smi pour vérifier l'utilisation du GPU et il oscille entre 85% et 99%.
Pradyumna Rahul

Réponses:


7

C'est à peu près prévu. Si vous divisez le nombre de secondes par le nombre d'images que vous avez traitées, vous obtenez 33 millisecondes par image, ce qui semble correct pour un si petit réseau. Les réseaux plus importants prennent généralement environ 50 à 200 millisecondes par image.

Oui, une grande couche dense est susceptible de nuire à vos performances, car il s'agit d'une énorme matrice (256 par 4096) et d'une grande multiplication de matrice pour l'accompagner chaque fois que vous exécutez le réseau.


Que suggéreriez-vous pour améliorer les performances?

4
1: augmentez la taille du lot à 32 ou 64. 2: réduisez la taille de la couche FC à peut-être 1024 ou 2048 unités et voyez si cela aide. 3: Arrêt précoce. Il est possible que votre réseau ait convergé ou commence à sur-équiper avant de terminer votre première époque, auquel cas vous devriez vous entraîner moins.

Dois-je réduire les pas par époque?
Pradyumna Rahul

@shimao qu'entendiez-vous par "train moins"? Voulez-vous dire utiliser moins de données?
StatsSorceress

3

Comme l'a dit Shimao, c'est à quoi vous vous attendez. Bien qu'il n'y ait pas beaucoup de couches, une taille d'entrée de 512x512 est une grande image à convoluer. Le temps de calcul important est probablement plus dû à la convolution de 64 filtres sur la grande image, au lieu des couches entièrement connectées.

Le réseau que vous avez mis en place a cependant un goulot d'étranglement d'informations drôle. Vous commencez avec 64 filtres sur l'image de taille originale, ne diminuant que lorsque la taille de votre image diminue. Au fur et à mesure que l'image traverse votre réseau, les fonctionnalités que vous apprenez deviennent de plus en plus abstraites et complexes. Votre couche Conv2D (32, (3, 3)) limite essentiellement le réseau à l'apprentissage d'une carte 128x128 de 32 fonctionnalités.

La plupart des architectures de réseau doublent le nombre de fonctionnalités à chaque regroupement, et les architectures imagenet les plus récentes abandonnent les couches entièrement connectées au profit d'un pool moyen par rapport à la carte des fonctionnalités finale, et effectuent essentiellement une régression logistique sur la sortie de ce pool.

Essayez de commencer avec moins de filtres, disons 16 dans votre première couche de convolution, en doublant à chaque fois que vous foulerez ou regrouperez. Faites-le plusieurs fois de plus que vous pour augmenter le champ de réception et réduire la taille de la carte d'entités. Faites cela jusqu'à 64x64 ou 32x32, ce qui correspondrait à 128 ou 256 filtres. Vous pouvez également utiliser le pool Global Avg ou Max de Keras pour éliminer les couches entièrement connectées. Cela devrait doubler la vitesse du réseau, et je m'attends à une augmentation de la précision en même temps.


Eh bien, l'architecture du réseau est basée sur un document de recherche que j'essayais de reproduire. lirmm.fr/%7Echaumont/publications/…
Pradyumna Rahul
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.