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?
4 Réponses :
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 :)
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.
É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!
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)
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émoirenew_img = np.array(img, dtype=np.float16)