Flask REST API를 사용한 Python 기계 학습 예측
게시 됨: 2022-03-11이 문서는 Flask REST API를 사용하여 실시간 예측을 수행하기 위해 기계 학습 또는 인공 지능(AI) 시스템의 맥락에서 Python을 사용하는 방법에 대해 설명합니다. 여기에 노출된 아키텍처는 기계 학습 애플리케이션을 위한 개념 증명(PoC)에서 MVP(Minimal Viable Product)로 가는 방법으로 볼 수 있습니다.
Python은 실시간 솔루션을 설계할 때 생각할 수 있는 첫 번째 선택이 아닙니다. 그러나 Tensorflow와 Scikit-Learn은 Python에서 지원하는 가장 많이 사용되는 기계 학습 라이브러리이므로 많은 Jupyter Notebook PoC에서 편리하게 사용됩니다.
이 솔루션을 가능하게 만드는 것은 예측에 비해 훈련에 많은 시간이 걸린다는 사실입니다. 훈련을 영화를 보고 그에 대한 질문에 대한 답을 예측하는 과정이라고 생각한다면, 매번 새로운 질문이 나올 때마다 영화를 다시 볼 필요가 없는 것이 상당히 효율적일 것 같습니다.
훈련은 그 "영화"의 일종의 압축된 보기이고 예측은 압축된 보기에서 정보를 검색하는 것입니다. 영화가 복잡하든 길든 간에 정말 빨라야 합니다.
Python의 빠른 [Flask] 예제로 이를 구현해 보겠습니다!
일반 기계 학습 아키텍처
일반적인 학습 및 예측 아키텍처 흐름을 간략하게 설명하는 것으로 시작하겠습니다.
먼저, 목적 함수에 따라 과거 데이터를 학습하기 위한 훈련 파이프라인을 생성합니다.
이렇게 하면 두 가지 핵심 요소가 출력되어야 합니다.
- 특성 공학 기능 : 훈련 시 사용한 변환은 예측 시 재사용해야 합니다.
- 모델 파라미터 : 최종 선정된 알고리즘과 하이퍼파라미터를 저장하여 예측시 재사용 가능
학습 시간 동안 수행된 기능 엔지니어링은 예측에 적용할 수 있도록 신중하게 저장해야 합니다. 그 과정에서 나타날 수 있는 많은 다른 문제들 중 하나의 일반적인 문제는 많은 알고리즘에 필요한 기능 크기 조정 입니다.
특성 X1이 값 1에서 1000으로 조정되고 f(x) = x/max(X1)
함수를 사용하여 [0,1] 범위로 다시 조정되면 예측 세트의 값이 2000이면 어떻게 될까요?
매핑 함수가 예측 시간에 올바르게 계산될 일관된 출력을 반환하도록 사전에 몇 가지 신중한 조정을 고려해야 합니다.
기계 학습 훈련 vs 예측
여기서 해결해야 할 중요한 질문이 있습니다. 먼저 훈련과 예측을 분리하는 이유는 무엇입니까?
모든 데이터(예측할 데이터 포함)가 미리 알려진 기계 학습 예제 및 과정의 맥락에서 예측기를 구축하는 매우 간단한 방법은 훈련 및 예측 데이터 (보통 테스트 세트).
그런 다음 "훈련 세트"에 대해 훈련하고 "테스트 세트"에 대해 예측하여 결과를 얻는 동시에 훈련 및 테스트 데이터 모두에 대해 기능 엔지니어링을 수행하고 동일하고 고유한 파이프라인에서 훈련 및 예측해야 합니다. .
그러나 실제 시스템에서는 일반적으로 훈련 데이터가 있고 예측할 데이터가 처리되는 대로 들어옵니다. 즉, 영화를 한 번에 보고 나중에 궁금한 점이 생기면 답이 쉽고 빨라야 합니다.
또한 훈련에는 시간이 걸리고(일부 이미지 세트의 경우 몇 주가 소요될 수 있음) 시간이 지남에 따라 충분히 안정적이어야 하기 때문에 일반적으로 새 데이터가 들어올 때마다 전체 모델을 다시 훈련할 필요가 없습니다.
이것이 많은 시스템에서 훈련과 예측이 명확하게 분리될 수 있거나 심지어 분리되어야 하는 이유이며, 이것은 또한 지능 시스템(인공 여부)이 학습하는 방식을 더 잘 반영합니다.
과적합과의 연결
훈련과 예측을 분리하는 것도 과적합 문제를 해결하는 좋은 방법입니다.
통계에서 과적합은 "특정 데이터 세트에 너무 가깝거나 정확히 일치하는 분석의 생성"이므로 추가 데이터에 적합하지 않거나 미래 관측치를 안정적으로 예측하지 못할 수 있습니다.
과적합은 특히 많은 기능이 있는 데이터 세트 또는 제한된 교육 데이터가 있는 데이터 세트에서 볼 수 있습니다. 두 경우 모두 데이터는 예측자가 검증할 수 있는 정보에 비해 너무 많은 정보를 갖고 있으며, 그 중 일부는 예측 변수에 연결되지 않을 수도 있습니다. 이 경우 노이즈 자체가 신호로 해석될 수 있습니다.
과적합을 제어하는 좋은 방법은 데이터의 일부를 훈련하고 우리가 근거가 있는 다른 부분을 예측하는 것입니다. 따라서 우리가 훈련하는 데이터가 시스템의 현실과 미래 상태를 나타내는 경우 새 데이터에서 예상되는 오류는 해당 데이터세트에서 대략적으로 측정된 오류입니다.
따라서 올바른 데이터 분할과 함께 적절한 교육 및 예측 파이프라인을 설계하면 과적합 문제를 해결할 뿐만 아니라 새 데이터에 대한 예측을 위해 해당 아키텍처를 재사용할 수 있습니다.
마지막 단계는 새 데이터의 오류가 예상과 동일하도록 제어하는 것입니다. 항상 이동이 있으며(실제 오류는 항상 예상보다 낮음) 수용 가능한 이동이 무엇인지 결정해야 하지만 이는 이 기사의 주제가 아닙니다.
예측을 위한 REST API
훈련과 예측을 명확하게 분리하는 것이 유용한 이유입니다. 기능 엔지니어링 방법과 모델 매개변수를 저장했다면 이러한 요소를 사용하여 간단한 REST API를 구축할 수 있습니다.
여기서 핵심은 API 시작 시 모델과 매개변수를 로드하는 것입니다. 일단 실행되고 메모리에 저장되면 각 API 호출은 기능 엔지니어링 계산과 ML 알고리즘의 "예측" 방법을 트리거합니다. 둘 다 일반적으로 실시간 응답을 보장할 만큼 충분히 빠릅니다.
API는 예측할 고유한 예 또는 여러 가지 다른 예(일괄 예측)를 허용하도록 설계할 수 있습니다.
다음은 JSON 입력 및 JSON 출력(질문 입력, 답변 출력)을 사용하여 이 원칙을 구현하는 최소 Python/Flask 코드입니다.
app = Flask(__name__) @app.route('/api/makecalc/', methods=['POST']) def makecalc(): """ Function run at each API call No need to re-load the model """ # reads the received json jsonfile = request.get_json() res = dict() for key in jsonfile.keys(): # calculates and predicts res[key] = model.predict(doTheCalculation(key)) # returns a json file return jsonify(res) if __name__ == '__main__': # Model is loaded when the API is launched model = pickle.load(open('modelfile', 'rb')) app.run(debug=True)
API는 새 데이터에서 예측하는 데 사용할 수 있지만 모델 학습에는 사용하지 않는 것이 좋습니다. 사용할 수는 있지만 이는 모델 훈련 코드를 복잡하게 만들고 메모리 리소스 측면에서 더 까다로울 수 있습니다.

