[GCP] Flask로 TF 2.0 MNIST 모델 서빙하기
Google Cloud Platform
우선 TensorFlow 2.0을 설치하자. 머신에 직접 설치하거나 도커를 다운받아 사용, 혹은 구글 colab을 활용( https://www.tensorflow.org/install)하면 되는데, TensorFlow에서 권장하는대로 머신에 VirtualEnv를 활용해서 설치하자
( https://www.tensorflow.org/install/pip). 설치하는 김에 Flask도 같이 설치해보자. Compute Machine 하나를 생성(크게 부담 없는 예제라 g1 instance)하고, SSH를 연결하여 실행하면 된다.
$ sudo apt update $ sudo apt install python3-dev python3-pip $ sudo pip3 install -U virtualenv # 굳이 system-wide로 flask를 설치할 필요는 없지만 그렇게 했다. $ sudo pip3 install flask $ sudo pip3 install flask-restful # virtualenv 환경에서 tensorflow 2.0 설치 $ virtualenv --system-site-packages -p python3 ./venv $ source ./venv/bin/activate # sh, bash, ksh, or zsh (venv) $ pip install --upgrade pip (venv) $ pip install --upgrade tensorflow
모든 환경이 마련되었으니, 우선 MNIST 모델을 TF 2.0으로 Training하여 모델을 Save 해 두자(tf_mnist_train.py). 대략 99% 이상 정확도가 나온다!
import tensorflow as tf import numpy as np # 학습 데이터 load ((train_data, train_label), (eval_data, eval_label)) = tf.keras.datasets.mnist.load_data() # data를 정규화하여 28x28로 reshape train_data=train_data/np.float32(255) train_data=train_data.reshape(60000, 28, 28, 1) train_data.shape eval_data = eval_data/np.float32(255) eval_data = eval_data.reshape(10000, 28, 28, 1) eval_data.shape from tensorflow.keras import models # CNN으로 모델 생성 model =models.Sequential() model.add(tf.keras.layers.Conv2D(32, (5,5), padding='same', activation='relu', input_shape=(28,28,1))) model.add(tf.keras.layers.MaxPooling2D((2,2))) model.add(tf.keras.layers.Conv2D(64, (5,5), activation='relu')) model.add(tf.keras.layers.MaxPooling2D((2,2))) model.add(tf.keras.layers.Conv2D(64, (5,5), activation='relu')) model.add(tf.keras.layers.Flatten()) model.add(tf.keras.layers.Dense(64, activation='relu')) model.add(tf.keras.layers.Dense(10, activation='softmax')) model.summary() # graph를 생성하고 training model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(train_data, train_label, epochs=5) test_loss, test_acc = model.evaluate(eval_data, eval_label, verbose=2) test_acc # save the model. TF 2.0에서는 experimental 대신 save_model만 하면됨 model_dir = "/tmp/tfkeras_mnist" tf.keras.experimental.export_saved_model(model, model_dir)
python으로 위 파일을 실행하면 모델이 지정된 곳에 저장된다. 우선 해당 모델을 불러서 제대로 예측하는지 확인해 보면, 99% 정확도니 예측은 비교적 정확해야 한다.
import tensorflow as tf import numpy as np # eval data 불러오고 ((train_data, train_label), (eval_data, eval_label)) = tf.keras.datasets.mnist.load_data() eval_data = eval_data/np.float32(255) eval_data = eval_data.reshape(10000, 28, 28, 1) # 저장한 모델 불러 온뒤 model_dir = "/tmp/tfkeras_mnist" new_model = tf.keras.experimental.load_from_saved_model(model_dir) new_model.summary() # 그래프를 형성하고, new_model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # 임의의 위치에 있는 MNIST 숫자를 하나 읽어서 예측 random_idx = np.random.choice(eval_data.shape[0]) test_data = eval_data[random_idx].reshape(1, 28, 28, 1) res = new_model.predict(test_data) # 제대로 학습되었는지 확인 print ("predict: {}, original: {}".format(np.argmax(res), eval_label[random_idx]))
대체로 결과는 아래와 같다.
(venv) $ python tf_test_mnist.py predict: 6, original: 6
모델은 제대로 만들어졌으니, 이제 Flask를 이용해 웹으로 서빙해 보자. virtualenv를 user 계정으로 수행하고 있으므로 5000번 이상의 포트를 사용해야 한다. 이를 위해 GCP에서 방화벽 규칙을 하나 만들어 주자.
(네트워킹 → VPC 네트워크 → 방화벽 규칙)
Flask 실행은 python 명령으로 직접 py파일을 실행하거나, FLASK_APP으로 지정된 파일을 flask run으로 수행할 수 있다. flask에서 어떻게 tensorflow를 불러오는 지 몰라, 일단 python 명령으로 수행할 것이다. 이전에 test한 모듈을 http get으로 읽어오는 부분에 넣어주기만 하면 된다.
from flask import Flask, render_template import flask_restful import tensorflow as tf import numpy as np # 데이터를 읽어들이고 ((train_data, train_label), (eval_data, eval_label)) = tf.keras.datasets.mnist.load_data() eval_data = eval_data/np.float32(255) eval_data = eval_data.reshape(10000, 28, 28, 1) # 저장해 두었던 모델을 읽어들인 후 model_dir = "/tmp/tfkeras_mnist" new_model = tf.keras.experimental.load_from_saved_model(model_dir) new_model.summary() #그래프를 생성하고 new_model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # Flask Restful API로 읽어들일 APP을 지정. app = Flask(__name__) api = flask_restful.Api(app) # Flask가 사용할 리소스는 Test 클래스. # get 함수가 HTTP Get으로 결과를 읽어들임 class Test(flask_restful.Resource): def get(self): random_idx = np.random.choice(eval_data.shape[0]) random_idx test_data = eval_data[random_idx].reshape(1, 28, 28, 1) res = new_model.predict(test_data) return { 'predict': np.argmax(res).tolist(), 'answer': eval_label[random_idx].tolist() } # Test 클래스를 리소스로 추가. 두번째 인자는 파일의 위치. # 우리는 ~/venv/tf_mnist 현재 디렉토리에서 읽을 것이므로 '/' api.add_resource(Test, '/') # 사용하는 포트는 5000번 if __name__ == "__main__": app.run(host="0.0.0.0", port=5000)
모든 작업이 끝났으니 서빙을 시작해 보자.
(venv) ryu_gcloud2@flask-test:~/venv/tf_mnist$ python3 app.py * Serving Flask app "app" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
서버가 잘 수행되었으니 브라우저로 테스트 해 보면 된다. 외부에서 접근되는 것이니, GCP Compute Instance의 외부 IP 주소를 하나 할당(이번 예제의 경우엔 아래 35.223.49.131)받고 그 주소로 접근(포트는 5000번)하면 된다.
Flask로 학습 모델 결과를 제대로 서빙하고 있다.
from http://ml-cloud.tistory.com/4 by ccl(A)
댓글
댓글 쓰기