I am trying to build the input for the saved model from BERT-SQuAD given that I have got all the elements for the input.
I fine-tuned a question answering model by running of run_squad.py in Google bert, then I exported the model with export_saved_model. Now when I have a new context and question, I can't build the correct input that can get return output from the model.
Code to export the model:
#export the model
def serving_input_receiver_fn():
feature_spec = {
"unique_ids": tf.FixedLenFeature([], tf.int64),
"input_ids": tf.FixedLenFeature([FLAGS.max_seq_length], tf.int64),
"input_mask": tf.FixedLenFeature([FLAGS.max_seq_length], tf.int64),
"segment_ids": tf.FixedLenFeature([FLAGS.max_seq_length], tf.int64),
}
serialized_tf_example = tf.placeholder(dtype=tf.string,
shape=FLAGS.predict_batch_size,
name='input_example_tensor')
receiver_tensors = {'examples': serialized_tf_example}
features = tf.parse_example(serialized_tf_example, feature_spec)
return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)
estimator = tf.contrib.tpu.TPUEstimator(
use_tpu=FLAGS.use_tpu,
model_fn=model_fn,
config=run_config,
train_batch_size=FLAGS.train_batch_size,
predict_batch_size=FLAGS.predict_batch_size)
estimator._export_to_tpu = False ## !!important to add this
estimator.export_saved_model(
export_dir_base ="C:/Users/ZitongZhou/Desktop/qa/bert_squad/servemodel",
serving_input_receiver_fn = serving_input_receiver_fn)
The way I loaded the model:
export_dir = 'servemodel'
subdirs = [x for x in Path(export_dir).iterdir()
if x.is_dir() and 'temp' not in str(x)]
latest = str(sorted(subdirs)[-1])
predict_fn = predictor.from_saved_model(latest)
I got the eval_features from the run_squad.py. The way I tried to build the input:
feature_spec = {
"unique_ids": np.asarray(eval_features[0].unique_id).tolist(),
"input_ids": np.asarray(eval_features[0].input_ids).tolist(),
"input_mask": np.asarray(eval_features[0].input_mask).tolist(),
"segment_ids": np.asarray(eval_features[0].segment_ids).tolist()
}
serialized_tf_example = tf.placeholder(dtype=tf.string,
shape=[1],
name='input_example_tensor')
receiver_tensors = {'examples': serialized_tf_example}
features = tf.parse_example(serialized_tf_example, feature_spec)
out = predict_fn({'examples':[str(feature_spec)]})
I expect to get a prediction 'out' so I can extract the answer to the question from it.
The traceback I got:
Traceback (most recent call last):
File "<ipython-input-51-0c3b618a8f48>", line 11, in <module>
features = tf.parse_example(serialized_tf_example, feature_spec)
File "C:\Users\ZitongZhou\Anaconda3\envs\nlp\lib\site-packages\tensorflow
\python\ops\parsing_ops.py", line 580, in parse_example
return parse_example_v2(serialized, features, example_names, name)
File "C:\Users\ZitongZhou\Anaconda3\envs\nlp\lib\site-packages\tensorflow
\python\ops\parsing_ops.py", line 803, in parse_example_v2
[VarLenFeature, SparseFeature, FixedLenFeature, FixedLenSequenceFeature])
File "C:\Users\ZitongZhou\Anaconda3\envs\nlp\lib\site-packages\tensorflow
\python\ops\parsing_ops.py", line 299, in _features_to_raw_params
raise ValueError("Invalid feature %s:%s." % (key, feature))
ValueError: Invalid feature input_ids:[101, 1005, 2129, 2214, 2003, 19523,
6562, 1005, 102, 1005, 19523, 11233, 2003, 2274, 2086, 2214, 1005, 102,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0].
I figured it out, I need to use tf.train.Example function:
def create_int_feature(values):
f = tf.train.Feature(int64_list=tf.train.Int64List(value=list(values)))
return f
inputs = collections.OrderedDict()
inputs["input_ids"] = create_int_feature(features[0].input_ids)
inputs["input_mask"] = create_int_feature(features[0].input_mask)
inputs["segment_ids"] = create_int_feature(features[0].segment_ids)
inputs["unique_ids"] = create_int_feature([features[0].unique_id])
tf_example = tf.train.Example(features=tf.train.Features(feature=inputs))
out = predict_fn({'examples':[tf_example.SerializeToString()]})