OpenVino 转换后的模型未返回与原始模型相同的分数值 (Sigmoid)

OpenVino converted model not returning same score values as original model (Sigmoid)

我已经转换了一个 Keras 模型以用于 OpenVino。原始的 Keras 模型使用 sigmoid 到 return 分数范围从 0 到 1 进行二进制 class 化。在将模型转换为与 OpenVino 一起使用后,两个 classes 的分数都接近 0.99,但其中一个 classes 的分数似乎略低。

例如,test1.jpg 和 test2.jpg(来自相反的 classes)分别产生 0.00320357 和 0.9999 的分数。

使用 OpenVino,相同的图像分别产生 0.9998982 和 0.9962392 的分数。

编辑* 一种怀疑是输入数组仍被 OpenVino 模型接受,但形状发生了某种变化或“混乱”,因此永远无法与 class 匹配?换句话说,如果你给它随机噪声,分数也总是 0.9999。也许我必须以某种方式让 OpenVino 模型接受原始形状 (1,180,180,3) 而不是 (1,3,180,180),这样我就不必强制输入与原始模型接受的形状不同的形状?不过这很奇怪,因为我在为 openvino 制作 xml 和 bin 时指定了形状:

python3 /opt/intel/openvino_2021/deployment_tools/model_optimizer/mo_tf.py --saved_model_dir /Users/.../Desktop/.../model13 --output_dir /Users/.../Desktop/... --input_shape=\[1,180,180,3]

但是,我从错误消息中知道推理引擎出于某种未知原因期望 (1,3,180,180)。这可能是问题所在吗?另一个怀疑是原始模型的冻结方式有问题。我正在探索冻结原始模型(keras 模型转换为 pb)的不同方法,以防问题与此相关。

我检查以确保在 OpenVino 实现中使用了 Sigmoid 激活函数(与 Keras 模型相同的激活)并且看起来确实如此。那么,为什么值不一样呢?任何帮助将不胜感激。

OpenVino 推理的代码是:

import openvino
from openvino.inference_engine import IECore, IENetwork 
from skimage import io
import sys
import numpy as np
import os

def loadNetwork(model_xml, model_bin):

    ie = IECore() 

    network =  ie.read_network(model=model_xml, weights=model_bin)

    input_placeholder_key = list(network.input_info)[0]
    input_placeholder = network.input_info[input_placeholder_key]

    output_placeholder_key = list(network.outputs)[0]
    output_placeholder = network.outputs[output_placeholder_key]

    return network, input_placeholder_key, output_placeholder_key

batch_size = 1
channels = 3
IMG_HEIGHT = 180
IMG_WIDTH = 180

#loadNetwork('saved_model.xml','saved_model.bin')

image_path = 'test.jpg'

def load_source(path_to_image):
    image = io.imread(path_to_image)
    img = np.resize(image,(180,180))
    return img

img_new = load_source('test2.jpg')

#Batch?

def classify(image):
    device = 'CPU'
    network, input_placeholder_key, output_placeholder_key = loadNetwork('saved_model.xml','saved_model.bin')
    ie = IECore() 
    exec_net = ie.load_network(network=network, device_name=device)
    res = exec_net.infer(inputs={input_placeholder_key: image})
    print(res)
    res = res[output_placeholder_key]
    return res

result = classify(img_new)
print(result)
result = result[0]
top_result = np.argmax(result)
print(top_result)
print(result[top_result])

结果:

{'StatefulPartitionedCall/model/dense/Sigmoid': array([[0.9962392]], dtype=float32)}
[[0.9962392]]
0
0.9962392

通常,Tensorflow 是唯一具有 NHWC 形状的网络,而大多数其他网络使用 NCHW。因此,OpenVINO 推理引擎满足大多数网络并使用 NCHW 布局。必须将模型转换为 NCHW 布局才能使用推理引擎。

将原生模型格式转换为 IR 涉及模型优化器执行必要的转换以将形状转换为推理引擎所需的布局(N、C、H、W)的过程。使用具有模型正确输入形状的 --input_shape 参数就足够了。

此外,大多数 TensorFlow 模型都是使用 RGB 顺序的图像进行训练的。在这种情况下,使用推理引擎样本的推理结果可能不正确。默认情况下,推理引擎示例和演示需要使用 BGR 通道顺序的输入。如果您训练模型使用 RGB 顺序,则需要在示例或演示应用程序中手动重新排列默认通道顺序,或者使用带有 --reverse_input_channels argument.

的模型优化器工具重新转换您的模型

我建议您通过使用 Hello Classification Python Sample 推断您的模型来验证这一点,因为这是为测试模型功能而提供的官方示例之一。

您可以参考这个“Intel Math Kernel Library for Deep Neural Network”以获得关于输入形状的更深入的解释。