구현 예 - 자전거 공유
Kaggle 데이터 세트인 자전거 공유를 예로 들어 보겠습니다. 우리가 자전거의 유지 관리, 물류 및 기타 비즈니스 측면을 더 잘 관리하기 위해 매일 자전거 대여 횟수를 예측하려는 자전거 공유 회사라고 가정해 보겠습니다.
렌탈은 주로 기상 조건에 달려 있으므로 일기 예보를 통해 회사는 렌탈 피크가 언제인지 더 잘 알 수 있고 요즘에는 유지 보수를 피하려고 할 수 있습니다.
먼저 모델을 훈련시키고 Jupyter 노트북에서 볼 수 있는 피클 객체로 저장합니다.
모델 교육 및 성능은 여기에서 다루지 않으며 전체 프로세스를 이해하기 위한 예시일 뿐입니다.
그런 다음 각 API 호출에서 수행될 데이터 변환을 작성합니다.
import numpy as np import pandas as pd from datetime import date def doTheCalculation(data): data['dayofyear']=(data['dteday']- data['dteday'].apply(lambda x: date(x.year,1,1)) .astype('datetime64[ns]')).apply(lambda x: x.days) X = np.array(data[['instant','season','yr','holiday','weekday','workingday', 'weathersit','temp','atemp','hum','windspeed','dayofyear']]) return X
이것은 월과 정확한 일을 모두 포함하는 변수(연도 중 일)의 계산일 뿐입니다. 또한 열을 선택하고 각각의 순서를 유지해야 합니다.
그런 다음 Flask로 REST API를 작성해야 합니다.
from flask import Flask, request, redirect, url_for, flash, jsonify from features_calculation import doTheCalculation import json, pickle import pandas as pd import numpy as np app = Flask(__name__) @app.route('/api/makecalc/', methods=['POST']) def makecalc(): """ Function run at each API call """ jsonfile = request.get_json() data = pd.read_json(json.dumps(jsonfile),orient='index',convert_dates=['dteday']) print(data) res = dict() ypred = model.predict(doTheCalculation(data)) for i in range(len(ypred)): res[i] = ypred[i] return jsonify(res) if __name__ == '__main__': modelfile = 'modelfile.pickle' model = pickle.load(open(modelfile, 'rb')) print("loaded OK") app.run(debug=True)
이 프로그램을 실행하면 기본적으로 포트 5000에서 API를 제공합니다.
로컬에서 요청을 테스트하는 경우 여전히 Python을 사용합니다.
import requests, json url = '[http://127.0.0.1:5000/api/makecalc/](http://127.0.0.1:5000/api/makecalc/)' text = json.dumps({"0":{"instant":1,"dteday":"2011-01-01T00:00:00.000Z","season":1,"yr":0,"mnth":1,"holiday":0,"weekday":6,"workingday":0,"weathersit":2,"temp":0.344167,"atemp":0.363625,"hum":0.805833,"windspeed":0.160446}, "1":{"instant":2,"dteday":"2011-01-02T00:00:00.000Z","season":1,"yr":0,"mnth":1,"holiday":0,"weekday":3,"workingday":0,"weathersit":2,"temp":0.363478,"atemp":0.353739,"hum":0.696087,"windspeed":0.248539}, "2":{"instant":3,"dteday":"2011-01-03T00:00:00.000Z","season":1,"yr":0,"mnth":1,"holiday":0,"weekday":1,"workingday":1,"weathersit":1,"temp":0.196364,"atemp":0.189405,"hum":0.437273,"windspeed":0.248309}})
요청에는 모델에 제공된 모든 정보가 포함됩니다. 따라서 우리 모델은 지정된 날짜에 대한 자전거 대여 예측으로 응답합니다(여기에는 세 가지가 있습니다).
headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'} r = requests.post(url, data=text, headers=headers) print(r,r.text) <Response [200]> { "0": 1063, "1": 1028, "2": 1399 }
그게 다야! 이 서비스는 유지 관리 계획 또는 사용자가 자전거 교통, 수요 및 대여 자전거 가용성을 인식하기 위해 모든 회사의 응용 프로그램에서 쉽게 사용할 수 있습니다.
함께 모아서
많은 기계 학습 시스템, 특히 PoC의 주요 결함은 훈련과 예측을 혼합하는 것입니다.
신중하게 분리하면 Python/Flask를 사용하여 상당히 낮은 개발 비용과 노력으로 MVP에 대한 실시간 예측을 매우 쉽게 수행할 수 있습니다. 특히 많은 PoC의 경우 초기에 Scikit-learn, Tensorflow, 또는 다른 Python 기계 학습 라이브러리.
그러나 이것은 모든 응용 프로그램, 특히 기능 엔지니어링이 많은 응용 프로그램 또는 각 호출에서 최신 데이터를 사용할 수 있어야 하는 가장 가까운 일치 항목을 검색하는 응용 프로그램에 대해 실현 가능하지 않을 수 있습니다.
어쨌든 영화에 대한 질문에 답하기 위해 계속해서 영화를 봐야 합니까? 머신 러닝에도 동일한 규칙이 적용됩니다!