호돌찌의 AI 연구소
article thumbnail

 

1. Flask 정의

The python micro framework for building web applications -
https://github.com/pallets/flask

Micro Service Architecture(MSA)를 위한 Web App Framework입니다. 웹 앱 프레임워크는 말 그대로 웹 서비스 개발을 위한 프레임워크라고 생각하면 됩니다. Django 등 다른 framework에 비해 가볍고 확장성, 유연성이 뛰어난 프레임워크가 Flask입니다. 여기서는 간단한 기능을 가볍게 구현하기에 적합하기 때문에 대부분의 ML Model의 첫 배포 Step으로 Flask를 애용합니다. 

 

2. Flask Install

python 3.6이상, pip3가 갖춰진 가상환경에서 수행하였습니다. 

mkdir flask-tutorial
cd flask-tutorial

pip install -U Flask==2.0.2

 

3. Hello world! - Flask

app.py라는 파일을 생성해 아래 코드를 복사해 붙여놓고 이를 수행합니다. Flask를 사용해 간단한 웹 서버를 띄우는 것이 목표 입니다. 

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"


# debug 모드로 실행, 모든 IP 에서 접근 허용
# 5000 포트로 사용하는 것을 의미
if __name__ == "__main__":
	app.run(debug=True, host='0.0.0.0', port=5000)

"python app.py"를 수행합니다. 아래와 같이 확인이 가능합니다.

Running on ~~~ 에 접속하니 Hello world! 를 확인할 수 있었다. 

 

4. Routing

flask에 route() 데코레이터는 python 함수를 web server의 URI에 mapping이 가능합니다. 원하는대로 Routing을 수행할 수 있는데, 아래 예시를 확인해보겠습니다. 

app.py 파일을 아래 코드를 복사해 수행하겠습니다. 파이썬 데코레이터 부분위주로 확인하시면 됩니다. 

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

@app.route("/fastcampus")
def hello_fastcampus():
    return "<p>Hello, Fast Campus!</p>"

if __name__ == "__main__":
	app.run(debug=True, host='0.0.0.0', port=5000)

그 이후 "python app.py"를 수행하고, @app.route("/fastcampus")  부분처럼 뒤에 URI 주소 뒤에 "/fastcampus" 추가하여 접속합니다. 

다른 페이지가 나타난 것을 확인할 수 있다. 

 

5. Post Method

Flask의 route() 데코레이터는 URI 뿐만아니라 HTTP Method도 지정이 가능하기에, 이를 활용하면 원하는대로 API를 만들 수 있습니다. 아래와 같은 코드를 복사해 app.py를 만듭니다. 

from flask import Flask
import json

app = Flask(__name__)

@app.route("/predict", methods=["POST", "PUT"])
def inference():
    return json.dumps({'hello': 'world'}), 200 # http status code 를 200 으로 반환하는 것을 의미

if __name__ == "__main__":
	app.run(debug=True, host='0.0.0.0', port=5000)

 

동일한 폴더에서 "python app.py" 를 수행해 application server를 로컬에서 띄우고 아래와 같은 curl를 수행합니다.

curl -X POST http://127.0.0.1:5000/predict


curl -X PUT http://127.0.0.1:5000/predict


curl -X GET http://127.0.0.1:5000/predict

 

post, put은 curl에 대한 응답이 정상적으로 나타남을 알 수 있습니다. 하지만 route()에서 GET부분은 method에 반영을 하지 않았기 때문에 error가 나타나는 것을 위 그림에서 알 수 있습니다. 

 

 

 

 

 

 

 

 

 

6. Flask에서 사용할 모델 Train 및 Save

이제부터 Flask 매우매우 기본적인 부분들만 찍어먹어 봤습니다. 모든 기능을 살펴보는 것이 목표가 아닙니다. 따라서 샘플 ML 모델을 API 서비스로 서빙하고자 할 때 Flask를 사용하는 방법을 알아보겠습니다. iris 데이터로 간단한 분류 모델 학습 후 pickle로 모델을 저장합니다. 그담에 flask에서는 model.pkl 을 load해 predict하는 server를 구현하겠습니다. 

