[Imple] Flask를 이용한 api 샘플
Flask는 Python의 웹 프레임 워크로 다양한 웹 엔진과 호환성이 좋고, 가벼워서 널리 이용되는 프레임워크다.
(특히 API를 만들기 매우 편리!)
샘플 소스는 다음과 같다.
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
이러한 Flask를 이용해 api를 만들고 모델 학습 결과로 이미지를 분류하는 간단한 소스를 구현해보고자 한다.
데이터는 import fashion_mnist 로 구글, 깃허브를 통해 쉽게 볼 수 있는 옷 종류 이미지 데이터를 사용하였다.
작성한 IDE는 Spyder(Python 3.9)로 Anaconda를 다운로드 받을때 함께 설치되었다.
① pre.py
app.py를 구현하기 전에 train, test 데이터를 나누고 이미지 다섯개 정도만 추출하여 따로 uploads 라는 폴더에 저장해두는 pre 소스를 구현 하였다.
# 파이프라인 테스트 코드
from tensorflow.keras.datasets import fashion_mnist
from imageio import imsave
(X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
for i in range(5) :
# 이미지를 로컬에 저장, 테스트로 다섯장
imsave(uri="C:/Users/user/FlaskAPI/uploads/{}.png".format(i), im=X_test[i])
이미지를 불러와 저장하는 imsave 는 scipy(1.2.0 이전 버전에서 제공) 혹은 imageio 모듈을 통해 사용할 수 있다.
로컬에 scipy는 1.2.0 이후 버전이므로 imageio 모듈을 사용하였다.
+ Spyder 사용 시 자주 사용한 단축키
행 선택 ctrl + 1 : 주석
메소드 ctrl + i : 해당 메소드 설명 확인 가능
행 선택 ctrl + enter : 행 실행
해당 파일을 실행하면 지정한 경로에 for range 개수인 다섯개의 이미지가 저장되어있음을 볼 수 있다.
② app.py
전체 소스이고, 소스에 대한 설명은 최대한 주석으로 남겨두었다.
대략 순서는 이렇게 보면 될 듯 하다.
1) 모델 구조, 학습된 모델을 가져와서 모델 만들기
2) flask api 만들기
3) /api/image/이미지이름 으로 post api 만들기 (이미지 이름을 건네면 지정 경로에 있는 이미지를 보고 클래스 분류 실행)
4) 결과(가장 근접한 분류확률 argmax(prediction[0])) 리턴.
5) 앱 실행
6) api 호출하고 결과보기
import os #경로와 파일을 다뤄 위치를 지정하거나 삭제함
import requests #경로를 생성하거나 서버로 오는 요청을 수신
import numpy as np #수학연산, 행렬 작업
import tensorflow as tf
from imageio import imsave, imread
from flask import Flask, request, jsonify
#모델 구조 가져오기
# 모델 망구성방식(토폴로지)에 대한 정보가 담긴 json 파일, 가중치를 저장하는 .h5 파일
with open("C:/Users/user/FlaskAPI/fashion_model_flask.json", "r") as f: #파일읽기 r
model_json = f.read() #모델구조읽기
# 읽은 파일 토대로 모델 만들기
model = tf.keras.models.model_from_json(model_json) #하나의 인자로 전체모델구조를 포함한 변수를 사용
#모델을 위한 모든 사전학습 가중치 불러오기
model.load_weights("C:/Users/user/FlaskAPI/fashion_model_flask.h5")
#flask api 만들기
app = Flask(__name__)
#이미지 분류 함수 만들기, 데코레이터사용
@app.route("/api/image/<string:img_name>", methods=["POST"])
def classify_image(img_name):
upload_dir = "C:/Users/user/FlaskAPI/uploads/"
image = imread(uri=upload_dir + img_name)
classes = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot'] #Fashion MNIST classes 가져옴
prediction = model.predict([image.reshape(1, 28*28)]) #예측값
return jsonify({" result ":classes[np.argmax(prediction[0])]})
#flask 실행
app.run(port=5000, debug=False)
* 당연히 소스 실행 전에 모델 망 구성방식을 정의한 fashion_model_flask.json 과 학습 시킨 모델 fashion_model_flask.h5 파일이 준비되어있어야 실행할 수 있다.*
소스를 실행하면 app.run을 통해 flask 앱이 실행이 되고, 콘솔 결과는 다음과 같다.
postman 을 이용해서 api를 호출하면
요렇게 0.png 가 Ankle boot 라는 결과가 돌아온다
실제로 0.png를 확인해보면 신발모양의 이미지임을 확인할 수 있었다!