keras訓練了個二分類的模型。需求是把keras模型跑到 tensorflow serving上 (TensorFlow Serving 系統用於在生產環境中運行模型)javascript
我把 keras模型轉tensorflow serving模型所使用的方法以下:css
該文件應該包含:java
import pandas as pd import os import tensorflow as tf tf.logging.set_verbosity(tf.logging.INFO) ... def build_model(): ############ ... return model def save_model_for_production(model, version, path='prod_models'): tf.keras.backend.set_learning_phase(1) if not os.path.exists(path): os.mkdir(path) export_path = os.path.join( tf.compat.as_bytes(path), tf.compat.as_bytes(version)) builder = tf.saved_model.builder.SavedModelBuilder(export_path) model_input = tf.saved_model.utils.build_tensor_info(model.input) model_output = tf.saved_model.utils.build_tensor_info(model.output) prediction_signature = ( tf.saved_model.signature_def_utils.build_signature_def( inputs={'inputs': model_input}, outputs={'output': model_output}, method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME)) with tf.keras.backend.get_session() as sess: builder.add_meta_graph_and_variables( sess=sess, tags=[tf.saved_model.tag_constants.SERVING], signature_def_map={ 'predict': prediction_signature, }) builder.save() if __name__ == '__main__': model_file = './my_model.h5' if (os.path.isfile(model_file)): print('model file detected. Loading.') model = tf.keras.models.load_model(model_file) else: print('No model file detected. Starting from scratch.') model = build_model() model.compile(loss='binary_crossentropy', optimizer="adam", metrics=['accuracy']) model.save(model_file) model.fit(X_train, y_train, batch_size=100, epochs=1, validation_data=(X_test, y_test)) model.summary() export_path = "tf-model" save_model_for_production(model, "1", export_path)
上面的例子將模型保存到 tf-model目錄下
tf-model目錄結構以下:python
tf-model/ └── 1 ├── saved_model.pb └── variables ├── variables.data-00000-of-00001 └── variables.index
tf-model/ └── 1 ├── saved_model.pb └── variables ├── variables.data-00000-of-00001 └── variables.index
saved_model.pb 是能在 tensorflow serving跑起來的模型。git
tensorflow_model_server --port=9000 --model_name="username" --model_base_path="/data/models/tf-model/"
標準輸出以下(算法模型已成功跑起來了):github
Running ModelServer at 0.0.0.0:00 ...
Running ModelServer at 0.0.0.0:00 ...
#!/usr/bin/env python # encoding: utf-8 """ @version: v1.0 @author: zwqjoy @contact: zwqjoy@163.com @site: https://blog.csdn.net/zwqjoy @file: client @time: 2018/6/29 15:02 """ from __future__ import print_function from grpc.beta import implementations import tensorflow as tf from tensorflow_serving.apis import predict_pb2 from tensorflow_serving.apis import prediction_service_pb2 import numpy as np tf.app.flags.DEFINE_string('server', 'localhost:9000', 'PredictionService host:port') FLAGS = tf.app.flags.FLAGS def main(_): host, port = FLAGS.server.split(':') channel = implementations.insecure_channel(host, int(port)) stub = prediction_service_pb2.beta_create_PredictionService_stub(channel) # Send request # See prediction_service.proto for gRPC request/response details. data = np.array([4, 0, 0, 0, 1, 0, 1]) data = data.astype(np.float32) request = predict_pb2.PredictRequest() request.model_spec.name = 'username' # 這個name跟tensorflow_model_server --model_name="username" 對應 request.model_spec.signature_name = 'predict' # 這個signature_name 跟signature_def_map 對應 request.inputs['inputs'].CopyFrom( tf.contrib.util.make_tensor_proto(data, shape=(1, 7))) # shape跟 keras的model.input類型對應 result = stub.Predict(request, 10.0) # 10 secs timeout print(result) if __name__ == '__main__': tf.app.run()
客戶端跑出的結果是:算法
outputs { key: "output" value { dtype: DT_FLOAT tensor_shape { dim { size: 1 } dim { size: 1 } } float_val: 0.976889811523 } }
outputs { key: "output" value { dtype: DT_FLOAT tensor_shape { dim { size: 1 } dim { size: 1 } } float_val: 0.976889811523 } }
float_val: 0.976889811523 就是咱們須要的結果(機率)
float_val: 0.976889811523 就是咱們須要的結果(機率)
一、 keras 保存模型api
能夠使用model.save(filepath)
將Keras模型和權重保存在一個HDF5文件中,該文件將包含:bash
固然這個 HDF5 也能夠是用下面的代碼生成session
from keras.models import load_model model.save('my_model.h5')
二、 keras 加載模型
keras 加載模型(中間部分代碼省略了):
import numpy as np from keras.datasets import mnist from keras.utils import np_utils from keras.models import Sequential from keras.layers import Dense from keras.optimizers import SGD from keras.models import load_model # 載入數據 (x_train,y_train),(x_test,y_test) = mnist.load_data() # (60000,28,28) print('x_shape:',x_train.shape) # (60000) print('y_shape:',y_train.shape) # (60000,28,28)->(60000,784) x_train = x_train.reshape(x_train.shape[0],-1)/255.0 x_test = x_test.reshape(x_test.shape[0],-1)/255.0 # 換one hot格式 y_train = np_utils.to_categorical(y_train,num_classes=10) y_test = np_utils.to_categorical(y_test,num_classes=10) # 載入模型 model = load_model('model.h5') # 評估模型 loss,accuracy = model.evaluate(x_test,y_test) print('\ntest loss',loss) print('accuracy',accuracy) # 訓練模型 model.fit(x_train,y_train,batch_size=64,epochs=2) # 評估模型 loss,accuracy = model.evaluate(x_test,y_test) print('\ntest loss',loss) print('accuracy',accuracy) # 保存參數,載入參數 model.save_weights('my_model_weights.h5') model.load_weights('my_model_weights.h5')
但願能讓新手少走一些彎路
有些方法已通過時了(例以下面這種):
from tensorflow_serving.session_bundle import exporter export_path = ... # where to save the exported graph export_version = ... # version number (integer) saver = tf.train.Saver(sharded=True) model_exporter = exporter.Exporter(saver) signature = exporter.classification_signature(input_tensor=model.input, scores_tensor=model.output) model_exporter.init(sess.graph.as_graph_def(), default_graph_signature=signature) model_exporter.export(export_path, tf.constant(export_version), sess)
from tensorflow_serving.session_bundle import exporter export_path = ... # where to save the exported graph export_version = ... # version number (integer) saver = tf.train.Saver(sharded=True) model_exporter = exporter.Exporter(saver) signature = exporter.classification_signature(input_tensor=model.input, scores_tensor=model.output) model_exporter.init(sess.graph.as_graph_def(), default_graph_signature=signature) model_exporter.export(export_path, tf.constant(export_version), sess)
若是使用這種過期的方法,用tensorflow serving 跑模型的時候會提示:
WARNING:tensorflow:From test.py:107: Exporter.export (from tensorflow.contrib.session_bundle.exporter) is deprecated and will be removed after 2017-06-30. Instructions for updating: No longer supported. Switch to SavedModel immediately.
WARNING:tensorflow:From test.py:107: Exporter.export (from tensorflow.contrib.session_bundle.exporter) is deprecated and will be removed after 2017-06-30. Instructions for updating: No longer supported. Switch to SavedModel immediately.
從warning中 顯然能夠知道這種方法要被拋棄了,再也不支持這種方法了, 建議咱們轉用 SaveModel方法。
填坑大法: 使用 SaveModel
def save_model_for_production(model, version, path='prod_models'): tf.keras.backend.set_learning_phase(1) if not os.path.exists(path): os.mkdir(path) export_path = os.path.join( tf.compat.as_bytes(path), tf.compat.as_bytes(version)) builder = tf.saved_model.builder.SavedModelBuilder(export_path) model_input = tf.saved_model.utils.build_tensor_info(model.input) model_output = tf.saved_model.utils.build_tensor_info(model.output) prediction_signature = ( tf.saved_model.signature_def_utils.build_signature_def( inputs={'inputs': model_input}, outputs={'output': model_output}, method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME)) with tf.keras.backend.get_session() as sess: builder.add_meta_graph_and_variables( sess=sess, tags=[tf.saved_model.tag_constants.SERVING], signature_def_map={ 'predict': prediction_signature, }) builder.save()
https://github.com/amir-abdi/keras_to_tensorflow