为什么 CNN 运行 in python 与 Matlab 相比非常慢?

Why CNN running in python is extremely slow in comparison to Matlab?

我在 Matlab 2019b 中训练了一个 CNN,可以对三个 类 之间的图像进行分类。当此 CNN 在 Matlab 中进行测试时,它运行良好,只需 10-15 秒即可对图像进行分类。我在 Maltab 中使用了 exportONNXNetwork 函数,这样我就可以在 Tensorflow 中实现我的 CNN。这是我用来在 python:

中使用 ONNX 文件的代码
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) 

当尝试使用此代码对同一测试集进行分类时,它似乎正确地对图像进行了分类,但它非常慢并且在某些时候达到高达 95+% 的高内存使用率时冻结了我的计算机.

我在分类时也注意到命令提示符中打印了这个:

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.

有什么方法可以使这个 python 代码分类更快?

也许您可以尝试通过这种方式了解代码的哪一部分需要很长时间:

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) 

让我知道输出是什么样的:)

在使用 Python 处理 TensorFlow 时,您应该考虑一些要点。 GPU 会更适合工作,因为它可以加快整个处理过程。为此,您必须安装 CUDA 支持。除此之外,编译器有时也很重要。根据我的经验,我可以说 VSCode 比 Spyder 更好。

希望对您有所帮助。

由于命令提示符指出您的程序需要很长时间来执行常量折叠,因此关闭它可能是值得的。 Based on this documentation,你可以试试 运行:

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)

这将禁用在 TensorFlow Graph 优化中执行的常量折叠。这可以双向工作:一方面它不会达到常量折叠截止日期,但另一方面禁用常量折叠会导致运行时间显着增加。总之值得一试,祝你好运!

在这种情况下,Grapper optimization suite has encountered some kind of infinite loop or memory leak. I would recommend filing an issue against the Github repo

调试为什么常量折叠需要这么长时间是一项挑战,但与 TensorFlow 后端相比,使用 ONNX TensorRT backend 可能会获得更好的性能。与 Nvidia GPU 上的 TensorFlow 后端相比,它实现了更好的性能,同时更快地编译典型图形。常量折叠通常不会为优化良好的模型提供较大的加速。

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)