我使用tensorflow 1.15
训练了模型并保存为检查点(带有.meta
,.index
和.data
文件)。
我需要在此图的开头和结尾添加一些其他操作。其中一些操作仅存在于tensorflow 2.0
和tensorflow_text 2.0
中。之后,我想将此模型保存为tensorflow-serving
。
我想做的是:使用tensorflow 2.0
这样保存为.pb
文件。
trained_checkpoint_prefix = 'path/to/model'
export_dir = os.path.join('path/to/export','0')
graph = tf.Graph()
with tf.compat.v1.Session(graph=graph) as sess:
# Restore from checkpoint
loader = tf.compat.v1.train.import_meta_graph(trained_checkpoint_prefix + '.meta')
loader.restore(sess,trained_checkpoint_prefix)
# Export checkpoint to Savedmodel
builder = tf.compat.v1.saved_model.builder.SavedmodelBuilder(export_dir)
classification_signature = tf.compat.v1.saved_model.signature_def_utils.build_signature_def(
inputs={
'token_indices': get_tensor_info('token_indices_ph:0'),'token_mask': get_tensor_info('token_mask_ph:0'),'y_mask': get_tensor_info('y_mask_ph:0'),},outputs={'probas': get_tensor_info('ner/Softmax:0'),'seq_lengths': get_tensor_info('ner/Sum:0')},method_name='predict',)
builder.add_meta_graph_and_variables(sess,[tf.saved_model.TRAINING,tf.saved_model.SERVING],strip_default_attrs=True,saver=loader,signature_def_map={'predict': classification_signature}) #,clear_devices=True)
builder.save()
此后,我创建了一个tf.keras.Model
来加载.pb
模型并负责我需要的所有人员:
import os
from pathlib import Path
import tensorflow as tf
import tensorflow_text as tf_text
class bertPipeline(tf.keras.Model):
def __init__(self):
super().__init__()
vocab_file = Path('path/to/vocab.txt')
vocab = vocab_file.read_text().split('\n')[:-1]
self.vocab_table = self.create_table(vocab)
export_dir = 'path/to/pb/model'
self.model = tf.saved_model.load(export_dir)
self.bert_tokenizer = bertTokenizer(
self.vocab_table,max_chars_per_token=15,token_out_type=tf.int64,lower_case=True,)
self.to_dense = tf_text.keras.layers.ToDense()
def call(self,texts):
tokens = self.bert_tokenizer.tokenize(texts)
tokens = tf.cast(tokens,dtype=tf.int32)
mask = self.make_mask(tokens)
token_ids = self.make_token_ids(tokens)
token_indices = self.to_dense(token_ids)
token_mask = self.to_dense(tf.ones_like(mask))
y_mask = self.to_dense(mask)
res = self.model.signatures['predict'](
token_indices=token_indices,token_mask=token_mask,y_mask=y_mask,)
starts_range = tf.range(0,tf.shape(res['seq_lengths'])[0]) * tf.shape(res['probas'])[1]
row_splits = tf.reshape(
tf.stack(
[
starts_range,starts_range + res['seq_lengths'],],axis=1,),[-1],)
row_splits = tf.concat(
[
row_splits,tf.expand_dims(tf.shape(res['probas'])[0] * tf.shape(res['probas'])[1],0),axis=0,)
probas = tf.RaggedTensor.from_row_splits(
tf.reshape(res['probas'],[-1,2]),row_splits,)[::2]
probas
return probas
def make_mask(self,tokens):
masked_suff = tf.concat(
[
tf.ones_like(tokens[:,:,:1],dtype=tf.int32),tf.zeros_like(tokens[:,1:],axis=-1,)
joined_mask = self.join_wordpieces(masked_suff)
return tf.concat(
[
tf.zeros_like(joined_mask[:,joined_mask,tf.zeros_like(joined_mask[:,)
def make_token_ids(self,tokens):
joined_tokens = self.join_wordpieces(tokens)
return tf.concat(
[
tf.fill(
[joined_tokens.nrows(),1],tf.dtypes.cast(
self.vocab_table.lookup(tf.constant('[CLS]')),dtype=tf.int32,)
),self.join_wordpieces(tokens),tf.fill(
[joined_tokens.nrows(),tf.dtypes.cast(
self.vocab_table.lookup(tf.constant('[SEP]')),)
def join_wordpieces(self,wordpieces):
return tf.RaggedTensor.from_row_splits(
wordpieces.flat_values,tf.gather(wordpieces.values.row_splits,wordpieces.row_splits))
def create_table(self,vocab,num_oov=1):
init = tf.lookup.KeyValueTensorInitializer(
vocab,tf.range(tf.size(vocab,out_type=tf.int64),dtype=tf.int64),key_dtype=tf.string,value_dtype=tf.int64)
return tf.lookup.StaticVocabularyTable(init,num_oov,lookup_key_dtype=tf.string)
当我调用此代码时,它可以很好地工作:
bert_pipeline = bertPipeline()
print(bbert_pipeline(["Some test string","another string"]))
---
<tf.RaggedTensor [[[0.17896245419979095,0.8210375308990479],[0.8825045228004456,0.11749550700187683],[0.9141901731491089,0.0858098641037941]],[[0.2768123149871826,0.7231876850128174],[0.9391192197799683,0.060880810022354126]]]>
但是我不知道如何保存它。如果我理解正确,tf.keras.Model
请勿将self.model
和self.bert_tokenizer
视为模型的一部分。如果我致电bert_pipeline.summary()
,则没有操作
bert_pipeline.build([])
bert_pipeline.summary()
---
Model: "bert_pipeline_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
to_dense (ToDense) multiple 0
=================================================================
Total params: 0
Trainable params: 0
Non-trainable params: 0
_________________________________________________________________
此外,我尝试使用显式tensorflow.compat.v1
和Session
在Graph
上运行它,但是在这种情况下,我只是无法正确加载模型。与import tensorflow.compat.v1 as tf
相同的代码和tensorflow 1.xx
的样板无法初始化某些变量:
# tf.saved_model.load(export_dir) changed to tf.saved_model.load_v2(export_dir) above
import tensorflow.compat.v1 as tf
graph = tf.Graph()
with tf.Session(graph=graph) as sess:
bert_pipeline = bertPipeline()
texts = tf.placeholder(tf.string,shape=[None],name='texts')
res_tensor = bert_pipeline(texts)
sess.run(tf.tables_initializer())
sess.run(tf.global_variables_initializer())
sess.run(res_tensor,feed_dict={texts: ["Some test string","another string"]})
---
FailedPreconditionError Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/client/session.py in _do_call(self,fn,*args)
1364 try:
-> 1365 return fn(*args)
1366 except errors.OpError as e:
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/client/session.py in _run_fn(feed_dict,fetch_list,target_list,options,run_metadata)
1349 return self._call_tf_sessionrun(options,feed_dict,-> 1350 target_list,run_metadata)
1351
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/client/session.py in _call_tf_sessionrun(self,run_metadata)
1442 fetch_list,-> 1443 run_metadata)
1444
FailedPreconditionError: [_Derived_]{{function_node __inference_pruned_77348}} {{function_node __inference_pruned_77348}} Attempting to use uninitialized value bert/encoder/layer_3/attention/self/query/kernel
[[{{node bert/encoder/layer_3/attention/self/query/kernel/read}}]]
[[bert_pipeline/StatefulPartitionedCall]]
During handling of the above exception,another exception occurred:
FailedPreconditionError Traceback (most recent call last)
<ipython-input-15-5a0a45327337> in <module>
21 sess.run(tf.global_variables_initializer())
22
---> 23 sess.run(res_tensor,"another string"]})
24
25 # print(res)
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/client/session.py in run(self,fetches,run_metadata)
954 try:
955 result = self._run(None,options_ptr,--> 956 run_metadata_ptr)
957 if run_metadata:
958 proto_data = tf_session.TF_GetBuffer(run_metadata_ptr)
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/client/session.py in _run(self,handle,run_metadata)
1178 if final_fetches or final_targets or (handle and feed_dict_tensor):
1179 results = self._do_run(handle,final_targets,final_fetches,-> 1180 feed_dict_tensor,run_metadata)
1181 else:
1182 results = []
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/client/session.py in _do_run(self,run_metadata)
1357 if handle is None:
1358 return self._do_call(_run_fn,feeds,targets,-> 1359 run_metadata)
1360 else:
1361 return self._do_call(_prun_fn,fetches)
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/client/session.py in _do_call(self,*args)
1382 '\nsession_config.graph_options.rewrite_options.'
1383 'disable_meta_optimizer = True')
-> 1384 raise type(e)(node_def,op,message)
1385
1386 def _extend_graph(self):
FailedPreconditionError: [_Derived_] Attempting to use uninitialized value bert/encoder/layer_3/attention/self/query/kernel
[[{{node bert/encoder/layer_3/attention/self/query/kernel/read}}]]
[[bert_pipeline/StatefulPartitionedCall]]
请,如果您有一些想法如何解决我保存图形的方法,或者您知道如何做得更好-请告诉我。谢谢!