아래 샘플코드를 train.py 로 저장합니다. ( * scikit-learn==1.0 을 미리 설치해주세요)

 

import os
import pickle

from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report
from sklearn.model_selection import train_test_split

RANDOM_SEED = 1234

# STEP 1) data load
data = load_iris()

# STEP 2) data split
X = data['data']
y = data['target']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,
                                                    random_state=RANDOM_SEED)

# STEP 3) train model
model = RandomForestClassifier(n_estimators=300, random_state=RANDOM_SEED)
model.fit(X_train, y_train)

# STEP 4) evaluate model
print(f"Accuracy :  {accuracy_score(y_test, model.predict(X_test))}")
print(classification_report(y_test, model.predict(X_test)))

# STEP 5) save model to ./build/model.pkl
os.makedirs("./build", exist_ok=True)
pickle.dump(model, open('./build/model.pkl', 'wb'))

"python train.py" 를 수행하면 아래와 같이 metric을 확인할 수 있습니다. 

 

위 샘플 코드에서 step 5를 보면 build 폴더를 만들어서 model.pkl 파일을 생성시킵니다. 

모델이 잘 있는 것을 알 수 있다. 

 

7. Flask 서버 구현

아래 샘플 코드를 복사해 "flask_server.py"를 만듭니다. 

import pickle

import numpy as np
from flask import Flask, jsonify, request

# 학습한 모델 파일을 부르기
model = pickle.load(open('./build/model.pkl', 'rb'))

# Flask Server 를 구현
app = Flask(__name__)


# POST /predict 라는 API 를 구현
@app.route('/predict', methods=['POST'])
def make_predict():
    # API Request Body 를 python dictionary object 로 변환
    request_body = request.get_json(force=True)

    # request body 를 model 의 형식에 맞게 변환
    X_test = [request_body['sepal_length'], request_body['sepal_width'],
              request_body['petal_length'], request_body['petal_width']]
    X_test = np.array(X_test)
    X_test = X_test.reshape(1, -1)

    # model 의 predict 함수를 호출하여, prediction 값을 구함
    y_test = model.predict(X_test)

    # prediction 값을 json 화 시킴
    response_body = jsonify(result=y_test.tolist())

    # predict 결과를 담아 API Response Body 를 return
    return response_body


if __name__ == '__main__':
    app.run(port=5000, debug=True)

 

 

 

8. API Test

그 다음에 "python flask_server.py"를 수행합니다.

서버가 동작함을 알 수 있다. 

 

그 다음에 curl을 이용해서 데이터 샘플 하나를 predict를 시키면 아래와 같이 "2"라는 값을 리턴하는 것을 알 수 있습니다.

curl -X POST -H "Content-Type:application/json" --data '{"sepal_length": 5.9, "sepal_width": 3.0, "petal_length": 5.1, "petal_width": 1.8}' http://localhost:5000/predict

 

 

 

 

 

아주 간단하게 flask을 개념 익히고, iris 데이터로 한번 확인하였습니다. 실은 이 부분에 대해서 쿠버네티스 환경에서 배포하려면 추가적인 공수가 많이 들어갑니다. 이 모든 작업들을 도커 이미지로 다 말아서 도커 레지스트리에 푸시하는 일련의 과정들에 대해 디플로이 먼트도 고려해야합니다. 또한 서버에서 로드밸런서 활용해 할당받은 아이피, 도메인으로 접속해야하는 등 제가 분석일을 하면서 다른 개발자의 고충들도 간접적으로 느껴지는 것 같습니다. 

 

다음 글에서는 seldon-core 로 찾아뵙겠습니다. 

 

 


https://bit.ly/37BpXiC

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

 

* 본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

 

 


profile

호돌찌의 AI 연구소

@hotorch's AI Labs

포스팅이 도움이 되셨다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!