Deploying Keras models using TensorFlow Serving and Flask

 

Often there’s a need to abstract away your machine learning model details and just deploy or integrate it with easy to use API endpoints. For eg., We can provide a URL endpoint using which anyone can make a POST request and they would get a JSON response of what the model has inferred without having to worry about its technicalities.

In this tutorial, we will create a TensorFlow Serving server to deploy our InceptionV3 image classification convolutional neural network (CNN) built in Keras. We will then create a simple Flask server which will accept POST request and do some image preprocessing, required for Tensorflow serving server, and return a JSON response.

What is TensorFlow Serving?

Serving is how you apply machine learning model after you’ve trained it.

Know more about TensorFlow Serving here

TensorFlow Serving makes the process of taking a model into production easier and faster. It allows you to safely deploy new models and run experiments while keeping the same server architecture and APIs. Out of the box, it provides integration with TensorFlow, but it can be extended to serve other types of models.

Installing TensorFlow Serving

Prerequisite: Please create a python virtual environment and install Keras with TensorFlow backend in it. Read more here.

Note: All the commands have been executed in python virtual environment on Ubuntu 18.04.1 LTS.

Now, inside the same virtual environment run the following commands (use sudo for root permissions):

$ apt install curl$ echo "deb [arch=amd64] http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" | sudo tee /etc/apt/sources.list.d/tensorflow-serving.list && curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | sudo apt-key add -$ apt-get update$ apt-get install tensorflow-model-server$ tensorflow_model_server --version
TensorFlow ModelServer: 1.10.0-dev
TensorFlow Library: 1.11.0$ python  --version
Python 3.6.6

You can upgrade to a newer version of tensorflow-model-server with:

$ apt-get upgrade tensorflow-model-server

Directory overview of what we are going to build

Understanding directory structure, before we get started, will help us in getting a clear picture of where we are at each step.

(tensorflow) ubuntu@Himanshu:~/Desktop/Medium/keras-and-tensorflow-serving$ tree -c
└── keras-and-tensorflow-serving
    ├── README.md
    ├── my_image_classifier
    │   └── 1
    │       ├── saved_model.pb
    │       └── variables
    │           ├── variables.data-00000-of-00001
    │           └── variables.index
    ├── test_images
    │   ├── car.jpg
    │   └── car.png
    ├── flask_server
    │   ├── app.py
    │   ├── flask_sample_request.py
    └── scripts
        ├── download_inceptionv3_model.py
        ├── inception.h5
        ├── auto_cmd.py
        ├── export_saved_model.py
        ├── imagenet_class_index.json
        └── serving_sample_request.py6 directories, 15 files

You can get all of these files from my GitHub repository:

Exporting Keras model for Tensorflow Serving

For this tutorial, we will download and save InceptionV3 CNN, having Imagenet weights, in Keras using download_inceptionv3_model.py. You can download any other model available in keras.applications library (here) or if you have built your own model in Keras then you can skip this step.

After executing the above script you should get the following output:

$ python download_inceptionv3_model.py
Using TensorFlow backend.
Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.5/inception_v3_weights_tf_dim_ordering_tf_kernels.h5
96116736/96112376 [==============================] - 161s 2us/step

Now we have our InceptionV3 CNN (inception.h5) saved in Keras format. We want to export our model in a format that the TensorFlow server can handle. We do this by executing export_saved_model.py script.

TensorFlow provides the SavedModel format as a universal format for exporting models. Under the hood, our Keras model is fully specified in terms of TensorFlow objects, so we can export it just fine using Tensorflow methods. TensorFlow provides a convenience function tf.saved_model.simple_save() which abstracts away some of these details and works fine for most use cases.

Output:

$ python export_saved_model.py
WARNING:tensorflow:No training configuration found in save file: the model was *not* compiled. Compile it manually.

We get this warning because we have downloaded a pre-trained model. We can use this model for inference as is, but if we want to train it further, we need to run the compile() function after loading it. This warning can be safely ignored for now. After executing this script, the following files are saved in my_image_classifier directory:

├── my_image_classifier
   └── 1
       ├── saved_model.pb
       └── variables
           ├── variables.data-00000-of-00001
           └── variables.index2 directories, 3 files

Suppose we want to update our model in the future (maybe because we have collected more training data and trained the model on the updated dataset), we can do so by,

  1. Running the same script on the new keras model
  2. Updating export_path = ‘../my_image_classifier/1’ to export_path = ‘../my_image_classifier/2’ in export_saved_model.py

TensorFlow Serving will automatically detect the new version of the model, in my_image_classifier directory, and update it in the server.

