El modelo convertido de OpenVino no devuelve los mismos valores de pun

El modelo convertido de OpenVino no devuelve los mismos valores de puntuación que el modelo original (Sigmoid)

He convertido un modelo de Keras para usarlo con OpenVino. El modelo Keras original usaba sigmoide para devolver puntajes que iban de 0 a 1 para la clasificación binaria. Después de convertir el modelo para su uso con OpenVino, los puntajes están todos cerca de 0,99 para ambas clases, pero parecen ligeramente más bajos para una de las clases.

Por ejemplo, test1.jpg y test2.jpg (de clases opuestas) arrojan puntuaciones de 0,00320357 y 0,9999, respectivamente.

Con OpenVino, las mismas imágenes arrojan puntuaciones de 0,9998982 y 0,9962392, respectivamente.

Editar* Una sospecha es que el modelo de OpenVino todavía acepta la matriz de entrada, pero de alguna manera cambia de forma o está "codificado" y, por lo tanto, nunca es compatible con la clase uno. En otras palabras, si lo alimentara con ruido aleatorio, la puntuación también sería siempre 0,9999. ¿Tal vez tendría que hacer que el modelo OpenVino aceptara la forma original (1,180,180,3) en lugar de (1,3,180,180) para no tener que forzar la entrada en una forma diferente a la que aceptó el modelo original? Sin embargo, eso es extraño porque especifiqué la forma al crear el xml y el contenedor para openvino:

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]

Sin embargo, sé por mensajes de error que el motor de inferencia espera (1,3,180,180) por alguna razón desconocida. ¿Podría ser el problema? La otra sospecha es que algo anda mal con la forma en que se congeló el modelo original. Estoy explorando diferentes formas de congelar el modelo original (modelo keras convertido a pb) en caso de que el problema esté relacionado con eso.

Revisé para asegurarme de que la función de activación de Sigmoid se usa en la implementación de OpenVino (la misma activación que el modelo de Keras) y parece que sí. ¿Por qué, entonces, los valores no son los mismos? Cualquier ayuda sería muy apreciada.

El código para la inferencia de OpenVino es:

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

Y el resultado:

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

Por lo general, Tensorflow es la única red con la forma NHWC, mientras que la mayoría de las demás usan NCHW. Por lo tanto, OpenVINO Inference Engine satisface la mayoría de las redes y utiliza el diseño NCHW. El modelo debe convertirse al diseño NCHW para poder trabajar con el motor de inferencia.

La conversión del formato del modelo nativo a IR implica el proceso en el que Model Optimizer realiza la transformación necesaria para convertir la forma al diseño requerido por el motor de inferencia (N,C,H,W). Usar el parámetro --input_shape con la forma de entrada correcta del modelo debería ser suficiente.

Además, la mayoría de los modelos de TensorFlow están entrenados con imágenes en orden RGB. En este caso, los resultados de la inferencia que utilizan las muestras del motor de inferencia pueden ser incorrectos. De manera predeterminada, las muestras y demostraciones de Inference Engine esperan una entrada con el orden de los canales BGR. Si entrenó su modelo para trabajar con el orden RGB, debe reorganizar manualmente el orden de los canales predeterminados en la aplicación de muestra o demostración o reconvertir su modelo usando la herramienta Model Optimizer con --argumento de canales de entrada inversos.

Le sugiero que valide esto infiriendo su modelo con el Hello Classification Python Sample en su lugar, ya que esta es una de las muestras oficiales proporcionadas para probar la funcionalidad del modelo.

Puede consultar esta "Biblioteca Intel Math Kernel para Deep Neural Red" para obtener una explicación más detallada sobre la forma de entrada.

cambiar de RGB a BGR con im_cv = cv.imread('test2.jpg') y luego frame = cv.cvtColor(im_cv, cv.COLOR_RGB2BGR) ¡lo hizo! Gracias.