I have a method to convert binary wire format to human readable format but I cannot do the inverse of this
import tensorflow as tf
from tensorflow.python.platform import gfile
def converter(filename):
with gfile.FastGFile(filename,'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
tf.import_graph_def(graph_def, name='')
tf.train.write_graph(graph_def, 'pbtxt/', 'protobuf.pb', as_text=True)
return
I just have to type the file name for this and it works. But on doing the opposite i get
File "pb_to_pbtxt.py", line 16, in <module>
converter('protobuf.pb') # here you can write the name of the file to be converted
File "pb_to_pbtxt.py", line 11, in converter
graph_def.ParseFromString(f.read())
File "/usr/local/lib/python2.7/dist-packages/google/protobuf/message.py", line 185, in ParseFromString
self.MergeFromString(serialized)
File "/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/python_message.py", line 1008, in MergeFromString
if self._InternalParse(serialized, 0, length) != length:
File "/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/python_message.py", line 1034, in InternalParse
new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)
File "/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/decoder.py", line 868, in SkipField
return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, end)
File "/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/decoder.py", line 838, in _RaiseInvalidWireType
raise _DecodeError('Tag had invalid wire type.')
You can perform the reverse translation using the google.protobuf.text_format module:
import tensorflow as tf
from google.protobuf import text_format
def convert_pbtxt_to_graphdef(filename):
"""Returns a `tf.GraphDef` proto representing the data in the given pbtxt file.
Args:
filename: The name of a file containing a GraphDef pbtxt (text-formatted
`tf.GraphDef` protocol buffer data).
Returns:
A `tf.GraphDef` protocol buffer.
"""
with tf.gfile.FastGFile(filename, 'r') as f:
graph_def = tf.GraphDef()
file_content = f.read()
# Merges the human-readable string in `file_content` into `graph_def`.
text_format.Merge(file_content, graph_def)
return graph_def
You can use tf.Graph.as_graph_def() and then Protobuf's SerializeToString() like so:
proto_graph = # obtained by calling tf.Graph.as_graph_def()
with open("my_graph.bin", "wb") as f:
f.write(proto_graph.SerializeToString())
If you just want to write the file and do not care about the encoding you can also use tf.train.write_graph()
v = tf.Variable(0, name='my_variable')
sess = tf.Session()
tf.train.write_graph(sess.graph_def, '/tmp/my-model', 'train.pbtxt')
Note: Tested on TF 0.10, not sure about earlier versions.
Related
Update: short answer, do not pack the archive to the same path as file source dir, the bug code in question is following
shutil.make_archive(zip_path, 'zip', tmpdir)
Original Question:
I am using shutils to pack and unpack a Tensorflow model folder (I think this issue is more related to shutils)
import tensorflow as tf
from tensorflow.keras import Model
from tensorflow.keras.layers import Dense
def load_model_as_bytes(model):
def file_chunk_generate(file_path):
CHUNK_SIZE = 4 * 1024 * 1024
with open(file_path, 'rb') as f:
while True:
piece = f.read(CHUNK_SIZE);
if len(piece) == 0:
return
yield ByteChunk(buffer=piece)
return file_chunk_generator
tmpdir = tempfile.mkdtemp()
tf.saved_model.save(model, tmpdir)
zip_path = os.path.join(tmpdir, "tf_model")
shutil.make_archive(zip_path, 'zip', tmpdir)
size = os.path.getsize(f'{zip_path}.zip')
logging.info(f"send model file zip, length: {size}") #-------output 4621
file_chunk_generator = file_chunk_generate(f'{zip_path}.zip')
return file_chunk_generator
class NeuralNetworkPart(Model):
def __init__(self):
super().__init__()
self.d1 = Dense(128, activation='relu')
self.d2 = Dense(10)
def call(self, x):
x = x[0]
x = self.d1(x)
return self.d2(x)
model = NeuralNetworkPart()
it = load_model_as_bytes(model)
tmpdir = tempfile.mkdtemp()
zip_path = os.path.join(tmpdir, "tf_model.zip")
with open(zip_path, 'wb') as f:
for byte_chunk in it:
f.write(byte_chunk.buffer)
logging.info(f"receive model file zip, length: {os.path.getsize(zip_path)}") #-------output 4621
shutil.unpack_archive(zip_path, tmpdir)
Basically this program get a folder, using make_archive to zip it. Then read the zip file as bytes, store it in a generator variable, and use the generator to write another zip file, and try to use unpack_archive to unzip it.
Before the byte generator is written, and after the zip file is written before unpack, the size are the same (checked in the logging), however when calling unpack, it raise EOF error
shutil.unpack_archive(zip_path, tmpdir)
File "/lib/python3.6/shutil.py", line 983, in unpack_archive
func(filename, extract_dir, **kwargs)
File "/lib/python3.6/shutil.py", line 901, in _unpack_zipfile
data = zip.read(info.filename)
File "/lib/python3.6/zipfile.py", line 1338, in read
return fp.read()
File "/lib/python3.6/zipfile.py", line 858, in read
buf += self._read1(self.MAX_N)
File "/lib/python3.6/zipfile.py", line 940, in _read1
data += self._read2(n - len(data))
File "/lib/python3.6/zipfile.py", line 975, in _read2
raise EOFError
This slightly simplified version seems to work just fine. Note that none of the temporary files are cleaned up by this; you might want to fix that before you have your tmpdir full of TensorFlow models.
import os
import shutil
import tempfile
def file_chunk_generate(file_path):
CHUNK_SIZE = 4 * 1024 * 1024
with open(file_path, "rb") as f:
while True:
piece = f.read(CHUNK_SIZE)
if not piece:
return
yield piece
def get_zip_chunk_generator(source_dir):
arcname = shutil.make_archive(
os.path.join(tempfile.mkdtemp("zip-"), "tf_model"), "zip", source_dir
)
return file_chunk_generate(arcname)
def make_source_dir():
tmpdir = tempfile.mkdtemp("src-")
for x in range(5):
with open(os.path.join(tmpdir, f"test-{x}.txt"), "wb") as f:
f.write(b"foo" * 1024)
return tmpdir
source_dir = make_source_dir()
it = get_zip_chunk_generator(source_dir)
dest_dir = tempfile.mkdtemp(prefix="dest-")
print("1", os.listdir(dest_dir))
zip_path = os.path.join(dest_dir, "tf_model_dest.zip")
with open(zip_path, "wb") as f:
for byte_chunk in it:
f.write(byte_chunk)
print("2", os.listdir(dest_dir))
shutil.unpack_archive(zip_path, dest_dir)
print("3", os.listdir(dest_dir))
The output is
1 []
2 ['tf_model_dest.zip']
3 ['test-0.txt', 'test-1.txt', 'test-3.txt', 'test-2.txt', 'tf_model_dest.zip', 'test-4.txt']
as you might expect.
I'd recommend using tarballs though if you're going to stream over the network (since you could indeed do that without any file on disk at all; ZIPs require seeking support to unpack, but TARs don't).
for my project I'm trying to do inference based on my trained model stored in saved_model.pb. I doubt that the mistake is due to my code you can see over here but more likely is due to an installation problem:
from PIL import Image
import numpy as np
import scipy
from scipy import misc
import matplotlib.pyplot as plt
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
with tf.Graph().as_default() as graph: # Set default graph as graph
with tf.Session() as sess:
# Load the graph in graph_def
print("load graph")
# We load the protobuf file from the disk and parse it to retrive the unserialized graph_drf
with gfile.FastGFile("saved_model.pb",'rb') as f:
from scipy.io import wavfile
samplerate, data = wavfile.read('sound.wav')
# Set FCN graph to the default graph
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
sess.graph.as_default()
# Import a graph_def into the current default Graph (In this case, the weights are (typically) embedded in the graph)
tf.import_graph_def(
graph_def,
input_map=None,
return_elements=None,
name="",
op_dict=None,
producer_op_list=None
)
# Print the name of operations in the session
for op in graph.get_operations():
print("Operation Name :",op.name) # Operation name
print("Tensor Stats :",str(op.values())) # Tensor name
# INFERENCE Here
l_input = graph.get_tensor_by_name('Inputs/fifo_queue_Dequeue:0') # Input Tensor
l_output = graph.get_tensor_by_name('upscore32/conv2d_transpose:0') # Output Tensor
print("Shape of input : ", tf.shape(l_input))
f.global_variables_initializer()
# Run model on single image
Session_out = sess.run( m_output, feed_dict = {m_input : data} )
print("Predicted class:", class_names[Session_out[0].argmax()] )
The traceback is the following
Traceback (most recent call last):
File "/home/pi/model_inference/test.py", line 11, in <module>
graph_def.ParseFromString(f.read())
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/message.py", line 199, in ParseFromString
return self.MergeFromString(serialized)
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/internal/python_message.py", line 1145, in MergeFromString
if self._InternalParse(serialized, 0, length) != length:
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/internal/python_message.py", line 1212, in InternalParse
pos = field_decoder(buffer, new_pos, end, self, field_dict)
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/internal/decoder.py", line 754, in DecodeField
if value._InternalParse(buffer, pos, new_pos) != new_pos:
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/internal/python_message.py", line 1212, in InternalParse
pos = field_decoder(buffer, new_pos, end, self, field_dict)
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/internal/decoder.py", line 733, in DecodeRepeatedField
if value.add()._InternalParse(buffer, pos, new_pos) != new_pos:
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/internal/python_message.py", line 1212, in InternalParse
pos = field_decoder(buffer, new_pos, end, self, field_dict)
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/internal/decoder.py", line 888, in DecodeMap
if submsg._InternalParse(buffer, pos, new_pos) != new_pos:
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/internal/python_message.py", line 1199, in InternalParse
buffer, new_pos, wire_type) # pylint: disable=protected-access
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/internal/decoder.py", line 989, in _DecodeUnknownField
(data, pos) = _DecodeUnknownFieldSet(buffer, pos)
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/internal/decoder.py", line 968, in _DecodeUnknownFieldSet
(data, pos) = _DecodeUnknownField(buffer, pos, wire_type)
File "/usr/local/lib/python3.7/dist-packages/google/protobuf/internal/decoder.py", line 993, in _DecodeUnknownField
raise _DecodeError('Wrong wire type in tag.')
google.protobuf.message.DecodeError: Wrong wire type in tag.
Important to note is that I'm trying this out on a raspberry pi v4 (thus linux running on it). I would be glad about any hint what to do.
Thanks in advance!
Try using tf.saved_model.load(path) where path is the path to your saved model's folder containing the assets and variables folder.follow this link to the tensorflow object-detection api inference tutorial.
It looks like your file "saved_model.pb" is not a saved (wireformat) protobuffer of the message type GraphDef. Maybe you can look how that was saved and find some instructions on how to load it back? Just guessing from the name, can it be a keras model and you have to use tf.keras.models.load_model?
I am using a graph file which i doesn't know the name of the variables on this graph model
this files i have :-
training_model_saved_model.pb
variables
training_model_variables_variables.data-00000-of-00001
training_model_variables_variables.index
i started by this code but i can't get the variable names so i can set them
import tensorflow as tf
import sys
from tensorflow.python.platform import gfile
from tensorflow.core.protobuf import saved_model_pb2
from tensorflow.python.util import compat
with tf.Session() as sess:
model_filename ='training_model_saved_model.pb'
with gfile.FastGFile(model_filename, 'rb') as f:
data = compat.as_bytes(f.read())
sm = saved_model_pb2.SavedModel()
sm.ParseFromString(data)
#print(sm)
if 1 != len(sm.meta_graphs):
print('More than one graph found. Not sure which to write')
sys.exit(1)
graph_def = tf.GraphDef()
#graph_def.ParseFromString(sm.meta_graphs[0])
x,y,z = tf.import_graph_def(sm.meta_graphs[0].graph_def,return_elements=['data/inputs:0',
'output/network_activation:0',
'data/correct_outputs:0'],
name='')
LOGDIR='Log_dir'
train_writer = tf.summary.FileWriter(LOGDIR)
train_writer.add_graph(sess.graph)
error return is expected
Traceback (most recent call last):
File "execute_model.py", line 24, in <module>
'data/correct_outputs:0'],name='')
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/importer.py", line 526, in import_graph_def
'Requested return_element %r not found in graph_def.' % name)
ValueError: Requested return_element 'data/inputs:0' not found in graph_def.
any help , thanks in advance
When I run tensor.py it tell me that "ImportError: No module named freezegraph"
Does it means I should create "freezgraph" by myself? sorry,I'm confused,looking forward for your introduction~
Here is the code:
#!/usr/bin/python
import os
import tensorflow as tf
import pmt
import freezegraph
def save_graph(sess,output_path,checkpoint,checkpoint_state_name,input_graph_name,output_graph_name,outname):
checkpoint_prefix = os.path.join(output_path,checkpoint)
# defaults to saving all variables
saver = tf.train.Saver(tf.all_variables())
saver.save(sess, checkpoint_prefix, global_step=0,latest_filename=checkpoint_state_name)
tf.train.write_graph(sess.graph.as_graph_def(),output_path,
input_graph_name)
# We save out the graph to disk, and then call the const conversion
# routine.
input_graph_path = os.path.join(output_path, input_graph_name)
input_saver_def_path = ""
input_binary = False
input_checkpoint_path = checkpoint_prefix + "-0"
output_node_names = outname
restore_op_name = "save/restore_all"
filename_tensor_name = "save/Const:0"
output_graph_path = os.path.join(output_path, output_graph_name)
clear_devices = False
freezegraph.freeze_graph(input_graph_path, input_saver_def_path,
input_binary, input_checkpoint_path,
output_node_names, restore_op_name,
filename_tensor_name, output_graph_path,clear_devices, "")
def load_graph(output_graph_path,inp,out,ckpt_path=""):
with tf.Graph().as_default():
output_graph_def = tf.GraphDef()
with tf.Session() as sess:
with open(output_graph_path, "rb") as f:
output_graph_def.ParseFromString(f.read())
_ = tf.import_graph_def(output_graph_def, name="")
n_input = sess.graph.get_tensor_by_name(inp)
output = sess.graph.get_tensor_by_name(out)
return (sess,n_input,output)
I change the "import freezegraph " to "from tensorflow.python.tools import freeze_graph" then I get new errors:
File "/home/imatrix/chrisruk/cnn-master/train_cnn.py", line 46, in <module>
save_graph(sess,"/tmp/","saved_checkpoint","checkpoint_state","input_graph.pb","output_graph.pb","out/Softmax")
File "/home/imatrix/ chrisruk/cnn-master/tensor.py", line 35, in save_graph
filename_tensor_name, output_graph_path,clear_devices, "")
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/tools/freeze_graph.py", line 103, in freeze_graph
_ = importer.import_graph_def(input_graph_def, name="")
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/importer.py", line 308, in import_graph_def
op_def=op_def)
File "/usr/local/lib/python2.7/dist-pack`enter code here`ages/tensorflow/python/framework/ops.py", line 2339, in create_op
self._add_op(ret)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py", line 2033, in _add_op
"is already used" % op.name)
ValueError: cannot add op with name Crossentropy/Mean/moving_avg as that name is already used
I want to save and load a fitted Random Forest Classifier, but I get an error.
forest = RandomForestClassifier(n_estimators = 100, max_features = mf_val)
forest = forest.fit(L1[0:100], L2[0:100])
joblib.dump(forest, 'screening_forest/screening_forest.pkl')
forest2 = joblib.load('screening_forest/screening_forest.pkl')
The error is:
File "C:\Users\mkolarek\Documents\other\TrackerResultAnalysis\ScreeningClassif
ier\ScreeningClassifier.py", line 67, in <module>
forest2 = joblib.load('screening_forest/screening_forest.pkl')
File "C:\Python27\lib\site-packages\sklearn\externals\joblib\numpy_pickle.py",
line 425, in load
obj = unpickler.load()
File "C:\Python27\lib\pickle.py", line 858, in load
dispatch[key](self)
File "C:\Python27\lib\site-packages\sklearn\externals\joblib\numpy_pickle.py",
line 285, in load_build
Unpickler.load_build(self)
File "C:\Python27\lib\pickle.py", line 1217, in load_build
setstate(state)
File "_tree.pyx", line 2280, in sklearn.tree._tree.Tree.__setstate__ (sklearn\
tree\_tree.c:18350)
ValueError: Did not recognise loaded array layout
Press any key to continue . . .
Do I have to initialize forest2 or something?
I solved it with cPickle instead:
with open('screening_forest/screening_forest.pickle', 'wb') as f:
cPickle.dump(forest, f)
with open('screening_forest/screening_forest.pickle', 'rb') as f:
forest2 = cPickle.load(f)
but a joblib solution could be useful as well.
Here is the method that you can try
model = RandomForestClassifier()
model.fit(data,lables)
import pickle
Model_file = 'model.pkl'
pickle.dump(model, open(Model_file, 'wb'))
'''Reloading the model
load the model from Saved file'''
loaded_model = pickle.load(open(Model_file, 'rb'))