Starting TensorFlow Serving server

To start TensorFlow Serving server on your local machine, run the following command:

$ tensorflow_model_server --model_base_path=/home/ubuntu/Desktop/Medium/keras-and-tensorflow-serving/my_image_classifier --rest_api_port=9000 --model_name=ImageClassifier
  • --model_base_path: This has to be an absolute path else you will get an error saying:
Failed to start server. Error: Invalid argument: Expected model ImageClassifier to have an absolute path or URI; got base_path()=./my_image_classifier
  • --rest_api_port: Tensorflow Serving will start a gRPC ModelServer on port 8500 and the REST API will be available on port 9000.
  • --model_name: This will be the name of your Serving server using which you will send a POST request. You can type any name you want here.

Testing our TensorFlow Serving server

From raw data to production models (Source)

The serving_sample_request.py script makes a POST request to the TensorFlow Serving server. The input image is passed via command line argument.

Output:

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

$ python serving_sample_request.py -i ../test_images/car.png
Using TensorFlow backend.
[["n04285008", "sports_car", 0.998414], ["n04037443", "racer", 0.00140099], ["n03459775", "grille", 0.000160794], ["n02974003", "car_wheel", 9.57862e-06], ["n03100240", "convertible", 6.01581e-06]]

TensorFlow Serving server takes slightly more time for responding to the first request as compared to subsequent calls.


Why do we need a Flask server?

As we can see, we have performed some image preprocessing steps in serving_sample_request.py (frontend caller). Following are the reasons to create Flask server on top of TensorFlow serving server:

  • When we are providing our API endpoint to frontend team we need to ensure that we don’t overwhelm them with preprocessing technicalities.
  • We might not always have a Python backend server (eg. Node.js server) so using numpy and keras libraries, for preprocessing, might be a pain.
  • If we are planning to serve multiple models then we will have to create multiple TensorFlow Serving servers and will have to add new URLs to our frontend code. But our Flask server would keep the domain URL same and we only need to add a new route (a function).
  • Providing subscription-based access, exception handling and other tasks can be carried out in the Flask app.

What we are trying to do is eliminate tight coupling between TensorFlow Serving servers and our Frontend.

Multiple TensorFlow Serving servers hidden behind a Flask server

For this tutorial, we will create a Flask server on the same machine and in the same virtual environment as that of TensorFlow Serving and make use of the installed libraries. Ideally, both should be running on separate machines because a higher number of requests would cause the Flask server to slow down because of the image preprocessing being carried out. Also, a single Flask server might not be sufficient if the number of requests is really high. We may also need a queuing system if we have multiple frontend callers. Nonetheless, we can use this method to develop a satisfactory proof of concept.

Creating a Flask server

Prerequisite: Install Flask, in python virtual environment from here.

We just need a single app.py file in order to create our Flask server.

Go to the directory where you have saved your app.py file and start the Flask server with the following command:

$ export FLASK_ENV=development && flask run --host=0.0.0.0
  • FLASK_ENV=development: This enables debug mode which basically gives you complete error logs. Don’t use this in a production environment.
  • The flask run command automatically executes the app.py file in the current directory.
  • --host=0.0.0.0: This enables you to make requests, to the Flask server, from any other machine. To make a request from a different machine, you will have to specify the IP address of the machine where the Flask server is running in place of localhost.

Output:

* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 1xx-xxx-xx4
Using TensorFlow backend.

Start the TensorFlow Serving server using the same previous command:

$ tensorflow_model_server --model_base_path=/home/ubuntu/Desktop/Medium/keras-and-tensorflow-serving/my_image_classifier --rest_api_port=9000 --model_name=ImageClassifier

Here’s a script (auto_cmd.py) to automate starting and stopping of the two servers (TensorFlow Serving and Flask). You can modify this script for more than two servers as well.

Remember to change the path at line 10 of auto_cmd.py to make it point to your app.py’s directory. You may also need to change line 6 in order to make it point to your virtual environment’s bin. You can then execute the above script from any directory by executing following in your terminal:

$ python auto_cmd.py

Testing our Flask server and TensorFlow Serving server

We make a sample request using the flask_sample_request.py script. The script basically mimics request from the frontend:

  1. We take an input image, encode it to base64 format and send it to our Flask server using POST request.
  2. Flask server decodes this base64 image and pre-processes it for our TensorFlow Serving server.
  3. Flask server then makes a POST request to our TensorFlow serving server and decodes the response.
  4. The decoded response is formatted and sent back to the frontend.

Output:

