Est-il fréquent de constater une perte de précision spectaculaire après la congélation d'un graphique pour le servir ? Lors de l'entraînement et de l'évaluation du jeu de données des fleurs à l'aide d'un inception-resnet-v2 pré-entraîné, ma précision est de 98-99%, avec une probabilité de 90+% pour les prédictions correctes. Cependant, après avoir gelé mon graphique et l'avoir prédit à nouveau, mon modèle n'est pas aussi précis et les bonnes étiquettes ne sont prédites qu'avec une confiance de 30-40%.
Après la formation sur les modèles, j'avais plusieurs éléments :
- Fichier de contrôle
- fichier model.ckpt.index
- fichier model.ckpt.meta
- fichier model.ckpt
- un fichier graph.pbtxt.
Comme je n'ai pas été en mesure d'exécuter le fichier officiel du graphique de gel qui se trouve dans la base de données de l Dépôt tensorflow sur GitHub (Je suppose que c'est parce que j'ai un fichier pbtxt et non un fichier pb après ma formation), je réutilise le code à partir de ce tutoriel à la place.
Voici le code que j'ai modifié pour figer mon graphique :
import os, argparse
import tensorflow as tf
from tensorflow.python.framework import graph_util
dir = os.path.dirname(os.path.realpath(__file__))
def freeze_graph(model_folder, input_checkpoint):
# We retrieve our checkpoint fullpath
checkpoint = tf.train.get_checkpoint_state(model_folder)
# input_checkpoint = checkpoint.model_checkpoint_path
# We precise the file fullname of our freezed graph
absolute_model_folder = "/".join(input_checkpoint.split('/')[:-1])
output_graph = absolute_model_folder + "/frozen_model.pb"
# Before exporting our graph, we need to precise what is our output node
# This is how TF decides what part of the Graph he has to keep and what part it can dump
# NOTE: this variable is plural, because you can have multiple output nodes
output_node_names = "InceptionResnetV2/Logits/Predictions"
# We clear devices to allow TensorFlow to control on which device it will load operations
clear_devices = True
# We import the meta graph and retrieve a Saver
saver = tf.train.import_meta_graph(input_checkpoint + '.meta', clear_devices=clear_devices)
# We retrieve the protobuf graph definition
graph = tf.get_default_graph()
input_graph_def = graph.as_graph_def()
# We start a session and restore the graph weights
with tf.Session() as sess:
saver.restore(sess, input_checkpoint)
# We use a built-in TF helper to export variables to constants
output_graph_def = graph_util.convert_variables_to_constants(
sess, # The session is used to retrieve the weights
input_graph_def, # The graph_def is used to retrieve the nodes
output_node_names.split(",") # The output node names are used to select the usefull nodes
)
# Finally we serialize and dump the output graph to the filesystem
with tf.gfile.GFile(output_graph, "wb") as f:
f.write(output_graph_def.SerializeToString())
print("%d ops in the final graph." % len(output_graph_def.node))
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("--model_folder", type=str, help="Model folder to export")
parser.add_argument("--input_checkpoint", type = str, help = "Input checkpoint name")
args = parser.parse_args()
freeze_graph(args.model_folder, args.input_checkpoint)
C'est le code que j'utilise pour exécuter ma prédiction, où je n'introduis qu'une seule image, comme prévu par l'utilisateur :
import tensorflow as tf
from scipy.misc import imread, imresize
import numpy as np
img = imread("./dandelion.jpg")
img = imresize(img, (299,299,3))
img = img.astype(np.float32)
img = np.expand_dims(img, 0)
labels_dict = {0:'daisy', 1:'dandelion',2:'roses', 3:'sunflowers', 4:'tulips'}
#Define the filename of the frozen graph
graph_filename = "./frozen_model.pb"
#Create a graph def object to read the graph
with tf.gfile.GFile(graph_filename, "rb") as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
#Construct the graph and import the graph from graphdef
with tf.Graph().as_default() as graph:
tf.import_graph_def(graph_def)
#We define the input and output node we will feed in
input_node = graph.get_tensor_by_name('import/batch:0')
output_node = graph.get_tensor_by_name('import/InceptionResnetV2/Logits/Predictions:0')
with tf.Session() as sess:
predictions = sess.run(output_node, feed_dict = {input_node: img})
print predictions
label_predicted = np.argmax(predictions[0])
print 'Predicted Flower:', labels_dict[label_predicted]
print 'Prediction probability:', predictions[0][label_predicted]
Et le résultat que j'ai reçu en exécutant ma prédiction :
2017-04-11 17:38:21.722217: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:901] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2017-04-11 17:38:21.722608: I tensorflow/core/common_runtime/gpu/gpu_device.cc:887] Found device 0 with properties:
name: GeForce GTX 860M
major: 5 minor: 0 memoryClockRate (GHz) 1.0195
pciBusID 0000:01:00.0
Total memory: 3.95GiB
Free memory: 3.42GiB
2017-04-11 17:38:21.722624: I tensorflow/core/common_runtime/gpu/gpu_device.cc:908] DMA: 0
2017-04-11 17:38:21.722630: I tensorflow/core/common_runtime/gpu/gpu_device.cc:918] 0: Y
2017-04-11 17:38:21.722642: I tensorflow/core/common_runtime/gpu/gpu_device.cc:977] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 860M, pci bus id: 0000:01:00.0)
2017-04-11 17:38:22.183204: I tensorflow/compiler/xla/service/platform_util.cc:58] platform CUDA present with 1 visible devices
2017-04-11 17:38:22.183232: I tensorflow/compiler/xla/service/platform_util.cc:58] platform Host present with 8 visible devices
2017-04-11 17:38:22.184007: I tensorflow/compiler/xla/service/service.cc:183] XLA service 0xb85a1c0 executing computations on platform Host. Devices:
2017-04-11 17:38:22.184022: I tensorflow/compiler/xla/service/service.cc:191] StreamExecutor device (0): <undefined>, <undefined>
2017-04-11 17:38:22.184140: I tensorflow/compiler/xla/service/platform_util.cc:58] platform CUDA present with 1 visible devices
2017-04-11 17:38:22.184149: I tensorflow/compiler/xla/service/platform_util.cc:58] platform Host present with 8 visible devices
2017-04-11 17:38:22.184610: I tensorflow/compiler/xla/service/service.cc:183] XLA service 0xb631ee0 executing computations on platform CUDA. Devices:
2017-04-11 17:38:22.184620: I tensorflow/compiler/xla/service/service.cc:191] StreamExecutor device (0): GeForce GTX 860M, Compute Capability 5.0
[[ 0.1670652 0.46482906 0.12899996 0.12481128 0.11429448]]
Predicted Flower: dandelion
Prediction probability: 0.464829
Source potentielle du problème : j'ai d'abord entraîné mon modèle en utilisant TF 0.12, mais je pense qu'il est compatible avec Tf 1.01, la version que j'utilise maintenant. Par mesure de sécurité, j'ai mis à jour mes fichiers vers TF 1.01 et réentraîné le modèle pour obtenir de nouveaux ensembles de fichiers de contrôle (avec la même précision), puis j'ai utilisé ces fichiers de contrôle pour le gel. J'ai compilé mon tensorflow à partir des sources. Le problème vient-il du fait que j'utilise un fichier pbtxt au lieu d'un fichier pb ? Je n'ai aucune idée de la façon dont je pourrais obtenir un fichier pb à partir de la formation de mon modèle.