7
votes

Pourquoi CNN s'exécutant en python est-il extrêmement lent par rapport à Matlab?

J'ai formé un CNN à Matlab 2019b qui classe les images entre trois classes. Lorsque ce CNN a été testé dans Matlab, il fonctionnait bien et ne prenait que 10 à 15 secondes pour classer une image. J'ai utilisé la fonction exportONNXNetwork dans Maltab afin de pouvoir implémenter mon CNN dans Tensorflow. Voici le code que j'utilise pour utiliser le fichier ONNX en python:

2020-04-18 18:26:39.214286: W tensorflow/core/grappler/optimizers/meta_optimizer.cc:530] constant_folding failed: Deadline exceeded: constant_folding exceeded deadline., time = 486776.938ms.

Lorsque vous essayez d'utiliser ce code pour classer le même ensemble de test, il semble classer correctement les images, mais il est très lent et gèle mon ordinateur car il atteint des utilisations de mémoire élevées allant jusqu'à 95 +% à certains moments.

J'ai également remarqué dans l'invite de commande lors de la classification, il imprime ceci:

import onnx
from onnx_tf.backend import prepare 
import numpy as np
from PIL import Image 

onnx_model = onnx.load('trainednet.onnx')
tf_rep = prepare(onnx_model)
filepath = 'filepath.png' 

img = Image.open(filepath).resize((224,224)).convert("RGB") 
img = array(img).transpose((2,0,1))
img = np.expand_dims(img, 0) 
img = img.astype(np.uint8) 

probabilities = tf_rep.run(img) 
print(probabilities) 

Existe-t-il un moyen de rendre ce code python plus rapide?


6 commentaires

Je vous recommande de vérifier d'abord quelques points: 1. utilisez-vous votre GPU avec python et Matlab? 2. Qu'est-ce qui prend 15sec (Matlab) ou plus (python), est-ce la classification elle-même ou le chargement du modèle et la manipulation d'image? 3. Quand la mémoire est-elle pleine, après le chargement d'une image? De plus, quel système d'exploitation utilisez-vous?


Avez-vous essayé d'exécuter un profileur pour voir où se trouve votre goulot d'étranglement? Voir docs.python.org/3/library/profile.html#module-cProfile et toucantoco.com/en/tech-blog/tech/…


"La meilleure façon de rendre python plus rapide est d'en utiliser moins"


Matlab est un produit exclusif et vaut son prix


Pouvez-vous publier le code matlab?


Vous ne devez pas charger toutes les images en même temps! chaque image chargée est de type int , mais pour un apprentissage plus rapide, vous devez la mettre à l'échelle à <0, 1> qui est évidemment float32 ou 64, et elles consomment beaucoup plus de mémoire. Veuillez réduire la charge d'image: P, vous pouvez utiliser numpy pour convertir les images en float16, ce qui aura moins de précision, mais aussi moins de consommation de mémoire new_img = np.array(img, dtype=np.float16)


4 Réponses :


2
votes

Vous pourriez peut-être essayer de comprendre quelle partie du code prend du temps de cette façon:

import onnx
from onnx_tf.backend import prepare 
import numpy as np
from PIL import Image 
import datetime

now = datetime.datetime.now()
onnx_model = onnx.load('trainednet.onnx')
tf_rep = prepare(onnx_model)
filepath = 'filepath.png' 
later = datetime.datetime.now()
difference = later - now
print("Loading time : %f ms" % (difference.microseconds / 1000))

img = Image.open(filepath).resize((224,224)).convert("RGB") 
img = array(img).transpose((2,0,1))
img = np.expand_dims(img, 0) 
img = img.astype(np.uint8) 

now = datetime.datetime.now()
probabilities = tf_rep.run(img) 
later = datetime.datetime.now()
difference = later - now
print("Prediction time : %f ms" % (difference.microseconds / 1000))
print(probabilities) 

Faites-moi savoir à quoi ressemble la sortie :)


0 commentaires

0
votes

Vous devez tenir compte de certains points lorsque vous travaillez sur TensorFlow avec Python. Un GPU sera meilleur pour le travail car il accélère l'ensemble du traitement. Pour cela, vous devez installer le support CUDA. En dehors de cela, le compilateur compte aussi parfois. Je peux dire que VSCode est meilleur que Spyder d'après mon expérience.

J'espère que cela aide.


0 commentaires

0
votes

Étant donné que l'invite de commande indique que votre programme prend beaucoup de temps pour effectuer un repliement constant, il peut être utile de désactiver cette option. Sur la base de cette documentation , vous pouvez essayer d'exécuter:

import numpy as np
import timeit
import traceback
import contextlib
import onnx
from onnx_tf.backend import prepare 
from PIL import Image 
import tensorflow as tf

@contextlib.contextmanager
def options(options):
  old_opts = tf.config.optimizer.get_experimental_options()
  tf.config.optimizer.set_experimental_options(options)
  try:
    yield
  finally:
    tf.config.optimizer.set_experimental_options(old_opts)


with options({'constant_folding': False}):

  onnx_model = onnx.load('trainednet.onnx')
  tf_rep - prepare(onnx_model)
  filepath = 'filepath.png' 

  img = Image.open(filepath).resize((224,224)).convert("RGB") 
  img = array(img).transpose((2,0,1))
  img = np.expand_dims(img, 0) 
  img = img.astype(np.uint8) 

  probabilities = tf_rep.run(img)
  print(probabilities)

Cela désactive le pliage constant effectué dans l'optimisation du graphe TensorFlow. Cela peut fonctionner dans les deux sens: d'une part, il n'atteindra pas le délai de pliage constant, mais d'autre part, la désactivation du pliage constant peut entraîner des augmentations significatives du temps d'exécution. Quoi qu'il en soit, cela vaut la peine d'essayer, bonne chance!


0 commentaires

2
votes

Dans ce cas, il semble que la suite d'optimisation Grapper ait rencontré une sorte de boucle infinie ou de fuite de mémoire. Je recommanderais de déposer un problème contre le repo Github .

Il est difficile de déboguer pourquoi le pliage constant prend si longtemps, mais vous pouvez avoir de meilleures performances en utilisant le backend ONNX TensorRT par rapport au backend TensorFlow. Il atteint de meilleures performances par rapport au backend TensorFlow sur les GPU Nvidia tout en compilant plus rapidement des graphiques typiques. Le pliage constant ne fournit généralement pas de grandes accélérations pour les modèles bien optimisés.

import onnx
import onnx_tensorrt.backend as backend
import numpy as np

model = onnx.load("trainednet.onnx'")
engine = backend.prepare(model, device='CUDA:1')

filepath = 'filepath.png' 

img = Image.open(filepath).resize((224,224)).convert("RGB") 
img = array(img).transpose((2,0,1))
img = np.expand_dims(img, 0) 
img = img.astype(np.uint8) 
output_data = engine.run(img)[0]
print(output_data)


0 commentaires