$ python flask_sample_request.py -i ../test_images/car.png
[
  [
    "n04285008", 
    "sports_car", 
    0.998414
  ], 
  [
    "n04037443", 
    "racer", 
    0.00140099
  ], 
  [
    "n03459775", 
    "grille", 
    0.000160794
  ], 
  [
    "n02974003", 
    "car_wheel", 
    9.57862e-06
  ], 
  [
    "n03100240", 
    "convertible", 
    6.01581e-06
  ]
]

Our flask server currently has only a single route for our single Tensorflow Serving server. We can serve multiple models by creating multiple Tensorflow serving servers on different or same machine. For that we just need to add more routes (functions) to our app.py file and perform required model specific pre-processing in it. We can give these routes to our frontend team to call the models as required.

Handling Cross-Origin HTTP request

Consider a scenario where we make a POST request using Angular, our Flask server receives OPTIONS header and not POST because,

  • A web application makes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, and port) than its own origin.
  • CORS (Cross Origin Resource Sharing) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin. Read more about CORS here.

Hence, Angular doesn’t get back any response from the Flask server. To solve this we have to enable Flask-CORS in our app.py. Know more about it here.

Conclusion

And that’s all we need to serve our machine learning model. TensorFlow Serving makes it really easy to integrate machine learning into websites and other applications. With plenty of prebuilt models available in keras (here), it’s possible to develop super useful applications with minimal knowledge of machine learning and deep learning algorithms.

If you found this tutorial helpful, please do share it with your friends and leave a clap :-). If you have any queries, feedback or suggestions do let me know in the comments. Also, you can connect with me on Twitter and LinkedIn. There is so much to share with all of you and I’m just getting started. Stay tuned for more!

 

[출처] https://towardsdatascience.com/deploying-keras-models-using-tensorflow-serving-and-flask-508ba00f1037

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
공지 오라클 기본 샘플 데이터베이스 졸리운_곰 2014.01.02 86873
공지 [SQL컨셉] 서적 "SQL컨셉"의 샘플 데이타 베이스 SAMPLE DATABASE of ORACLE 가을의 곰을... 2013.02.10 79171
공지 [G_SQL] Sample Database 가을의 곰을... 2012.05.20 95908
82 sqlrelay (Queue 서버 설치) SQL Relay는 강력한 데이터베이스 연결 관리 솔루션입니다 file 졸리운_곰 2020.02.17 1894
81 MySQL: 대량 접속 처리하기 졸리운_곰 2020.02.17 1628
80 My-SQL 연산함수/ISNULL/group by/compute 졸리운_곰 2020.02.01 1573
79 MySQL 세자리 마다 콤마 찍기 file 졸리운_곰 2020.01.24 1021
78 docker mysql 한글 깨짐 해결 & 초기 설정 졸리운_곰 2020.01.23 1983
77 select 결과를 update하는 방법은 여러가지가 존재합니다. 졸리운_곰 2019.03.02 1196
76 DB 중복 개수 확인 file 졸리운_곰 2019.02.16 1610
75 여러 row를 1개의 컬럼으로 리턴 ( GROUP_CONCAT ) 졸리운_곰 2019.01.29 1140
74 MySQL CONCAT 함수로 2개 이상의 필드(컬럼) 결합하기 졸리운_곰 2019.01.29 1071
73 [Mysql] 중복 데이터 값 찾기 졸리운_곰 2019.01.17 1504
72 [MySQL] 레코드 데이터 치환하기 (REPLACE) 졸리운_곰 2018.12.19 1347
71 [mysql] FOREIGN KEY 연관된 데이터 삭제 ON DELETE CASCADE file 졸리운_곰 2018.12.16 1381
70 [MYSQL]NULL 값을 다른 값으로 변경, [MySQL] IFNULL , select문에서 null값 치환 졸리운_곰 2018.11.23 1972
69 MySQL workbench safe mode 해제하기 file 졸리운_곰 2018.11.19 990
68 MySQL 중복 데이터 찾아서 삭제하기 졸리운_곰 2018.10.29 1294
67 MySQL에서 중복되는 행을 하나만 남기도 모두 삭제하는 방법 졸리운_곰 2018.10.29 1259
66 7 ways to convince MySQL to use the right index 졸리운_곰 2018.08.30 1769
65 MYSQL에서 원치않는 TABLE LOCK이 걸렸을 경우 해제 방법입니다. 졸리운_곰 2018.08.29 1317
64 제목 : [mysql] 현재날짜에서 이전달 구하기 file 졸리운_곰 2018.08.28 1747
63 [mysql-함수]날짜 관련 함수 모음 졸리운_곰 2018.08.24 1465
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED